@in-the-loop-labs/pair-review 1.1.0 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@in-the-loop-labs/pair-review",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Your AI-powered code review partner - Close the feedback loop with AI coding agents",
5
5
  "main": "src/server.js",
6
6
  "bin": {
package/public/css/pr.css CHANGED
@@ -5658,7 +5658,15 @@ body:not([data-theme="dark"]) .theme-icon-light {
5658
5658
  color: var(--color-text-tertiary);
5659
5659
  font-size: 0.75rem;
5660
5660
  max-width: var(--toolbar-branch-max-width);
5661
- overflow: hidden;
5661
+ padding: 2px 6px;
5662
+ background-color: var(--color-bg-tertiary);
5663
+ border-radius: var(--radius-sm);
5664
+ transition: all var(--transition-fast);
5665
+ }
5666
+
5667
+ .toolbar-branch:hover {
5668
+ background-color: var(--color-bg-secondary);
5669
+ color: var(--color-text-secondary);
5662
5670
  }
5663
5671
 
5664
5672
  .toolbar-branch svg {
@@ -5672,6 +5680,36 @@ body:not([data-theme="dark"]) .theme-icon-light {
5672
5680
  text-overflow: ellipsis;
5673
5681
  }
5674
5682
 
5683
+ /* Shared copy button styles for toolbar (branch + commit) */
5684
+ .toolbar-copy-btn {
5685
+ display: inline-flex;
5686
+ align-items: center;
5687
+ justify-content: center;
5688
+ background: none;
5689
+ border: none;
5690
+ padding: 2px;
5691
+ cursor: pointer;
5692
+ color: var(--color-text-tertiary);
5693
+ border-radius: var(--radius-xs);
5694
+ transition: all var(--transition-fast);
5695
+ opacity: 0;
5696
+ }
5697
+
5698
+ .toolbar-branch:hover .toolbar-copy-btn,
5699
+ .toolbar-commit:hover .toolbar-copy-btn {
5700
+ opacity: 1;
5701
+ }
5702
+
5703
+ .toolbar-copy-btn:hover {
5704
+ background-color: var(--color-bg-primary);
5705
+ color: var(--color-accent-primary);
5706
+ }
5707
+
5708
+ .toolbar-copy-btn.copied {
5709
+ color: var(--color-success);
5710
+ opacity: 1;
5711
+ }
5712
+
5675
5713
  .toolbar-stat {
5676
5714
  font-family: var(--font-mono);
5677
5715
  font-size: 0.7rem;
@@ -5710,7 +5748,6 @@ body:not([data-theme="dark"]) .theme-icon-light {
5710
5748
  padding: 2px 6px;
5711
5749
  background-color: var(--color-bg-tertiary);
5712
5750
  border-radius: var(--radius-sm);
5713
- cursor: pointer;
5714
5751
  transition: all var(--transition-fast);
5715
5752
  }
5716
5753
 
@@ -5724,29 +5761,6 @@ body:not([data-theme="dark"]) .theme-icon-light {
5724
5761
  flex-shrink: 0;
5725
5762
  }
5726
5763
 
5727
- .toolbar-commit-copy {
5728
- display: inline-flex;
5729
- align-items: center;
5730
- justify-content: center;
5731
- background: none;
5732
- border: none;
5733
- padding: 2px;
5734
- cursor: pointer;
5735
- color: var(--color-text-tertiary);
5736
- border-radius: var(--radius-xs);
5737
- transition: all var(--transition-fast);
5738
- opacity: 0;
5739
- }
5740
-
5741
- .toolbar-commit:hover .toolbar-commit-copy {
5742
- opacity: 1;
5743
- }
5744
-
5745
- .toolbar-commit-copy:hover {
5746
- background-color: var(--color-bg-primary);
5747
- color: var(--color-accent-primary);
5748
- }
5749
-
5750
5764
  /* Pending Draft Indicator in Toolbar */
5751
5765
  .pending-draft-indicator {
5752
5766
  display: inline-flex;
@@ -1329,19 +1329,59 @@ class LocalManager {
1329
1329
  pathText.title = fullPath;
1330
1330
  }
1331
1331
 
1332
- // Update branch name
1332
+ // Update branch name (header badge)
1333
1333
  const branchText = document.getElementById('local-branch-text');
1334
1334
  if (branchText) {
1335
1335
  branchText.textContent = reviewData.branch || 'unknown';
1336
1336
  }
1337
1337
 
1338
- // Update commit SHA
1338
+ // Update branch name (toolbar) and wire up copy button
1339
+ const branchName = document.getElementById('pr-branch-name');
1340
+ if (branchName) {
1341
+ branchName.textContent = reviewData.branch || 'unknown';
1342
+ }
1343
+
1344
+ const branchCopy = document.getElementById('pr-branch-copy');
1345
+ if (branchCopy && !branchCopy.hasAttribute('data-listener-added')) {
1346
+ branchCopy.setAttribute('data-listener-added', 'true');
1347
+ branchCopy.addEventListener('click', async (e) => {
1348
+ e.stopPropagation();
1349
+ const branch = branchName ? branchName.textContent : '';
1350
+ if (!branch || branch === '--' || branch === 'unknown') return;
1351
+ try {
1352
+ await navigator.clipboard.writeText(branch);
1353
+ branchCopy.classList.add('copied');
1354
+ setTimeout(() => branchCopy.classList.remove('copied'), 2000);
1355
+ } catch (err) {
1356
+ console.error('Failed to copy branch name:', err);
1357
+ }
1358
+ });
1359
+ }
1360
+
1361
+ // Update commit SHA and wire up copy button
1339
1362
  const commitSha = document.getElementById('pr-commit-sha');
1340
1363
  if (commitSha && reviewData.localHeadSha) {
1341
1364
  commitSha.textContent = reviewData.localHeadSha.substring(0, 7);
1342
1365
  commitSha.dataset.fullSha = reviewData.localHeadSha;
1343
1366
  }
1344
1367
 
1368
+ const commitCopy = document.getElementById('pr-commit-copy');
1369
+ if (commitCopy && !commitCopy.hasAttribute('data-listener-added')) {
1370
+ commitCopy.setAttribute('data-listener-added', 'true');
1371
+ commitCopy.addEventListener('click', async (e) => {
1372
+ e.stopPropagation();
1373
+ const fullSha = commitSha ? commitSha.dataset.fullSha : '';
1374
+ if (!fullSha) return;
1375
+ try {
1376
+ await navigator.clipboard.writeText(fullSha);
1377
+ commitCopy.classList.add('copied');
1378
+ setTimeout(() => commitCopy.classList.remove('copied'), 2000);
1379
+ } catch (err) {
1380
+ console.error('Failed to copy SHA:', err);
1381
+ }
1382
+ });
1383
+ }
1384
+
1345
1385
  // Update settings link visibility and href
1346
1386
  const settingsLink = document.getElementById('settings-link');
1347
1387
  if (settingsLink) {
@@ -150,6 +150,38 @@ class DiffRenderer {
150
150
  );
151
151
  }
152
152
 
153
+ /**
154
+ * Workaround for highlight.js Markdown grammar treating mid-word underscores
155
+ * as emphasis/strong markers.
156
+ *
157
+ * In Markdown, `_text_` is italic and `__text__` is bold, but only when the
158
+ * underscores are at word boundaries. highlight.js doesn't enforce this, so
159
+ * identifiers like `update_policy` get incorrectly highlighted:
160
+ * update_policy -> update<span class="hljs-emphasis">_policy</span>
161
+ * snake_case_var -> snake<span class="hljs-emphasis">_case_</span>var
162
+ *
163
+ * This method detects emphasis/strong spans that are preceded by a word
164
+ * character (letter, digit, or underscore) and strips the span wrapper,
165
+ * restoring the original text.
166
+ * @param {string} html - HTML output from highlight.js
167
+ * @returns {string} Corrected HTML
168
+ */
169
+ static fixMarkdownHighlighting(html) {
170
+ // Strip hljs-emphasis spans preceded by a word character (mid-word underscore)
171
+ // e.g., update<span class="hljs-emphasis">_policy</span> -> update_policy
172
+ html = html.replace(
173
+ /(\w)<span class="hljs-emphasis">(_[^<]*)<\/span>/g,
174
+ '$1$2'
175
+ );
176
+ // Strip hljs-strong spans preceded by a word character (mid-word double underscore)
177
+ // e.g., mid<span class="hljs-strong">__word__</span>bold -> mid__word__bold
178
+ html = html.replace(
179
+ /(\w)<span class="hljs-strong">(__[^<]*)<\/span>/g,
180
+ '$1$2'
181
+ );
182
+ return html;
183
+ }
184
+
153
185
  /**
154
186
  * Escape HTML characters
155
187
  * @param {string} text - Text to escape
@@ -304,6 +336,11 @@ class DiffRenderer {
304
336
  html = DiffRenderer.fixRubyHighlighting(html);
305
337
  }
306
338
 
339
+ // Workaround: highlight.js Markdown grammar treats mid-word underscores as emphasis
340
+ if (language === 'markdown') {
341
+ html = DiffRenderer.fixMarkdownHighlighting(html);
342
+ }
343
+
307
344
  contentCell.innerHTML = html;
308
345
  } catch (e) {
309
346
  // If highlighting fails, fall back to plain text
package/public/js/pr.js CHANGED
@@ -520,12 +520,30 @@ class PRManager {
520
520
  // Update meta info - show only head branch, full info in tooltip
521
521
  const branchName = document.getElementById('pr-branch-name');
522
522
  const branchContainer = document.getElementById('pr-branch');
523
+ const branchCopy = document.getElementById('pr-branch-copy');
523
524
  if (branchName) {
524
525
  branchName.textContent = pr.head_branch;
525
526
  // Set tooltip with full branch info (base <- head, showing merge direction)
526
527
  if (branchContainer) {
527
528
  branchContainer.title = `${pr.base_branch} <- ${pr.head_branch}`;
528
529
  }
530
+
531
+ if (branchCopy && !branchCopy.hasAttribute('data-listener-added')) {
532
+ branchCopy.setAttribute('data-listener-added', 'true');
533
+ branchCopy.addEventListener('click', async (e) => {
534
+ e.stopPropagation();
535
+ const branch = branchName.textContent;
536
+ if (!branch || branch === '--') return;
537
+ try {
538
+ await navigator.clipboard.writeText(branch);
539
+ // Visual feedback
540
+ branchCopy.classList.add('copied');
541
+ setTimeout(() => branchCopy.classList.remove('copied'), 2000);
542
+ } catch (err) {
543
+ console.error('Failed to copy branch name:', err);
544
+ }
545
+ });
546
+ }
529
547
  }
530
548
 
531
549
  const additions = document.getElementById('pr-additions');
package/public/local.html CHANGED
@@ -264,16 +264,29 @@
264
264
  </svg>
265
265
  </button>
266
266
  <div class="toolbar-meta" id="toolbar-meta">
267
+ <span class="toolbar-branch" id="pr-branch">
268
+ <svg viewBox="0 0 16 16" fill="currentColor" width="12" height="12">
269
+ <path d="M11.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122V6A2.5 2.5 0 0110 8.5H6a1 1 0 00-1 1v1.128a2.251 2.251 0 11-1.5 0V5.372a2.25 2.25 0 111.5 0v1.836A2.492 2.492 0 016 7h4a1 1 0 001-1v-.628A2.25 2.25 0 019.5 3.25zM4.25 12a.75.75 0 100 1.5.75.75 0 000-1.5zM3.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0z"/>
270
+ </svg>
271
+ <span id="pr-branch-name">--</span>
272
+ <button type="button" class="toolbar-branch-copy toolbar-copy-btn" id="pr-branch-copy" title="Copy branch name" aria-label="Copy branch name">
273
+ <svg viewBox="0 0 16 16" fill="currentColor" width="10" height="10">
274
+ <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path>
275
+ <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
276
+ </svg>
277
+ </button>
278
+ </span>
279
+ <span class="toolbar-separator"></span>
267
280
  <span class="toolbar-stat toolbar-stat-additions" id="pr-additions">+0</span>
268
281
  <span class="toolbar-stat toolbar-stat-deletions" id="pr-deletions">-0</span>
269
282
  <span class="toolbar-files" id="pr-files-count">0 files</span>
270
283
  <span class="toolbar-separator"></span>
271
- <span class="toolbar-commit" id="pr-commit" title="Click to copy full SHA">
284
+ <span class="toolbar-commit" id="pr-commit" title="Commit SHA">
272
285
  <svg viewBox="0 0 16 16" fill="currentColor" width="12" height="12">
273
286
  <path d="M11.93 8.5a4.002 4.002 0 0 1-7.86 0H.75a.75.75 0 0 1 0-1.5h3.32a4.002 4.002 0 0 1 7.86 0h3.32a.75.75 0 0 1 0 1.5Zm-1.43-.75a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"/>
274
287
  </svg>
275
288
  <span id="pr-commit-sha">HEAD</span>
276
- <button type="button" class="toolbar-commit-copy" id="pr-commit-copy" title="Copy full SHA" aria-label="Copy full SHA">
289
+ <button type="button" class="toolbar-commit-copy toolbar-copy-btn" id="pr-commit-copy" title="Copy full SHA" aria-label="Copy full SHA">
277
290
  <svg viewBox="0 0 16 16" fill="currentColor" width="10" height="10">
278
291
  <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path>
279
292
  <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
package/public/pr.html CHANGED
@@ -147,18 +147,24 @@
147
147
  <path d="M11.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122V6A2.5 2.5 0 0110 8.5H6a1 1 0 00-1 1v1.128a2.251 2.251 0 11-1.5 0V5.372a2.25 2.25 0 111.5 0v1.836A2.492 2.492 0 016 7h4a1 1 0 001-1v-.628A2.25 2.25 0 019.5 3.25zM4.25 12a.75.75 0 100 1.5.75.75 0 000-1.5zM3.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0z"/>
148
148
  </svg>
149
149
  <span id="pr-branch-name">--</span>
150
+ <button type="button" class="toolbar-branch-copy toolbar-copy-btn" id="pr-branch-copy" title="Copy branch name" aria-label="Copy branch name">
151
+ <svg viewBox="0 0 16 16" fill="currentColor" width="10" height="10">
152
+ <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path>
153
+ <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
154
+ </svg>
155
+ </button>
150
156
  </span>
151
157
  <span class="toolbar-separator"></span>
152
158
  <span class="toolbar-stat toolbar-stat-additions" id="pr-additions">+0</span>
153
159
  <span class="toolbar-stat toolbar-stat-deletions" id="pr-deletions">-0</span>
154
160
  <span class="toolbar-files" id="pr-files-count">0 files</span>
155
161
  <span class="toolbar-separator"></span>
156
- <span class="toolbar-commit" id="pr-commit" title="Click to copy full SHA">
162
+ <span class="toolbar-commit" id="pr-commit" title="Commit SHA">
157
163
  <svg viewBox="0 0 16 16" fill="currentColor" width="12" height="12">
158
164
  <path d="M11.93 8.5a4.002 4.002 0 0 1-7.86 0H.75a.75.75 0 0 1 0-1.5h3.32a4.002 4.002 0 0 1 7.86 0h3.32a.75.75 0 0 1 0 1.5Zm-1.43-.75a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"/>
159
165
  </svg>
160
166
  <span id="pr-commit-sha">--</span>
161
- <button type="button" class="toolbar-commit-copy" id="pr-commit-copy" title="Copy full SHA" aria-label="Copy full SHA">
167
+ <button type="button" class="toolbar-commit-copy toolbar-copy-btn" id="pr-commit-copy" title="Copy full SHA" aria-label="Copy full SHA">
162
168
  <svg viewBox="0 0 16 16" fill="currentColor" width="10" height="10">
163
169
  <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path>
164
170
  <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>