@helping-ai-workflow/md2doc 3.0.0 → 3.0.2

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/lib/md2doc.js CHANGED
@@ -1086,21 +1086,29 @@ ${itemsHtml}
1086
1086
  // [contentLeft-54, contentLeft-18] until spec §4.2's own numbers were
1087
1087
  // restored), clear of .sidebar-splitter — see the .content rule below.
1088
1088
  //
1089
- // GEOMETRY, AS MEASURED (S4 T1; the previous version of this comment
1090
- // claimed "an 8px gap" between the gutter and the table row grip, a number
1091
- // left over from the v2.11.0 pair position that v2.11.1 invalidated — the
1092
- // real gap was MINUS 6px, i.e. an overlap):
1089
+ // GEOMETRY, AS MEASURED (v2.12.0/S4 T1; the previous version of this
1090
+ // comment claimed "an 8px gap" between the gutter and the table row grip, a
1091
+ // number left over from the v2.11.0 pair position that v2.11.1
1092
+ // invalidated — the real gap was MINUS 6px, i.e. an overlap):
1093
1093
  // ⠿ [contentLeft-22, contentLeft-4] (--ed-gutter-btn wide)
1094
- // row grip [contentLeft, contentLeft+20] (--ed-te-grip-row-w wide)
1095
- // The grip used to be centred on the table's left border at
1096
- // [contentLeft-10, contentLeft+10], which overlapped the ⠿'s right 6px and
1097
- // — being position: fixed, z-index 7, on document.body — won the hit test
1098
- // there. spec §4.2 conflict 2's ruling (grip entirely inside the table)
1099
- // is landed in lib/editor/client.js's updateTableEdgeGrips(); the
1094
+ // row grip [contentLeft-10, contentLeft+10] (--ed-te-grip-row-w wide,
1095
+ // centred on the table's left border)
1096
+ // The grip straddling the table's left border overlapped the ⠿'s right 6px
1097
+ // and — being position: fixed, z-index 7, on document.body — won the hit
1098
+ // test there. v2.12.0/S4 T1's fix moved the grip entirely inside the table
1099
+ // instead (its left edge on the border), which fixed the overlap but
1100
+ // broke the row/column symmetry the user expected (the column grip still
1101
+ // straddles the table's TOP border) — reported as a v3.0.1 regression.
1102
+ // v3.0.1 fixes it at the source instead: the ⠿/+ pair itself moves
1103
+ // further LEFT by --ed-gutter-shift below, which removes the overlap
1104
+ // without moving the grip at all, so the grip can straddle the border
1105
+ // again (see updateTableEdgeGrips() in lib/editor/client.js). The
1100
1106
  // clearance that remains is exactly --ed-gutter-gap, because the ⠿'s right
1101
- // edge and the grip's left edge are both derived from it. The grip is kept
1102
- // off the first cell's TEXT by --ed-te-cell-pad-left below, not by the
1103
- // 14px default padding, which is narrower than the grip.
1107
+ // edge and the grip's left edge are both derived from it. The grip's
1108
+ // straddling half (10px) sits well inside the first cell's default 14px
1109
+ // left padding, so no extra edit-mode padding is needed any more — the
1110
+ // v2.10.1-era --ed-te-cell-pad-left token this comment used to describe is
1111
+ // gone.
1104
1112
  // (The padding was 48px until §4.2's hit-test conflict 1 was fixed; see the
1105
1113
  // .content rule in editModeLayoutCss below for why it is 56px now.)
1106
1114
  // S1 Task 5: the ordered-list ordinal is drawn by a CSS counter, and the
@@ -1156,12 +1164,14 @@ ${itemsHtml}
1156
1164
  further in, to spec §4.2's own [contentLeft-40, contentLeft-4] — the
1157
1165
  clearance is 16px at this padding rather than 2px. The padding stays at
1158
1166
  56px: nothing asks for the text column to move, and this measurement is
1159
- the one the §4.2 conflict-1 guard is written against.) The table row grip no
1160
- longer reaches this far left at all: §4.2 conflict 2 moved it inside the
1161
- table to [contentLeft, contentLeft+20] (S4 T1), so nothing but the gutter
1162
- pair itself occupies [contentLeft-40, contentLeft-4]. Guarded by the
1163
- elementFromPoint(splitter.right - 2, y) assertion §4.2 asks for, in
1164
- test/editor-client-runtime.test.js. */
1167
+ the one the §4.2 conflict-1 guard is written against.) v3.0.1 shifts the
1168
+ pair a further --ed-gutter-shift (10px) left, to [contentLeft-50,
1169
+ contentLeft-14], so the table row grip can straddle the table's own left
1170
+ border again instead of sitting inside it — see the --ed-gutter-shift
1171
+ comment above .ed-handle below. That still leaves 6px of clearance from
1172
+ splitterRight (contentLeft-56), so the conflict-1 guard still holds.
1173
+ Guarded by the elementFromPoint(splitter.right - 2, y) assertion §4.2
1174
+ asks for, in test/editor-client-runtime.test.js. */
1165
1175
  .content { padding-left: 56px; }
1166
1176
 
1167
1177
  /* S1: every block is one full-width row, whatever its type or depth. The
@@ -1231,38 +1241,41 @@ ${itemsHtml}
1231
1241
  [contentLeft-54, contentLeft-18], which with 56px of padding sits wholly
1232
1242
  inside the content column (2px clear of .sidebar-splitter's right edge —
1233
1243
  see the padding rule's own comment for the measurement), so + never
1234
- reaches a negative viewport x and never covers the splitter. The table
1235
- row grip is at [contentLeft, contentLeft+20] since §4.2 conflict 2
1236
- landed (S4 T1), so the clearance from the ⠿'s right edge is exactly
1237
- --ed-gutter-gap and cannot drift: both edges are derived from it. */
1244
+ reaches a negative viewport x and never covers the splitter. As of
1245
+ v3.0.1 the table row grip straddles the table's left border again
1246
+ (centred on it, [tableLeft-10, tableLeft+10] — see updateTableEdgeGrips()
1247
+ in lib/editor/client.js), and the pair itself has moved left by
1248
+ --ed-gutter-shift below so the clearance from the ⠿'s right edge is
1249
+ still exactly --ed-gutter-gap and cannot drift: both edges are derived
1250
+ from it. */
1238
1251
  /* Stated ONCE, as tokens, because §4.2's three numbers are not independent:
1239
1252
  the gutter is exactly two buttons wide plus the deliberate right-hand
1240
- breathing gap, and the hover zone below is exactly the gutter. Writing any
1241
- of them as a second literal is how the corridor comes back. */
1253
+ breathing gap, and the hover zone below is exactly the gutter plus
1254
+ whatever --ed-gutter-shift moved the pair by. Writing any of them as a
1255
+ second literal is how the corridor comes back. */
1242
1256
  :root {
1243
1257
  --ed-gutter-btn: 18px;
1244
1258
  --ed-gutter-gap: 4px;
1245
1259
  --ed-gutter-w: calc(var(--ed-gutter-btn) * 2 + var(--ed-gutter-gap));
1246
- /* spec §4.2 hit-test conflict 2, landed S4 T1. The table row grip now
1247
- sits ENTIRELY inside the table (its LEFT edge on the table's left
1248
- border — see updateTableEdgeGrips() in lib/editor/client.js), which
1249
- leaves the ⠿'s right edge and the grip's left edge exactly
1250
- --ed-gutter-gap apart: the 4px breathing gap §4.2 already keeps on the
1251
- right of the gutter pair IS the separation. Nothing new is written
1252
- down, so nothing new can drift.
1253
- The consequence is this token: the grip is 20px wide and the first
1254
- column's default padding is 14px, so an inset grip would sit on that
1255
- cell's TEXT — the v2.10.1 user-acceptance defect that got the first
1256
- attempt at this ruling reverted. The first column is padded past the
1257
- grip instead, by the grip's own width plus that same gap. */
1258
- --ed-te-cell-pad-left: calc(var(--ed-te-grip-row-w) + var(--ed-gutter-gap));
1259
1260
  }
1261
+ /* v3.0.1: the pair moves LEFT by --ed-gutter-shift so the table row grip
1262
+ can straddle the table's left border again (see updateTableEdgeGrips()
1263
+ in lib/editor/client.js) while still keeping --ed-gutter-gap between the
1264
+ ⠿'s right edge and the grip's left edge. Written as a token because the
1265
+ two rules below and the acceptance test all derive from it. Measured at
1266
+ 1400x900 (README.md, first table): pre-shift ⠿=[390,408] +=[372,390]
1267
+ tableLeft=412; a 10px shift lands ⠿=[380,398] +=[362,380], grip
1268
+ (straddling, 20px wide, centred on tableLeft) = [402,422], leaving
1269
+ exactly --ed-gutter-gap (4px) between the ⠿'s right edge (398) and the
1270
+ grip's left edge (402), and +'s left edge (362) stays well clear of 0. */
1271
+ :root { --ed-gutter-shift: 10px; }
1260
1272
  .ed-handle {
1261
- left: calc(-1 * (var(--ed-gutter-btn) + var(--ed-gutter-gap))); top: 0;
1273
+ left: calc(-1 * (var(--ed-gutter-btn) + var(--ed-gutter-gap) + var(--ed-gutter-shift)));
1274
+ top: 0;
1262
1275
  width: var(--ed-gutter-btn);
1263
1276
  }
1264
1277
  .ed-insert {
1265
- left: calc(-1 * var(--ed-gutter-w)); top: 0;
1278
+ left: calc(-1 * (var(--ed-gutter-w) + var(--ed-gutter-shift))); top: 0;
1266
1279
  width: var(--ed-gutter-btn);
1267
1280
  }
1268
1281
  /* v2.11.1: the gutter's HOVER ZONE, and it is the reason the pair could move
@@ -1291,9 +1304,17 @@ ${itemsHtml}
1291
1304
 
1292
1305
  One absolutely-positioned pseudo-element spanning the whole gutter for the
1293
1306
  block's whole height makes :hover continuously true from the text out
1294
- past the +, at every Y. Its width is the --ed-gutter-w token the pair's
1295
- own offsets are built from, so the two cannot drift apart — if they do,
1296
- the corridor comes straight back.
1307
+ past the +, at every Y. Its span is derived from the SAME two tokens the
1308
+ pair's own offsets are: --ed-gutter-w (the pair's own width, the gutter
1309
+ proper) plus --ed-gutter-shift (how far v3.0.1 moved the pair left to
1310
+ clear the straddling table row grip). Both edges therefore track the
1311
+ pair automatically — the zone's left edge is exactly the +'s left edge
1312
+ and its right edge is the block's, with no literal repeated anywhere —
1313
+ so the two cannot drift apart. If they ever do, the corridor comes
1314
+ straight back: v3.0.1 shifted the pair to [blockLeft-50, blockLeft-14]
1315
+ while this rule still read the un-shifted --ed-gutter-w alone, leaving
1316
+ it spanning [blockLeft-40, blockLeft] — 10px short on the left of the
1317
+ very buttons it exists to keep reachable.
1297
1318
  .ed-block is already position:relative, and position: absolute keeps
1298
1319
  this out of the li row's flex flow. It is deliberately NOT
1299
1320
  pointer-events: none: that would stop it being hit-tested, which is the
@@ -1305,18 +1326,8 @@ ${itemsHtml}
1305
1326
  literal.) */
1306
1327
  .ed-block::before {
1307
1328
  content: ""; position: absolute;
1308
- left: calc(-1 * var(--ed-gutter-w)); top: 0;
1309
- width: var(--ed-gutter-w); height: 100%;
1310
- }
1311
-
1312
- /* §4.2 conflict 2's other half: the row grip lives inside the first column
1313
- now, so that column's cells must be padded past it. EDIT MODE ONLY —
1314
- reader HTML and PDF output keep the shared 7px 14px and stay
1315
- byte-identical. Only the LEFT padding changes, and only on the first
1316
- cell of each row; every other cell is untouched. */
1317
- .ed-block[data-block-type="table"] th:first-child,
1318
- .ed-block[data-block-type="table"] td:first-child {
1319
- padding-left: var(--ed-te-cell-pad-left);
1329
+ left: calc(-1 * (var(--ed-gutter-w) + var(--ed-gutter-shift))); top: 0;
1330
+ width: calc(var(--ed-gutter-w) + var(--ed-gutter-shift)); height: 100%;
1320
1331
  }`;
1321
1332
 
1322
1333
  const html = `<!DOCTYPE html>
@@ -2174,6 +2185,17 @@ ${itemsHtml}
2174
2185
  }
2175
2186
  .ed-block:hover .ed-handle,
2176
2187
  .ed-handle:focus { opacity: 1; }
2188
+ /* v3.0.2: a table's row grip is a document.body child at z-index 7 that
2189
+ straddles the table's left border, and a table block's ⠿ sits at the
2190
+ header row's own Y — so a pointer travelling left toward the ⠿ crosses
2191
+ the grip, elementFromPoint stops returning the block, and :hover above
2192
+ goes false mid-approach. The grip cannot move (it must be a body child
2193
+ to stay put while the table scrolls), so lib/editor/client.js holds the
2194
+ gutter lit with this class for the duration instead. It does NOT
2195
+ restore :hover, so .ed-block:hover's own outline still blinks there —
2196
+ a recorded, unfixed residue. */
2197
+ .ed-block.ed-keep-lit .ed-handle,
2198
+ .ed-block.ed-keep-lit .ed-insert { opacity: 1; }
2177
2199
  .ed-handle:hover { background: rgba(0, 0, 0, 0.08); }
2178
2200
  /* The ⠿ handle's menu: 轉換成 › / 建立副本 / 刪除 / MD 原始碼 (spec §3.7),
2179
2201
  each led by a 16px currentColor icon (v2.12.0; drawn in
@@ -2196,7 +2218,11 @@ ${itemsHtml}
2196
2218
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
2197
2219
  }
2198
2220
  .ed-handle-menu-btn {
2199
- min-width: 132px; height: 26px; padding: 0 10px;
2221
+ /* v3.0.1: the icon sits FLUSH LEFT and the label sits one space-width
2222
+ after it (user request: 「符號靠左對齊,文字跟符號間距一個空格」).
2223
+ The right padding is untouched — it is what keeps the 轉換成 row's
2224
+ chevron off the panel edge. */
2225
+ min-width: 132px; height: 26px; padding: 0 10px 0 6px;
2200
2226
  border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 6px;
2201
2227
  background: rgba(255, 255, 255, 0.08); color: inherit;
2202
2228
  font: inherit; font-size: 12px; line-height: 1;
@@ -2207,8 +2233,10 @@ ${itemsHtml}
2207
2233
  width, so S2's one-left-edge / monotonic-top invariants are untouched.
2208
2234
  The submenu's own buttons carry this class and no icon; a lone text node
2209
2235
  is an anonymous flex item at flex-start, i.e. exactly where text-align
2210
- put it. */
2211
- display: flex; align-items: center; gap: 8px;
2236
+ put it.
2237
+ v3.0.1: gap dropped from 8px to 4px — one space-width at this 12px
2238
+ font size — now that every row (both menu levels) carries an icon. */
2239
+ display: flex; align-items: center; gap: 4px;
2212
2240
  }
2213
2241
  /* Notion's own sizing. The stroke colour is NOT set here on purpose: the
2214
2242
  markup carries stroke="currentColor" (lib/editor/client.js), so the icon
@@ -2216,8 +2244,20 @@ ${itemsHtml}
2216
2244
  retheme for free. A hex here would break that silently. (No backticks in
2217
2245
  this comment: it lives inside a JS template literal.)
2218
2246
  flex: 0 0 auto because a 16px-wide flex item next to a nowrap label
2219
- would otherwise be the thing that shrinks. */
2220
- .ed-menu-icon { flex: 0 0 auto; width: 16px; height: 16px; }
2247
+ would otherwise be the thing that shrinks.
2248
+ v3.0.1: the selector is ".ed-handle-menu-btn .ed-menu-icon", not the
2249
+ bare class — the gutter menu is appended INTO a ".ed-block"
2250
+ (lib/editor/client.js's blockEl.appendChild(gutterMenu)), which is a
2251
+ descendant of <main class="content">, and ".content svg" above
2252
+ carries "margin: 0 auto" at specificity (0,1,1) (one class, one
2253
+ type). The bare ".ed-menu-icon" is only (0,1,0) and LOSES that fight
2254
+ regardless of source order, so every icon picked up centering
2255
+ auto-margins instead of sitting flush left — measured on this branch
2256
+ as an icon offset that swung with label length (11px-40px) instead
2257
+ of a constant one. Scoping under ".ed-handle-menu-btn" raises this
2258
+ to (0,2,0), which wins on class count alone. (No backticks in this
2259
+ comment: it lives inside a JS template literal.) */
2260
+ .ed-handle-menu-btn .ed-menu-icon { flex: 0 0 auto; width: 16px; height: 16px; margin: 0; }
2221
2261
  /* The 轉換成 submenu carries BOTH classes, so it inherits every rule above
2222
2262
  and only overrides the horizontal offset. It is a CHILD of the menu, and
2223
2263
  the menu is itself position:absolute, so the menu's own padding box is
@@ -2361,18 +2401,23 @@ ${itemsHtml}
2361
2401
  affordance) with two real, adequately-sized (>=18x24px) click/drag
2362
2402
  targets. '.ed-te-grip-row' is a vertical 6-dot handle shown at the LEFT
2363
2403
  EDGE of the hovered row -- every row, the HEADER included (spec 3.10:
2364
- the header is draggable too), sitting ENTIRELY INSIDE the table with its
2365
- LEFT edge on the table's left border (spec 4.2 hit-test conflict 2,
2366
- landed in S4 T1). The two axes are therefore NOT mirror images any more:
2367
- '.ed-te-grip-col' still straddles the table's TOP border, because nothing
2368
- of the page's own chrome lives up there. The row axis cannot: MEASURED on
2369
- v2.12.0 at 1400x900, the straddling grip occupied [tableLeft-10,
2370
- tableLeft+10] while the block's own '.ed-handle' occupied [blockLeft-22,
2371
- blockLeft-4] with tableLeft == blockLeft, so the grip (position: fixed,
2372
- z-index 7, on document.body) won the hit test for the RIGHT 6px of every
2373
- ⠿ whose Y band it reached. The first column's own padding is widened in
2374
- the edit-mode-only layout chunk near the end of this stylesheet so the
2375
- inset grip still never reaches cell TEXT; '.ed-te-grip-col' is a horizontal 6-dot
2404
+ the header is draggable too), STRADDLING the table's left border,
2405
+ centred on it (spec 4.2 hit-test conflict 2). v2.12.0/S4 T1 tried moving
2406
+ it entirely inside the table instead (left edge on the border) to stop it
2407
+ winning the hit test against the block's own ⠿ — MEASURED at 1400x900,
2408
+ the straddling grip occupied [tableLeft-10, tableLeft+10] while
2409
+ '.ed-handle' occupied [blockLeft-22, blockLeft-4] with tableLeft ==
2410
+ blockLeft, so the grip (position: fixed, z-index 7, on document.body)
2411
+ won the hit test for the RIGHT 6px of every ⠿ whose Y band it reached —
2412
+ but that broke the row/column symmetry the user expected ('.ed-te-grip-col'
2413
+ still straddles the table's TOP border, because nothing of the page's
2414
+ own chrome lives up there), and was reported as a regression. v3.0.1
2415
+ restores the straddle and instead moves the ⠿/+ pair itself further left
2416
+ by --ed-gutter-shift, which removes the overlap at its source (see the
2417
+ edit-mode-only layout chunk near the end of this stylesheet); the row
2418
+ grip's straddling half sits well inside the first cell's default 14px
2419
+ padding, so no extra padding token is needed either.
2420
+ '.ed-te-grip-col' is a horizontal 6-dot
2376
2421
  handle shown just ABOVE the hovered column (every column). Dots are plain <span>s laid out via CSS grid with
2377
2422
  place-content: center, so the dot cluster stays compact/centered
2378
2423
  regardless of the button's own (larger, hit-target-sized) box — no
@@ -2391,12 +2436,12 @@ ${itemsHtml}
2391
2436
  .ed-te-grip:hover { background: rgba(0, 0, 0, 0.06); }
2392
2437
  .ed-te-grip-dot { width: 3px; height: 3px; border-radius: 50%; background: #9ca3af; }
2393
2438
  .ed-te-grip:hover .ed-te-grip-dot { background: #6b7280; }
2394
- /* spec §4.2 hit-test conflict 2 (S4 T1): the row grip's width is a TOKEN
2395
- because two other numbers are derived from it — lib/editor/client.js pins
2396
- the grip's LEFT edge to the table's left border (so the whole grip is
2397
- inside the first column and shares no pixel with the block gutter's ⠿),
2398
- and the edit-mode first-column padding must be wide enough to host it
2399
- without covering cell text. Written once here, derived twice below. */
2439
+ /* spec §4.2 hit-test conflict 2: the row grip's width is a TOKEN because
2440
+ lib/editor/client.js's updateTableEdgeGrips() reads it (via
2441
+ gripRowWidthPx()) to CENTRE the grip on the table's left border —
2442
+ tableRect.left - gw / 2. Written once here, read once there, so the CSS
2443
+ width and the JS position can never drift apart the way they did when
2444
+ the position was a hard-coded literal 20. */
2400
2445
  :root { --ed-te-grip-row-w: 20px; }
2401
2446
  .ed-te-grip-row {
2402
2447
  width: var(--ed-te-grip-row-w); height: 28px; cursor: grab; z-index: 7;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helping-ai-workflow/md2doc",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Markdown → HTML / PDF renderer with WaveDrom, Mermaid, and Graphviz support",
5
5
  "keywords": [
6
6
  "markdown",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "scripts": {
38
38
  "preinstall": "node scripts/preinstall.js",
39
- "test": "node test/md2doc.test.js && node test/blockmap.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/lightbox-anno-style.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js && node test/convert-md.test.js && node test/render-api.test.js && node test/lineops.test.js && node test/indent-clamp.test.js && node test/selection.test.js && node test/editmode-render.test.js && node test/editmode-wavedrom-reinit.test.js && node test/editor-server.test.js && node test/cli-edit.test.js && node test/open-viewer.test.js && node test/editor-client.test.js && node test/editor-client-runtime.test.js && node test/roundtrip.test.js && node test/byte-stability.test.js && node test/editor-server-throw.test.js && node test/editor-reader-rebind.test.js && node test/inline-md.test.js && node test/table-md.test.js && node test/gate-compat.test.js && node test/history.test.js && node test/list-md.test.js"
39
+ "test": "node test/md2doc.test.js && node test/blockmap.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/lightbox.test.js && node test/lightbox-anno.test.js && node test/lightbox-anno-style.test.js && node test/reader-panels.test.js && node test/cli.test.js && node test/code-operator.test.js && node test/convert-md.test.js && node test/render-api.test.js && node test/lineops.test.js && node test/indent-clamp.test.js && node test/selection.test.js && node test/editmode-render.test.js && node test/editmode-wavedrom-reinit.test.js && node test/editor-server.test.js && node test/cli-edit.test.js && node test/open-viewer.test.js && node test/editor-client.test.js && node test/editor-client-runtime.test.js && node test/roundtrip.test.js && node test/byte-stability.test.js && node test/editor-server-throw.test.js && node test/editor-reader-rebind.test.js && node test/inline-md.test.js && node test/table-md.test.js && node test/gate-compat.test.js && node test/history.test.js && node test/list-md.test.js && node test/table-width.test.js"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",