@mrsf/markdown-it-mrsf 0.2.0 → 0.4.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.
@@ -1,9 +1,9 @@
1
1
  /**
2
- * MRSF markdown-it plugin — renderer rules.
2
+ * MRSF markdown-it plugin — renderer rules (overlay gutter architecture).
3
3
  *
4
- * Adds custom renderer rules for MRSF tokens:
5
- * - mrsf_badge: renders badge + tooltip HTML (gutter)
6
- * - mrsf_highlight_open/close: renders <mark> wrappers with inline tooltips
4
+ * Adds a single custom renderer rule:
5
+ * - mrsf_data_script: renders a <script type="application/mrsf+json">
6
+ * containing serialized comment data for the MrsfController.
7
7
  */
8
8
  /**
9
9
  * Install MRSF renderer rules on a markdown-it instance.
package/dist/style.css CHANGED
@@ -1,10 +1,15 @@
1
1
  /*
2
- * Sidemark — markdown-it plugin default styles
2
+ * Sidemark — MRSF plugin default styles (overlay gutter architecture).
3
3
  *
4
- * Include via: import "@mrsf/markdown-it-mrsf/style.css"
5
- * or <link rel="stylesheet" href=".../@mrsf/markdown-it-mrsf/dist/style.css">
4
+ * Include via: import "@mrsf/plugin-shared/style.css"
5
+ * or <link rel="stylesheet" href=".../@mrsf/plugin-shared/dist/style.css">
6
6
  *
7
7
  * Customise with CSS custom properties (--mrsf-*).
8
+ *
9
+ * Layout: The controller wraps the rendered markdown in an overlay root
10
+ * with position:relative, and creates absolute-positioned gutter columns
11
+ * on the left and/or right. The plugins only add data-mrsf-line
12
+ * attributes — no visual DOM injection.
8
13
  */
9
14
 
10
15
  /* ── Custom property defaults ────────────────────────────── */
@@ -22,6 +27,7 @@
22
27
  --mrsf-severity-high: #e74c3c;
23
28
  --mrsf-severity-medium: #f39c12;
24
29
  --mrsf-severity-low: #3498db;
30
+ --mrsf-gutter-width: 36px;
25
31
  --mrsf-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
26
32
  }
27
33
 
@@ -33,29 +39,36 @@
33
39
  }
34
40
  }
35
41
 
36
- /* ── Gutter container (left gutter mode) ────────────────── */
42
+ /* ── Overlay root (created by controller) ────────────────── */
37
43
 
38
- .mrsf-gutter-container {
39
- --mrsf-gutter-width: 44px;
44
+ .mrsf-overlay-root {
40
45
  position: relative;
41
- padding-left: var(--mrsf-gutter-width);
42
46
  }
43
47
 
44
- /* In left gutter mode, line-highlight must be static so the badge's
45
- position: absolute resolves against the gutter container — not the
46
- individual line element, which may be deeply nested inside lists. */
47
- .mrsf-gutter-container .mrsf-line-highlight {
48
- position: static;
48
+ .mrsf-gutter {
49
+ position: absolute;
50
+ top: 0;
51
+ bottom: 0;
52
+ width: var(--mrsf-gutter-width);
53
+ pointer-events: none;
54
+ z-index: 10;
49
55
  }
50
56
 
51
- /* ── Line highlight ─────────────────────────────────────── */
57
+ .mrsf-gutter-left {
58
+ left: calc(-1 * var(--mrsf-gutter-width) - 8px);
59
+ }
60
+
61
+ .mrsf-gutter-right {
62
+ right: calc(-1 * var(--mrsf-gutter-width) - 8px);
63
+ }
64
+
65
+ /* ── Line highlight (CSS-only tinting for commented lines) ── */
52
66
 
53
67
  .mrsf-line-highlight {
54
68
  border-left: 3px solid var(--mrsf-accent);
55
69
  padding-left: 8px;
56
70
  background: rgba(55, 148, 255, 0.06);
57
71
  border-radius: 2px;
58
- position: relative;
59
72
  transition: background 0.15s ease;
60
73
  }
61
74
 
@@ -63,6 +76,18 @@
63
76
  background: rgba(55, 148, 255, 0.12);
64
77
  }
65
78
 
79
+ /* ── Gutter items (badges & add buttons, positioned by JS) ── */
80
+
81
+ .mrsf-gutter-item {
82
+ position: absolute;
83
+ left: 0;
84
+ right: 0;
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ pointer-events: auto;
89
+ }
90
+
66
91
  /* ── Badge ──────────────────────────────────────────────── */
67
92
 
68
93
  .mrsf-badge {
@@ -74,11 +99,9 @@
74
99
  line-height: 1;
75
100
  padding: 2px 6px;
76
101
  border-radius: 10px;
77
- cursor: default;
102
+ cursor: pointer;
78
103
  user-select: none;
79
104
  white-space: nowrap;
80
- vertical-align: middle;
81
- margin-left: 6px;
82
105
 
83
106
  color: var(--mrsf-badge-fg);
84
107
  background: var(--mrsf-badge-bg);
@@ -100,56 +123,36 @@
100
123
  border-left-color: var(--mrsf-severity-medium);
101
124
  }
102
125
 
103
- /* ── Tooltip container ──────────────────────────────────── */
126
+ /* ── Add button (in gutter) ─────────────────────────────── */
104
127
 
105
- .mrsf-tooltip-anchor {
106
- position: relative;
107
- display: inline-block;
108
- vertical-align: baseline;
109
- }
110
-
111
- /* Gutter position: right (default) — float the badge to the right */
112
- .mrsf-tooltip-anchor.mrsf-gutter-right {
113
- float: right;
114
- margin-left: 8px;
115
- }
116
-
117
- .mrsf-tooltip-anchor.mrsf-gutter-right .mrsf-badge {
118
- margin-left: 0;
119
- }
120
-
121
- /* Gutter position: tight — badge inline immediately before text */
122
- .mrsf-tooltip-anchor.mrsf-gutter-tight .mrsf-badge {
123
- margin-right: 6px;
124
- margin-left: 0;
125
- }
126
-
127
- /* Gutter position: left — badge in the left margin gutter.
128
- Positioned against the gutter container (not the line element). */
129
- .mrsf-tooltip-anchor.mrsf-gutter-left {
130
- position: absolute;
131
- left: 4px;
128
+ .mrsf-gutter-add {
129
+ opacity: 0;
130
+ pointer-events: none;
131
+ border: 1px solid var(--mrsf-tooltip-border);
132
+ background: var(--mrsf-tooltip-bg);
133
+ color: var(--mrsf-tooltip-fg);
134
+ border-radius: 50%;
135
+ width: 20px;
136
+ height: 20px;
137
+ font-size: 12px;
138
+ line-height: 18px;
139
+ text-align: center;
140
+ cursor: pointer;
141
+ transition: opacity 0.12s ease;
132
142
  }
133
143
 
134
- .mrsf-tooltip-anchor.mrsf-gutter-left .mrsf-badge {
135
- margin-left: 0;
144
+ /* Show add button on line hover (detected by controller via data attr) */
145
+ [data-mrsf-line]:hover ~ .mrsf-gutter .mrsf-gutter-add,
146
+ .mrsf-gutter-item:hover .mrsf-gutter-add {
147
+ opacity: 1;
148
+ pointer-events: auto;
136
149
  }
137
150
 
138
- /* Tooltip for left-gutter badges */
139
- .mrsf-tooltip-anchor.mrsf-gutter-left > .mrsf-tooltip {
140
- left: 0;
141
- right: auto;
142
- }
143
-
144
- /* Inline highlight tooltip anchor */
145
- .mrsf-inline-anchor {
146
- /* inherit inline-block from .mrsf-tooltip-anchor */
147
- }
151
+ /* ── Tooltip (positioned by JS, appended to gutter item) ── */
148
152
 
149
153
  .mrsf-tooltip {
150
154
  display: none;
151
155
  position: absolute;
152
- left: 0;
153
156
  top: 100%;
154
157
  z-index: 1000;
155
158
  min-width: 300px;
@@ -170,20 +173,19 @@
170
173
  color: var(--mrsf-tooltip-fg);
171
174
  }
172
175
 
173
- /* Right-aligned gutter: anchor tooltip to the right edge */
174
- .mrsf-tooltip-anchor.mrsf-gutter-right > .mrsf-tooltip {
175
- left: auto;
176
- right: 0;
176
+ /* Left gutter: tooltip opens to the right */
177
+ .mrsf-gutter-left .mrsf-tooltip {
178
+ left: 0;
179
+ right: auto;
177
180
  }
178
181
 
179
- /* Inline tooltip: smaller and anchored to the left of the highlight */
180
- .mrsf-inline-tooltip {
181
- min-width: 260px;
182
+ /* Right gutter: tooltip opens to the left */
183
+ .mrsf-gutter-right .mrsf-tooltip {
184
+ left: auto;
185
+ right: 0;
182
186
  }
183
187
 
184
- /* Show tooltip on hover or focus-within (keyboard accessible) */
185
- .mrsf-tooltip-anchor:hover > .mrsf-tooltip,
186
- .mrsf-tooltip-anchor:focus-within > .mrsf-tooltip {
188
+ .mrsf-tooltip.mrsf-tooltip-visible {
187
189
  display: block;
188
190
  animation: mrsf-fade-in 0.15s ease;
189
191
  }
@@ -194,11 +196,8 @@
194
196
  }
195
197
 
196
198
  /* ── Thread / Comment ───────────────────────────────────── */
197
- /* All inner elements use <span> for valid HTML inside <p>/<h> elements,
198
- with display: block to maintain block layout. */
199
199
 
200
200
  .mrsf-thread {
201
- display: block;
202
201
  padding: 4px 0;
203
202
  }
204
203
 
@@ -209,7 +208,6 @@
209
208
  }
210
209
 
211
210
  .mrsf-comment {
212
- display: block;
213
211
  padding: 4px 0;
214
212
  }
215
213
 
@@ -221,7 +219,6 @@
221
219
  /* ── Replies ────────────────────────────────────────────── */
222
220
 
223
221
  .mrsf-replies {
224
- display: block;
225
222
  margin-left: 16px;
226
223
  padding-left: 8px;
227
224
  border-left: 2px solid var(--mrsf-tooltip-border);
@@ -291,7 +288,6 @@
291
288
  /* ── Comment body ───────────────────────────────────────── */
292
289
 
293
290
  .mrsf-comment-body {
294
- display: block;
295
291
  white-space: pre-wrap;
296
292
  word-break: break-word;
297
293
  }
@@ -299,30 +295,92 @@
299
295
  /* ── Selected text quote in tooltip ─────────────────────── */
300
296
 
301
297
  .mrsf-selected-text {
302
- display: block;
303
298
  font-family: monospace;
304
299
  font-size: 0.85em;
305
300
  background: rgba(127, 127, 127, 0.1);
306
301
  border-left: 3px solid rgba(127, 127, 127, 0.3);
307
- padding: 4px 8px;
308
302
  margin: 4px 0;
309
303
  border-radius: 2px;
304
+ }
305
+
306
+ .mrsf-selected-text-summary {
307
+ padding: 4px 8px;
308
+ cursor: pointer;
309
+ overflow: hidden;
310
+ text-overflow: ellipsis;
311
+ white-space: nowrap;
312
+ display: block;
313
+ list-style: none;
314
+ color: var(--mrsf-fg, inherit);
315
+ opacity: 0.7;
316
+ }
317
+
318
+ .mrsf-selected-text-summary::-webkit-details-marker {
319
+ display: none;
320
+ }
321
+
322
+ .mrsf-selected-text-summary::before {
323
+ content: "▶ ";
324
+ font-size: 0.7em;
325
+ vertical-align: middle;
326
+ margin-right: 2px;
327
+ }
328
+
329
+ .mrsf-selected-text[open] > .mrsf-selected-text-summary {
330
+ display: none;
331
+ }
332
+
333
+ .mrsf-selected-text-full {
334
+ display: block;
335
+ padding: 4px 8px;
310
336
  white-space: pre-wrap;
311
337
  word-break: break-word;
312
338
  }
313
339
 
314
- /* ── Inline text highlight ──────────────────────────────── */
340
+ /* ── Inline text highlight (overlay positioned by JS) ───── */
341
+
342
+ .mrsf-highlight-overlay {
343
+ position: absolute;
344
+ background: var(--mrsf-highlight-bg);
345
+ border-bottom: 2px solid var(--mrsf-highlight-border);
346
+ border-radius: 2px;
347
+ pointer-events: none;
348
+ transition: background 0.15s ease;
349
+ }
350
+
351
+ /* ── Inline comment text highlight (<mark> by controller) ── */
315
352
 
316
- .mrsf-highlight {
353
+ .mrsf-inline-highlight {
317
354
  background: var(--mrsf-highlight-bg);
318
355
  border-bottom: 2px solid var(--mrsf-highlight-border);
319
356
  border-radius: 2px;
320
- padding: 0 1px;
357
+ cursor: pointer;
321
358
  transition: background 0.15s ease;
322
359
  }
323
360
 
324
- .mrsf-highlight:hover {
325
- background: rgba(255, 213, 79, 0.45);
361
+ .mrsf-inline-highlight:hover {
362
+ background: rgba(255, 213, 79, 0.4);
363
+ }
364
+
365
+ /* Inline tooltip (appended to document.body, positioned by JS) */
366
+ .mrsf-inline-tooltip {
367
+ position: fixed;
368
+ z-index: 1100;
369
+ min-width: 300px;
370
+ max-width: 480px;
371
+ max-height: 400px;
372
+ overflow-y: auto;
373
+ padding: 8px;
374
+ border-radius: 6px;
375
+ background: var(--mrsf-tooltip-bg);
376
+ border: 1px solid var(--mrsf-tooltip-border);
377
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
378
+ font-family: var(--mrsf-font-family);
379
+ font-size: 13px;
380
+ line-height: 1.5;
381
+ color: var(--mrsf-tooltip-fg);
382
+ white-space: normal;
383
+ animation: mrsf-fade-in 0.15s ease;
326
384
  }
327
385
 
328
386
  /* ── Interactive action buttons ─────────────────────────── */
@@ -339,6 +397,15 @@
339
397
  display: flex;
340
398
  }
341
399
 
400
+ .mrsf-tooltip-actions {
401
+ display: flex;
402
+ justify-content: flex-end;
403
+ gap: 6px;
404
+ margin-top: 8px;
405
+ padding-top: 6px;
406
+ border-top: 1px solid var(--mrsf-tooltip-border);
407
+ }
408
+
342
409
  .mrsf-action-btn {
343
410
  font-size: 11px;
344
411
  padding: 2px 8px;
@@ -351,6 +418,63 @@
351
418
  transition: background 0.15s ease;
352
419
  }
353
420
 
421
+ .mrsf-action-btn.mrsf-action-danger {
422
+ color: #d13438;
423
+ border-color: rgba(209, 52, 56, 0.7);
424
+ }
425
+
354
426
  .mrsf-action-btn:hover {
355
427
  background: rgba(127, 127, 127, 0.2);
356
428
  }
429
+
430
+ /* ── Floating "Add comment" button (selection-based) ────── */
431
+
432
+ /* ── Orphaned comments section (bottom of container) ────── */
433
+
434
+ .mrsf-orphaned-section {
435
+ margin-top: 24px;
436
+ padding-top: 16px;
437
+ border-top: 2px dashed var(--mrsf-tooltip-border);
438
+ }
439
+
440
+ .mrsf-orphaned-heading {
441
+ font-family: var(--mrsf-font-family);
442
+ font-size: 12px;
443
+ font-weight: 600;
444
+ text-transform: uppercase;
445
+ letter-spacing: 0.5px;
446
+ color: #999;
447
+ margin-bottom: 8px;
448
+ }
449
+
450
+ .mrsf-orphaned-thread {
451
+ padding: 8px;
452
+ margin-bottom: 6px;
453
+ border-radius: 6px;
454
+ border: 1px solid var(--mrsf-tooltip-border);
455
+ background: rgba(127, 127, 127, 0.06);
456
+ opacity: 0.7;
457
+ font-family: var(--mrsf-font-family);
458
+ font-size: 13px;
459
+ line-height: 1.5;
460
+ color: var(--mrsf-tooltip-fg);
461
+ }
462
+
463
+ .mrsf-add-inline-button {
464
+ position: absolute;
465
+ z-index: 1200;
466
+ display: none;
467
+ font-size: 12px;
468
+ padding: 6px 10px;
469
+ border-radius: 6px;
470
+ border: 1px solid var(--mrsf-tooltip-border);
471
+ background: var(--mrsf-tooltip-bg);
472
+ color: var(--mrsf-tooltip-fg);
473
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
474
+ cursor: pointer;
475
+ font-family: var(--mrsf-font-family);
476
+ }
477
+
478
+ .mrsf-add-inline-button:hover {
479
+ background: rgba(127, 127, 127, 0.2);
480
+ }
package/dist/types.d.ts CHANGED
@@ -55,6 +55,12 @@ export interface MrsfPluginOptions {
55
55
  * Default: true.
56
56
  */
57
57
  inlineHighlights?: boolean;
58
+ /**
59
+ * Whether to add a `mrsf-line-highlight` CSS class on block elements
60
+ * that have comments. Provides a subtle visual tint on commented lines.
61
+ * Default: false.
62
+ */
63
+ lineHighlight?: boolean;
58
64
  /** Color scheme hint (default: 'auto'). */
59
65
  theme?: "light" | "dark" | "auto";
60
66
  /** Working directory for sidecar discovery (default: process.cwd()). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrsf/markdown-it-mrsf",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "markdown-it plugin for rendering Sidemark/MRSF (Markdown Review Sidecar Format) review comments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",