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