@vscode/markdown-editor 0.0.2-3 → 0.0.2-30

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.
Files changed (34) hide show
  1. package/dist/_observables/observableInternal/index.d.ts +1 -1
  2. package/dist/_observables/observableInternal/logging/consoleObservableLogger.d.ts +1 -1
  3. package/dist/_observables/observableInternal/logging/debugger/devToolsLogger.d.ts +1 -1
  4. package/dist/_observables/observableInternal/logging/logging.d.ts +1 -1
  5. package/dist/_observables/observableInternal/reactions/{autorun.d.ts → createEffect.d.ts} +11 -3
  6. package/dist/config-Dvgk17FF.js +282 -0
  7. package/dist/config-Dvgk17FF.js.map +1 -0
  8. package/dist/config.d.ts +10 -0
  9. package/dist/config.js +6 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/index.d.ts +1049 -54
  12. package/dist/index.js +4196 -1870
  13. package/dist/index.js.map +1 -1
  14. package/dist/markdown-editor.css +1 -0
  15. package/dist/observables.js +45 -43
  16. package/dist/observables.js.map +1 -1
  17. package/dist/{runOnChange-C00UIwqQ.js → runOnChange-e7FtCqOQ.js} +115 -111
  18. package/dist/runOnChange-e7FtCqOQ.js.map +1 -0
  19. package/dist/stringEdit-DzLs4E1d.js +177 -0
  20. package/dist/stringEdit-DzLs4E1d.js.map +1 -0
  21. package/dist/web-editors.d.ts +125 -0
  22. package/dist/web-editors.js +5169 -0
  23. package/dist/web-editors.js.map +1 -0
  24. package/package.json +46 -9
  25. package/src/contrib/comments/commentInput.css +150 -0
  26. package/src/contrib/comments/comments.css +129 -0
  27. package/src/contrib/commentsVscode/vscodeCommentWidgetV2.css +171 -0
  28. package/src/view/editor.css +493 -20
  29. package/src/view/themes/default.css +11 -3
  30. package/src/view/themes/github.css +12 -8
  31. package/src/view/themes/vscode-default.css +355 -0
  32. package/src/view/themes/vscode-github.css +349 -0
  33. package/dist/runOnChange-C00UIwqQ.js.map +0 -1
  34. /package/dist/_observables/observableInternal/reactions/{autorunImpl.d.ts → createEffectImpl.d.ts} +0 -0
@@ -1,3 +1,5 @@
1
+ @import '@vscode/codicons/dist/codicon.css';
2
+
1
3
  /*
2
4
  * Base editor styles — ABSOLUTE MINIMUM.
3
5
  *
@@ -12,14 +14,32 @@
12
14
  * theme files (`themes/default.css`, `themes/github.css`) applied via the
13
15
  * `classNames` editor option; those selectors only ever match inside their
14
16
  * own theme class and never style the global scope.
17
+ *
18
+ * NO `--vscode-*` variables may be referenced here. This base file must stay
19
+ * theme-agnostic and know nothing about VS Code. Where a value needs to vary
20
+ * per theme, expose a local `--md-*` custom property WITH a sensible literal
21
+ * fallback (e.g. `var(--md-cursor-background, #000)`) and let a theme file set
22
+ * it. Only the `themes/vscode-*.css` themes are permitted to read `--vscode-*`
23
+ * variables and map them onto these `--md-*` properties.
15
24
  */
16
25
 
17
26
  .md-editor {
27
+ display: flow-root;
18
28
  outline: none;
19
29
  /* The editor paints its own cursor (`.md-cursor`); hide the native caret. */
20
30
  caret-color: transparent;
21
31
  }
22
32
 
33
+ /*
34
+ * The transient empty paragraph — the blank line conjured by pressing Enter at
35
+ * the end of a paragraph (see `PendingParagraph` in the model). It is not part
36
+ * of the document (Markdown has no empty-paragraph node); it holds a single
37
+ * `<br>` so it occupies one line's height, and the caret is painted over it.
38
+ */
39
+ .md-pending-paragraph {
40
+ min-height: 1em;
41
+ }
42
+
23
43
  /*
24
44
  * Inner content container. Holds the rendered document and the cursor/selection
25
45
  * overlays, which position themselves relative to this box, so it is the
@@ -28,27 +48,87 @@
28
48
  * `.md-editor`.
29
49
  */
30
50
  .md-editor-content {
51
+ --md-editor-content-inline-start-padding: 48px;
52
+ --md-readonly-toggle-width: 58px;
53
+ --md-readonly-toggle-height: 32px;
54
+ /* Leaves 16px of optical separation beyond the active block's 8px outset glow. */
55
+ --md-readonly-toggle-gap: 24px;
56
+ --md-readonly-toggle-inset: 4px;
57
+ --md-editor-content-inline-end-padding: var(--md-editor-content-inline-start-padding);
31
58
  position: relative;
32
59
  margin-inline: auto;
33
- padding: 48px;
60
+ padding-block: 0;
61
+ padding-inline: var(--md-editor-content-inline-start-padding) var(--md-editor-content-inline-end-padding);
62
+ }
63
+
64
+ .md-editor-content-with-readonly-toggle {
65
+ --md-editor-content-inline-end-padding: calc(var(--md-readonly-toggle-width) + var(--md-readonly-toggle-gap) + var(--md-readonly-toggle-inset));
66
+ }
67
+
68
+ .md-editor-content-with-readonly-toggle>.md-document :is(.md-heading, .md-paragraph) {
69
+ overflow-wrap: anywhere;
34
70
  }
35
71
 
36
72
  .md-block-active {
37
- background: #f8f8f8;
73
+ background: var(--md-block-active-background, #f8f8f8);
38
74
  border-radius: 4px;
39
- box-shadow: 0 0 0 8px #f8f8f8;
75
+ box-shadow: 0 0 0 8px var(--md-block-active-background, #f8f8f8);
40
76
  }
41
77
 
42
78
  /*
43
- * A rendered (inactive) link opens on a plain click, so it keeps the anchor's
44
- * pointer cursor. Once its block is active the link is editable source and a
45
- * plain click places the caret (Ctrl/Cmd+click still opens), so it shows the
46
- * normal editing cursor like the surrounding text.
79
+ * The whole-empty-document case. Markdown has no empty-paragraph node, so a
80
+ * document with no content parses to a single empty paragraph (see
81
+ * `_ensureBlocks` in the parser) which renders as a childless `<p>` of zero
82
+ * height. Give it one line's height so the editor presents an intentional,
83
+ * clickable empty editing surface — and so typing the first character causes no
84
+ * layout shift (a filled line is also one `lh` tall).
85
+ */
86
+ .md-paragraph:empty {
87
+ min-height: 1lh;
88
+ }
89
+
90
+ /*
91
+ * ...and never paint the active-block card over that zero-content line: with no
92
+ * text to size it, the card's background + 8px box-shadow glow would show up as
93
+ * a stray gray bar. The two extra classes outrank the base `.md-block-active`
94
+ * rule above in every theme (themes only remap `--md-block-active-background`).
95
+ */
96
+ .md-paragraph:empty.md-block-active {
97
+ background: transparent;
98
+ box-shadow: none;
99
+ }
100
+
101
+ /*
102
+ * Cursor mirrors the same open affordance as the underline below: the anchor's
103
+ * pointer cursor appears exactly when a click would open the link. An inactive
104
+ * (rendered) link opens on a plain click, so it keeps the browser's default
105
+ * anchor pointer. Once its block is active a plain click places the caret, so
106
+ * the link shows the normal editing cursor — except while Ctrl/Cmd is held
107
+ * (`.md-mod-down`), when a click opens it and the pointer returns.
47
108
  */
48
109
  .md-block-active a {
49
110
  cursor: inherit;
50
111
  }
51
112
 
113
+ .md-editor.md-mod-down .md-block-active a[href] {
114
+ cursor: pointer;
115
+ }
116
+
117
+ /*
118
+ * Link underline is an "open affordance": show it only while a click on the
119
+ * link right now would actually open it. An inactive (rendered) link opens on
120
+ * a plain click, so hovering it underlines. An active link's plain click edits
121
+ * its source — it only opens with Ctrl/Cmd — so it underlines on hover only
122
+ * while that modifier is held (`.md-mod-down`, set live by the view).
123
+ */
124
+ .md-editor a[href]:hover {
125
+ text-decoration: underline;
126
+ }
127
+
128
+ .md-editor:not(.md-mod-down) .md-block-active a[href]:hover {
129
+ text-decoration: none;
130
+ }
131
+
52
132
  .md-fence-spacer {
53
133
  visibility: hidden;
54
134
  font-family: 'Cascadia Code', 'Fira Code', monospace;
@@ -84,6 +164,33 @@
84
164
  white-space: pre-wrap;
85
165
  }
86
166
 
167
+ /*
168
+ * An unhandled block: a construct the parser does not model (setext heading,
169
+ * frontmatter fence, an extension token). Its raw source is shown verbatim,
170
+ * styled like a code block but visibly flagged as "not understood" by a dashed
171
+ * warning border, so the content is preserved and editable rather than silently
172
+ * dropped.
173
+ *
174
+ * The wrapper is the non-scrolling box (border + block spacing); the inner
175
+ * `.md-unhandled-scroll` <pre> is the horizontal scroller.
176
+ */
177
+ .md-unhandled-block {
178
+ margin: 0.5em 0;
179
+ border: 1px dashed #d0a000;
180
+ border-radius: 4px;
181
+ }
182
+
183
+ /*
184
+ * Inner scroller. Beats the per-theme `.md-theme-* .md-code-block` box rules
185
+ * (same class count) via the extra `pre` type selector: no margin/border of its
186
+ * own (those live on the wrapper).
187
+ */
188
+ pre.md-unhandled-scroll.md-code-block {
189
+ margin: 0;
190
+ border: 0;
191
+ border-radius: 4px;
192
+ }
193
+
87
194
  /*
88
195
  * Visible whitespace indicators, shown only in the active/source view. The real
89
196
  * whitespace character stays in the DOM (so source ↔ DOM mapping and selection
@@ -183,15 +290,61 @@
183
290
  }
184
291
 
185
292
  /*
186
- * Glue (table cell pipes, the task `[x] ` source, source padding) keeps its
187
- * inline footprint when hidden so column widths and the checkbox gutter stay
188
- * identical between active and inactive states.
293
+ * Glue normally keeps its inline footprint when hidden so source padding and
294
+ * widget gutters stay identical between active and inactive states. Hidden
295
+ * table-cell glue is the exception below: leaving it in inline flow lets its
296
+ * invisible spaces wrap around long cell content.
189
297
  */
190
298
  .md-glue-hidden {
191
299
  display: inline;
192
300
  visibility: hidden;
193
301
  }
194
302
 
303
+ /*
304
+ * Inactive table pipes stay in the DOM/source tree, but leave layout and
305
+ * hit-testing entirely. Keeping an invisible rect either in the content flow or
306
+ * over the cell padding can create phantom lines or steal clicks from visible
307
+ * text. Hidden source offsets therefore collapse to the neighboring semantic
308
+ * seam, matching other display-none markers. Visible pipes retain the per-theme
309
+ * active/source layout.
310
+ */
311
+ .md-table td>.md-glue-tableCellGlue.md-glue-hidden {
312
+ display: none;
313
+ }
314
+
315
+ /*
316
+ * Active table: take each cell's TRAILING structural glue (the source space
317
+ * after the cell text, and — via the per-theme `right: 0` rule — the last
318
+ * column's closing `|`) out of the cell's inline flow. Left in flow, that glue
319
+ * wraps below long cell content (the same wrapping the hidden-glue note above
320
+ * describes), which makes the cell two lines tall: the browser's default
321
+ * `vertical-align: middle` then re-centres the other cells' single-line content
322
+ * in Y, their runs merge into one oversized VisualLine, and the caret — sized
323
+ * directly from that line box — grows far past the line height while the
324
+ * visible pipes drift apart row-to-row. Positioning the trailing glue
325
+ * absolutely removes it from wrapping flow while keeping its real client rects
326
+ * at the static (content-line) position, so caret placement, hit-testing,
327
+ * source mapping and injectivity are unchanged. `top`/`bottom: auto` keep it on
328
+ * that content line rather than the cell's top edge. This mirrors the inactive
329
+ * `display: none` above; the leading `| ` glue deliberately stays in flow (a
330
+ * relative glyph shift, per theme) so first-text X is preserved.
331
+ *
332
+ * `:not(:first-child)` restricts this to a genuine trailing glue: a non-empty
333
+ * cell emits leading + trailing glue, but an EMPTY cell parses to a single glue
334
+ * node that is simultaneously first and last child. That lone node is the
335
+ * cell's leading pipe, so it must stay in flow like every other leading pipe;
336
+ * excluding it keeps empty cells identical to their previous (base) behaviour.
337
+ */
338
+ .md-table.md-block-active td {
339
+ position: relative;
340
+ }
341
+
342
+ .md-table.md-block-active td>.md-glue-tableCellGlue:last-child:not(:first-child) {
343
+ position: absolute;
344
+ top: auto;
345
+ bottom: auto;
346
+ }
347
+
195
348
  /*
196
349
  * Inter-block glue: the run of blank lines between two top-level blocks. It is
197
350
  * mounted as the last inline child of the block that precedes it, so it sits at
@@ -228,15 +381,6 @@
228
381
  visibility: hidden;
229
382
  }
230
383
 
231
- /*
232
- * Table cell-glue pipes (`| `) keep their inline footprint when hidden so the
233
- * column widths stay identical active and inactive.
234
- */
235
- .md-marker-tableCellGlue.md-marker-hidden {
236
- display: inline;
237
- visibility: hidden;
238
- }
239
-
240
384
  /*
241
385
  * The code-block fences (```lang / ```) each sit on their own source line. When
242
386
  * hidden they keep their vertical footprint (visibility hidden, not display
@@ -271,6 +415,48 @@
271
415
  height: 16px;
272
416
  }
273
417
 
418
+ /*
419
+ * A wide table scrolls horizontally inside its wrapper (the block box) instead
420
+ * of overflowing the page and scrolling the editor's fixed left gutter away.
421
+ * The wrapper is the scroll viewport the selection/caret clipping measures (see
422
+ * `BlockViewNode.scrollElement` / `blockViewportClip`); the inner `<table>`
423
+ * keeps `width: auto` (theme-defined) so it sizes to its content and overflows.
424
+ *
425
+ * `width: fit-content` keeps the wrapper hugging the table's intrinsic width, so
426
+ * a narrow table — and the active-block glow redirected onto the wrapper below —
427
+ * stays as wide as the table (unchanged from before this wrapper existed).
428
+ * `max-width: 100%` caps it at the content column, past which the table
429
+ * overflows and scrolls locally. This is the standard responsive-table pattern
430
+ * (cf. GitHub's own `width: max-content; max-width: 100%`).
431
+ */
432
+ .md-table-wrapper {
433
+ overflow-x: auto;
434
+ width: fit-content;
435
+ max-width: 100%;
436
+ }
437
+
438
+ /*
439
+ * The active-block highlight is an *outset* glow (`box-shadow: 0 0 0 8px`).
440
+ * Making the wrapper a scroll box (`overflow-x: auto`, which also forces
441
+ * `overflow-y: auto`) clips descendant paint to its padding box, so the glow on
442
+ * the inner active `<table>` would be cut off (the table has no horizontal
443
+ * margin to give the shadow room). Render the generic active chrome on the
444
+ * wrapper instead — a scroll box's own shadow is never clipped by its own
445
+ * overflow, exactly like a code block carries the glow on its own scroller —
446
+ * and drop it from the table, which keeps `md-block-active` purely for the
447
+ * per-theme source-pipe styling.
448
+ */
449
+ .md-table-wrapper:has(> .md-table.md-block-active) {
450
+ background: var(--md-block-active-background, #f8f8f8);
451
+ border-radius: 4px;
452
+ box-shadow: 0 0 0 8px var(--md-block-active-background, #f8f8f8);
453
+ }
454
+
455
+ .md-table.md-block-active {
456
+ background: none;
457
+ box-shadow: none;
458
+ }
459
+
274
460
  .md-selection-layer {
275
461
  position: absolute;
276
462
  top: 0;
@@ -285,6 +471,54 @@
285
471
  fill: rgba(59, 130, 246, 0.25);
286
472
  }
287
473
 
474
+ /*
475
+ * Gutter markers (source-control style change indicators). The layer fills the
476
+ * content box; each marker is an absolutely-positioned bar pinned to the left
477
+ * gutter (inside `.md-editor-content`'s 48px padding). The view sets only
478
+ * `top`/`height`; horizontal placement, width and color live here so themes can
479
+ * tune them without touching layout. Like the other overlays it never eats
480
+ * pointer events.
481
+ */
482
+ .md-gutter-layer {
483
+ position: absolute;
484
+ top: 0;
485
+ left: 0;
486
+ width: 100%;
487
+ height: 100%;
488
+ pointer-events: none;
489
+ overflow: visible;
490
+ }
491
+
492
+ .md-gutter-marker {
493
+ position: absolute;
494
+ left: var(--md-gutter-marker-left, 18px);
495
+ width: var(--md-gutter-marker-width, 3px);
496
+ border-radius: 2px;
497
+ }
498
+
499
+ .md-gutter-marker-added {
500
+ background: var(--md-gutter-added, #2ea043);
501
+ }
502
+
503
+ .md-gutter-marker-modified {
504
+ background: var(--md-gutter-modified, #0969da);
505
+ }
506
+
507
+ /*
508
+ * A deletion has no lines to span, so it is drawn as a downward-pointing
509
+ * triangle centered on the seam where the removed text used to be (the top of
510
+ * the line that now follows it), matching the git deleted-lines affordance.
511
+ */
512
+ .md-gutter-marker-deleted {
513
+ width: 0;
514
+ height: 0;
515
+ border-radius: 0;
516
+ border-left: var(--md-gutter-marker-width, 3px) solid var(--md-gutter-deleted, #cf222e);
517
+ border-top: 4px solid transparent;
518
+ border-bottom: 4px solid transparent;
519
+ transform: translateY(-4px);
520
+ }
521
+
288
522
  /* Source markers occupy the gutter so toggling them never shifts content. */
289
523
  .md-heading {
290
524
  position: relative;
@@ -437,6 +671,16 @@
437
671
  white-space: pre;
438
672
  }
439
673
 
674
+ /*
675
+ * A continuation-line indent inside a paragraph is source-only padding. When
676
+ * inactive, the preceding soft-break newline already collapses to the single
677
+ * rendered space Markdown requires; retaining the hidden indent would add the
678
+ * tab/space run's width on top of it.
679
+ */
680
+ .md-paragraph>.md-glue-indent.md-glue-hidden {
681
+ display: none;
682
+ }
683
+
440
684
  /*
441
685
  * A loose list item's later block (its second paragraph etc.) owns the source
442
686
  * continuation indent that precedes it as its `leadingTrivia`. Like a nested
@@ -540,11 +784,43 @@
540
784
  .md-cursor {
541
785
  position: absolute;
542
786
  width: 2px;
543
- background: #000;
787
+ background: var(--md-cursor-background, #000);
544
788
  pointer-events: none;
789
+ }
790
+
791
+ /*
792
+ * The painted caret is only shown while the editor is genuinely focused — focus
793
+ * rests inside it and its window is focused, mirrored onto the root as
794
+ * `.md-focused`. When unfocused, hide the caret element but keep its layout box
795
+ * (so caret geometry, selection and comment anchoring are unchanged) and stop
796
+ * the blink. Adding the animation on focus restarts it from 0% (a solid caret).
797
+ */
798
+ .md-editor:not(.md-focused) .md-cursor {
799
+ visibility: hidden;
800
+ }
801
+
802
+ .md-editor.md-focused .md-cursor {
545
803
  animation: md-cursor-blink 1s step-end infinite;
546
804
  }
547
805
 
806
+ /*
807
+ * Read-only mode retains the logical caret for selection and comment anchoring.
808
+ * Hide only its painted element so unlocking can restore it in place.
809
+ */
810
+ .md-editor.md-readonly .md-cursor {
811
+ visibility: hidden;
812
+ }
813
+
814
+ .md-editor.md-readonly-editing-attempt {
815
+ animation: md-readonly-editing-attempt 300ms ease-out;
816
+ }
817
+
818
+ @keyframes md-readonly-editing-attempt {
819
+ 50% {
820
+ box-shadow: inset 0 0 0 2px var(--md-readonly-shine-glow, rgba(255, 255, 255, 0.58));
821
+ }
822
+ }
823
+
548
824
  @keyframes md-cursor-blink {
549
825
 
550
826
  0%,
@@ -555,4 +831,201 @@
555
831
  50% {
556
832
  opacity: 0;
557
833
  }
834
+ }
835
+
836
+ /*
837
+ * Edit / read-only lock toggle.
838
+ *
839
+ * The asymmetric content padding reserves a real rail for the control:
840
+ * button width + gap + edge inset. The zero-height sticky host spans the
841
+ * document column and that rail, keeping the button beside (never over) the
842
+ * rendered document as it scrolls. Colors use local `--md-readonly-*` custom
843
+ * properties with literal fallbacks so this base file stays theme-agnostic
844
+ * (themes may override them).
845
+ */
846
+ .md-readonly-toggle-host {
847
+ position: sticky;
848
+ top: 0;
849
+ width: calc(100% + var(--md-editor-content-inline-end-padding));
850
+ height: 0;
851
+ z-index: 10;
852
+ pointer-events: none;
853
+ }
854
+
855
+ .md-readonly-toggle {
856
+ position: absolute;
857
+ top: 4px;
858
+ right: var(--md-readonly-toggle-inset);
859
+ pointer-events: auto;
860
+ display: inline-grid;
861
+ grid-template-columns: repeat(2, 24px);
862
+ align-items: center;
863
+ justify-items: center;
864
+ gap: 2px;
865
+ box-sizing: border-box;
866
+ width: var(--md-readonly-toggle-width);
867
+ height: var(--md-readonly-toggle-height);
868
+ padding: 3px;
869
+ overflow: hidden;
870
+ direction: ltr;
871
+ appearance: none;
872
+ border-radius: 999px;
873
+ border: 1px solid var(--md-readonly-border, #b8b8b8);
874
+ background: var(--md-readonly-background, #f3f3f3);
875
+ color: var(--md-readonly-foreground, #444444);
876
+ font-size: 16px;
877
+ line-height: 1;
878
+ cursor: pointer;
879
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
880
+ transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
881
+ }
882
+
883
+ /*
884
+ * Below this width there is not enough document column for the side rail to be
885
+ * useful. Give the host its own row and stop it from sticking, so neither long
886
+ * unbreakable content nor later content scrolled through the viewport can ever
887
+ * pass underneath the button.
888
+ */
889
+ .md-editor-narrow .md-readonly-toggle-host {
890
+ position: relative;
891
+ height: calc(var(--md-readonly-toggle-height) + var(--md-readonly-toggle-inset) + var(--md-readonly-toggle-inset));
892
+ }
893
+
894
+ .md-readonly-toggle::after {
895
+ content: '';
896
+ position: absolute;
897
+ z-index: 2;
898
+ top: -8px;
899
+ bottom: -8px;
900
+ left: -30px;
901
+ width: 24px;
902
+ background: linear-gradient(90deg,
903
+ transparent,
904
+ var(--md-readonly-shine-edge, rgba(255, 255, 255, 0.16)) 24%,
905
+ var(--md-readonly-shine, #ffffff) 50%,
906
+ var(--md-readonly-shine-edge, rgba(255, 255, 255, 0.16)) 76%,
907
+ transparent);
908
+ box-shadow: 0 0 8px 2px var(--md-readonly-shine-glow, rgba(255, 255, 255, 0.58));
909
+ opacity: 0;
910
+ pointer-events: none;
911
+ transform: skewX(-20deg);
912
+ }
913
+
914
+ .md-readonly-toggle.md-readonly-toggle-shine::after {
915
+ animation: md-readonly-toggle-shine 2s linear;
916
+ will-change: transform, opacity;
917
+ }
918
+
919
+ @keyframes md-readonly-toggle-shine {
920
+ 0% {
921
+ opacity: 0;
922
+ transform: translateX(0) skewX(-20deg);
923
+ }
924
+
925
+ 12%,
926
+ 88% {
927
+ opacity: 1;
928
+ }
929
+
930
+ 100% {
931
+ opacity: 0;
932
+ transform: translateX(122px) skewX(-20deg);
933
+ }
934
+ }
935
+
936
+ .md-readonly-toggle:hover {
937
+ border-color: var(--md-readonly-border-hover, #8d8d8d);
938
+ background: var(--md-readonly-background-hover, #e9e9e9);
939
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.1);
940
+ }
941
+
942
+ .md-readonly-toggle:focus-visible {
943
+ outline: 2px solid var(--md-readonly-accent, #4c8bf5);
944
+ outline-offset: 1px;
945
+ }
946
+
947
+ .md-readonly-toggle .md-readonly-toggle-indicator {
948
+ position: absolute;
949
+ top: 50%;
950
+ left: 3px;
951
+ width: 24px;
952
+ height: 24px;
953
+ border-radius: 50%;
954
+ background: var(--md-readonly-accent, #4c8bf5);
955
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.25);
956
+ transform: translate(26px, -50%);
957
+ transition: background-color 0.12s ease, transform 0.16s ease;
958
+ }
959
+
960
+ .md-readonly-toggle .md-readonly-toggle-icon {
961
+ position: relative;
962
+ z-index: 1;
963
+ display: block;
964
+ width: 16px;
965
+ height: 16px;
966
+ color: var(--md-readonly-foreground, #444444);
967
+ opacity: 0.62;
968
+ pointer-events: none;
969
+ transition: color 0.12s ease, opacity 0.12s ease;
970
+ }
971
+
972
+ .md-readonly-toggle:not(.md-readonly-toggle-locked) .md-readonly-toggle-icon-editing,
973
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-locked {
974
+ color: var(--md-readonly-accent-foreground, #ffffff);
975
+ opacity: 1;
976
+ }
977
+
978
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-indicator {
979
+ transform: translate(0, -50%);
980
+ }
981
+
982
+ @media (prefers-reduced-motion: reduce) {
983
+
984
+ .md-editor.md-readonly-editing-attempt,
985
+ .md-readonly-toggle,
986
+ .md-readonly-toggle .md-readonly-toggle-indicator,
987
+ .md-readonly-toggle .md-readonly-toggle-icon,
988
+ .md-readonly-toggle.md-readonly-toggle-shine::after {
989
+ animation: none;
990
+ transition: none;
991
+ }
992
+ }
993
+
994
+ @media (forced-colors: active) {
995
+ .md-readonly-toggle {
996
+ forced-color-adjust: none;
997
+ border-color: ButtonText;
998
+ background: ButtonFace;
999
+ color: ButtonText;
1000
+ box-shadow: none;
1001
+ }
1002
+
1003
+ .md-readonly-toggle::after {
1004
+ display: none;
1005
+ }
1006
+
1007
+ .md-readonly-toggle:hover {
1008
+ border-color: Highlight;
1009
+ background: ButtonFace;
1010
+ box-shadow: none;
1011
+ }
1012
+
1013
+ .md-readonly-toggle:focus-visible {
1014
+ outline-color: Highlight;
1015
+ }
1016
+
1017
+ .md-readonly-toggle .md-readonly-toggle-indicator {
1018
+ background: Highlight;
1019
+ box-shadow: none;
1020
+ }
1021
+
1022
+ .md-readonly-toggle .md-readonly-toggle-icon {
1023
+ color: ButtonText;
1024
+ opacity: 1;
1025
+ }
1026
+
1027
+ .md-readonly-toggle:not(.md-readonly-toggle-locked) .md-readonly-toggle-icon-editing,
1028
+ .md-readonly-toggle.md-readonly-toggle-locked .md-readonly-toggle-icon-locked {
1029
+ color: HighlightText;
1030
+ }
558
1031
  }
@@ -121,9 +121,14 @@
121
121
  --md-list-indent-step: 24px;
122
122
  }
123
123
 
124
+ .md-theme-default .md-table-wrapper {
125
+ /* Block spacing lives on the wrapper (the scroll/BFC box) so it collapses
126
+ with siblings as before; the inner table has no margin of its own. */
127
+ margin: 0.5em 0;
128
+ }
129
+
124
130
  .md-theme-default .md-table {
125
131
  border-collapse: collapse;
126
- margin: 0.5em 0;
127
132
  width: auto;
128
133
  }
129
134
 
@@ -201,6 +206,9 @@
201
206
  * box) so the right outline is a straight line. Absolute removes it from flow,
202
207
  * but it is the trailing node so no text shifts; the leading pipe still fixes
203
208
  * first-text X and the row stays one line tall, keeping the compare invariants.
209
+ * `top: auto` keeps the pipe on the content line (the shared editor.css rule
210
+ * also takes trailing glue out of flow); the previous `top: 0` floated it to
211
+ * the cell's top edge, misaligning it with the leading pipes on wrapping rows.
204
212
  */
205
213
  .md-theme-default .md-table.md-block-active td:last-child {
206
214
  position: relative;
@@ -209,7 +217,7 @@
209
217
  .md-theme-default .md-table.md-block-active td:last-child>.md-glue-tableCellGlue:last-child {
210
218
  position: absolute;
211
219
  right: 0;
212
- top: 0;
220
+ top: auto;
213
221
  }
214
222
 
215
223
  /*
@@ -220,7 +228,7 @@
220
228
  .md-theme-default .md-table.md-block-active .md-table-delimiter-row td:last-child>.md-marker-tableDelimiterClose {
221
229
  position: absolute;
222
230
  right: 0;
223
- top: 0;
231
+ top: auto;
224
232
  }
225
233
 
226
234
  .md-theme-default code {
@@ -99,10 +99,6 @@
99
99
  text-decoration: none;
100
100
  }
101
101
 
102
- .github-markdown-theme a:hover {
103
- text-decoration: underline;
104
- }
105
-
106
102
  /* GitHub uses a 600 weight for bold, not the browser default 700. */
107
103
  .github-markdown-theme strong {
108
104
  font-weight: 600;
@@ -201,10 +197,15 @@
201
197
  line-height: 1;
202
198
  }
203
199
 
204
- .github-markdown-theme .md-table {
205
- border-collapse: collapse;
200
+ .github-markdown-theme .md-table-wrapper {
201
+ /* Block spacing lives on the wrapper (the scroll/BFC box) so it collapses
202
+ with siblings as before; the inner table has no margin of its own. */
206
203
  margin-top: 0;
207
204
  margin-bottom: 16px;
205
+ }
206
+
207
+ .github-markdown-theme .md-table {
208
+ border-collapse: collapse;
208
209
  width: auto;
209
210
  }
210
211
 
@@ -284,6 +285,9 @@
284
285
  * box) so the right outline is a straight line. Absolute removes it from flow,
285
286
  * but it is the trailing node so no text shifts; the leading pipe still fixes
286
287
  * first-text X and the row stays one line tall, keeping the compare invariants.
288
+ * `top: auto` keeps the pipe on the content line (the shared editor.css rule
289
+ * also takes trailing glue out of flow); the previous `top: 0` floated it to
290
+ * the cell's top edge, misaligning it with the leading pipes on wrapping rows.
287
291
  */
288
292
  .github-markdown-theme .md-table.md-block-active td:last-child {
289
293
  position: relative;
@@ -292,7 +296,7 @@
292
296
  .github-markdown-theme .md-table.md-block-active td:last-child>.md-glue-tableCellGlue:last-child {
293
297
  position: absolute;
294
298
  right: 0;
295
- top: 0;
299
+ top: auto;
296
300
  }
297
301
 
298
302
  /*
@@ -303,5 +307,5 @@
303
307
  .github-markdown-theme .md-table.md-block-active .md-table-delimiter-row td:last-child>.md-marker-tableDelimiterClose {
304
308
  position: absolute;
305
309
  right: 0;
306
- top: 0;
310
+ top: auto;
307
311
  }