@abraca/cli 1.6.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1256,7 +1256,14 @@ function elementTextContent(el) {
1256
1256
  for (let i = 0; i < el.length; i++) {
1257
1257
  const child = el.get(i);
1258
1258
  if (child instanceof Y.XmlText) parts.push(xmlTextToMarkdown(child));
1259
- else if (child instanceof Y.XmlElement) parts.push(elementTextContent(child));
1259
+ else if (child instanceof Y.XmlElement) {
1260
+ if (child.nodeName === "docLink") {
1261
+ const docId = child.getAttribute("docId");
1262
+ if (docId) parts.push(`[[${docId}]]`);
1263
+ continue;
1264
+ }
1265
+ parts.push(elementTextContent(child));
1266
+ }
1260
1267
  }
1261
1268
  return parts.join("");
1262
1269
  }
@@ -1285,7 +1292,9 @@ function serializeElement(el, indent = "") {
1285
1292
  case "table": return serializeTable(el);
1286
1293
  case "docEmbed": {
1287
1294
  const docId = el.getAttribute("docId");
1288
- return docId ? `![[${docId}]]` : "";
1295
+ if (!docId) return "";
1296
+ const seamlessAttr = el.getAttribute("seamless");
1297
+ return seamlessAttr === true || seamlessAttr === "true" ? `![[${docId}]]{seamless}` : `![[${docId}]]`;
1289
1298
  }
1290
1299
  case "svgEmbed": {
1291
1300
  const svg = el.getAttribute("svg") || "";
@@ -1599,14 +1608,12 @@ function parseInline(text) {
1599
1608
  text: kbdProps["value"] || "",
1600
1609
  attrs: { kbd: { value: kbdProps["value"] || "" } }
1601
1610
  });
1602
- } else if (match[5] !== void 0) {
1603
- const docId = match[5];
1604
- const displayText = match[6] ?? docId;
1605
- tokens.push({
1606
- text: displayText,
1607
- attrs: { link: { href: `/doc/${docId}` } }
1608
- });
1609
- } else if (match[7] !== void 0) tokens.push({
1611
+ } else if (match[5] !== void 0) tokens.push({
1612
+ text: "",
1613
+ node: "docLink",
1614
+ nodeAttrs: { docId: match[5] }
1615
+ });
1616
+ else if (match[7] !== void 0) tokens.push({
1610
1617
  text: match[7],
1611
1618
  attrs: { strike: true }
1612
1619
  });
@@ -1633,7 +1640,7 @@ function parseInline(text) {
1633
1640
  lastIndex = match.index + match[0].length;
1634
1641
  }
1635
1642
  if (lastIndex < stripped.length) tokens.push({ text: stripped.slice(lastIndex) });
1636
- return tokens.filter((t) => t.text.length > 0);
1643
+ return tokens.filter((t) => t.node || t.text.length > 0);
1637
1644
  }
1638
1645
  function parseTableRow(line) {
1639
1646
  const parts = line.split("|");
@@ -1761,11 +1768,14 @@ function parseBlocks(markdown) {
1761
1768
  i++;
1762
1769
  continue;
1763
1770
  }
1764
- const docEmbedMatch = line.match(/^!\[\[([^\]|]+?)(?:\|[^\]]*?)?\]\]\s*$/);
1771
+ const docEmbedMatch = line.match(/^!\[\[([^\]|]+?)(?:\|[^\]]*?)?\]\](\{[^}]*\})?\s*$/);
1765
1772
  if (docEmbedMatch) {
1773
+ const props = parseMdcProps(docEmbedMatch[2]);
1774
+ const seamless = "seamless" in props || props["seamless"] === "true" || /\{[^}]*\bseamless\b[^}]*\}/.test(docEmbedMatch[2] ?? "");
1766
1775
  blocks.push({
1767
1776
  type: "docEmbed",
1768
- docId: docEmbedMatch[1]
1777
+ docId: docEmbedMatch[1],
1778
+ seamless: seamless || void 0
1769
1779
  });
1770
1780
  i++;
1771
1781
  continue;
@@ -2043,13 +2053,22 @@ function parseBlocks(markdown) {
2043
2053
  return blocks;
2044
2054
  }
2045
2055
  function fillTextInto(el, tokens) {
2046
- const filtered = tokens.filter((t) => t.text.length > 0);
2056
+ const filtered = tokens.filter((t) => t.node || t.text.length > 0);
2047
2057
  if (!filtered.length) return;
2048
- const xtNodes = filtered.map(() => new Y.XmlText());
2049
- el.insert(0, xtNodes);
2058
+ const children = filtered.map((tok) => {
2059
+ if (tok.node) {
2060
+ const xe = new Y.XmlElement(tok.node);
2061
+ if (tok.nodeAttrs) for (const [k, v] of Object.entries(tok.nodeAttrs)) xe.setAttribute(k, v);
2062
+ return xe;
2063
+ }
2064
+ return new Y.XmlText();
2065
+ });
2066
+ el.insert(0, children);
2050
2067
  filtered.forEach((tok, i) => {
2051
- if (tok.attrs) xtNodes[i].insert(0, tok.text, tok.attrs);
2052
- else xtNodes[i].insert(0, tok.text);
2068
+ if (tok.node) return;
2069
+ const xt = children[i];
2070
+ if (tok.attrs) xt.insert(0, tok.text, tok.attrs);
2071
+ else xt.insert(0, tok.text);
2053
2072
  });
2054
2073
  }
2055
2074
  function blockElName(b) {
@@ -2296,6 +2315,7 @@ function fillBlock(el, block) {
2296
2315
  break;
2297
2316
  case "docEmbed":
2298
2317
  el.setAttribute("docId", block.docId);
2318
+ if (block.seamless) el.setAttribute("seamless", "true");
2299
2319
  break;
2300
2320
  case "svgEmbed":
2301
2321
  el.setAttribute("svg", block.svg);
@@ -2820,40 +2840,138 @@ registerCommand({
2820
2840
  if (!raw) return `Document ${docId} not found.`;
2821
2841
  const entry = toPlain(raw);
2822
2842
  const metaKeys = new Set([
2823
- "icon",
2824
2843
  "color",
2844
+ "icon",
2845
+ "subtitle",
2846
+ "note",
2847
+ "datetimeStart",
2848
+ "datetimeEnd",
2849
+ "allDay",
2850
+ "dateStart",
2851
+ "dateEnd",
2852
+ "timeStart",
2853
+ "timeEnd",
2854
+ "dateTaken",
2855
+ "checked",
2825
2856
  "priority",
2826
2857
  "status",
2827
- "checked",
2858
+ "taskProgress",
2828
2859
  "rating",
2829
2860
  "tags",
2830
- "dateStart",
2831
- "dateEnd",
2832
- "datetimeStart",
2833
- "datetimeEnd",
2834
- "allDay",
2861
+ "members",
2835
2862
  "url",
2836
2863
  "email",
2837
2864
  "phone",
2838
2865
  "number",
2839
2866
  "unit",
2840
- "subtitle",
2841
- "note",
2842
- "taskProgress",
2843
2867
  "coverUploadId",
2868
+ "coverDocId",
2869
+ "coverMimeType",
2844
2870
  "geoType",
2845
2871
  "geoLat",
2846
2872
  "geoLng",
2873
+ "geoDescription",
2847
2874
  "deskX",
2848
2875
  "deskY",
2876
+ "deskZ",
2849
2877
  "deskMode",
2878
+ "mmX",
2879
+ "mmY",
2880
+ "graphX",
2881
+ "graphY",
2882
+ "graphPinned",
2850
2883
  "spShape",
2851
- "spColor",
2852
- "chartType",
2884
+ "spOpacity",
2885
+ "spX",
2886
+ "spY",
2887
+ "spZ",
2888
+ "spRX",
2889
+ "spRY",
2890
+ "spRZ",
2891
+ "spSX",
2892
+ "spSY",
2893
+ "spSZ",
2894
+ "spModelUploadId",
2895
+ "spModelDocId",
2896
+ "slidesTransition",
2897
+ "fileType",
2898
+ "entry",
2899
+ "bold",
2900
+ "italic",
2901
+ "textColor",
2902
+ "bgColor",
2903
+ "align",
2904
+ "formula",
2853
2905
  "kanbanColumnWidth",
2854
2906
  "galleryColumns",
2907
+ "galleryAspect",
2908
+ "galleryCardStyle",
2909
+ "galleryShowLabels",
2910
+ "gallerySortBy",
2855
2911
  "calendarView",
2856
- "tableMode"
2912
+ "calendarWeekStart",
2913
+ "calendarShowWeekNumbers",
2914
+ "tableMode",
2915
+ "tableSortKey",
2916
+ "tableSortDir",
2917
+ "timelineZoom",
2918
+ "timelinePixelsPerDay",
2919
+ "timelineCenterDate",
2920
+ "checklistFilter",
2921
+ "checklistSort",
2922
+ "mapShowLabels",
2923
+ "graphSpacing",
2924
+ "graphShowLabels",
2925
+ "graphEdgeThickness",
2926
+ "showRefEdges",
2927
+ "mmSpacing",
2928
+ "spatialGridVisible",
2929
+ "slidesTheme",
2930
+ "chartType",
2931
+ "chartMetric",
2932
+ "chartColorScheme",
2933
+ "chartLimit",
2934
+ "chartShowLegend",
2935
+ "chartShowValues",
2936
+ "sheetsDefaultColWidth",
2937
+ "sheetsDefaultRowHeight",
2938
+ "sheetsShowGridlines",
2939
+ "sheetsFreezeRows",
2940
+ "sheetsFreezeCols",
2941
+ "mediaRepeat",
2942
+ "mediaShuffle"
2943
+ ]);
2944
+ const numericKeys = new Set([
2945
+ "priority",
2946
+ "rating",
2947
+ "number",
2948
+ "taskProgress",
2949
+ "geoLat",
2950
+ "geoLng",
2951
+ "deskX",
2952
+ "deskY",
2953
+ "deskZ",
2954
+ "mmX",
2955
+ "mmY",
2956
+ "graphX",
2957
+ "graphY",
2958
+ "spOpacity",
2959
+ "spX",
2960
+ "spY",
2961
+ "spZ",
2962
+ "spRX",
2963
+ "spRY",
2964
+ "spRZ",
2965
+ "spSX",
2966
+ "spSY",
2967
+ "spSZ",
2968
+ "galleryColumns",
2969
+ "chartLimit",
2970
+ "timelinePixelsPerDay",
2971
+ "sheetsDefaultColWidth",
2972
+ "sheetsDefaultRowHeight",
2973
+ "sheetsFreezeRows",
2974
+ "sheetsFreezeCols"
2857
2975
  ]);
2858
2976
  const updates = {};
2859
2977
  let hasUpdates = false;
@@ -2861,17 +2979,7 @@ registerCommand({
2861
2979
  if (value === "null") updates[key] = null;
2862
2980
  else if (value === "true") updates[key] = true;
2863
2981
  else if (value === "false") updates[key] = false;
2864
- else if ([
2865
- "priority",
2866
- "rating",
2867
- "number",
2868
- "taskProgress",
2869
- "geoLat",
2870
- "geoLng",
2871
- "deskX",
2872
- "deskY",
2873
- "galleryColumns"
2874
- ].includes(key)) updates[key] = parseFloat(value);
2982
+ else if (numericKeys.has(key)) updates[key] = parseFloat(value);
2875
2983
  else if (key === "tags") updates[key] = value.split(",").map((s) => s.trim());
2876
2984
  else updates[key] = value;
2877
2985
  hasUpdates = true;
@@ -3181,6 +3289,801 @@ registerCommand({
3181
3289
  }
3182
3290
  });
3183
3291
 
3292
+ //#endregion
3293
+ //#region packages/mcp/src/converters/page-types.ts
3294
+ const PAGE_TYPES = {
3295
+ doc: {
3296
+ key: "doc",
3297
+ label: "Document",
3298
+ icon: "file-text",
3299
+ description: "Rich text document with real-time collaboration",
3300
+ core: true,
3301
+ supportsChildren: true
3302
+ },
3303
+ kanban: {
3304
+ key: "kanban",
3305
+ label: "Kanban",
3306
+ icon: "kanban",
3307
+ description: "Drag-and-drop task board with columns and cards",
3308
+ core: true,
3309
+ supportsChildren: true,
3310
+ childLabel: "Column",
3311
+ grandchildLabel: "Card",
3312
+ defaultMetaFields: [{
3313
+ type: "select",
3314
+ key: "kanbanColumnWidth",
3315
+ options: [
3316
+ "narrow",
3317
+ "default",
3318
+ "wide"
3319
+ ],
3320
+ label: "Column Width"
3321
+ }]
3322
+ },
3323
+ gallery: {
3324
+ key: "gallery",
3325
+ label: "Gallery",
3326
+ icon: "images",
3327
+ description: "Visual grid of items with rich content",
3328
+ core: true,
3329
+ supportsChildren: true,
3330
+ childLabel: "Item",
3331
+ metaSchema: [
3332
+ {
3333
+ type: "location",
3334
+ latKey: "geoLat",
3335
+ lngKey: "geoLng",
3336
+ label: "Location"
3337
+ },
3338
+ {
3339
+ type: "datetime",
3340
+ key: "datetimeStart",
3341
+ label: "Date"
3342
+ },
3343
+ {
3344
+ type: "tags",
3345
+ key: "tags",
3346
+ label: "Tags"
3347
+ },
3348
+ {
3349
+ type: "rating",
3350
+ key: "rating",
3351
+ max: 5,
3352
+ label: "Rating"
3353
+ },
3354
+ {
3355
+ type: "icon",
3356
+ key: "icon",
3357
+ label: "Icon"
3358
+ },
3359
+ {
3360
+ type: "colorPreset",
3361
+ key: "color",
3362
+ presets: [
3363
+ "#6366f1",
3364
+ "#ec4899",
3365
+ "#f97316",
3366
+ "#22c55e",
3367
+ "#3b82f6",
3368
+ "#a855f7"
3369
+ ],
3370
+ label: "Color"
3371
+ }
3372
+ ],
3373
+ defaultMetaFields: [
3374
+ {
3375
+ type: "number",
3376
+ key: "galleryColumns",
3377
+ min: 1,
3378
+ max: 6,
3379
+ step: 1,
3380
+ label: "Columns"
3381
+ },
3382
+ {
3383
+ type: "select",
3384
+ key: "galleryAspect",
3385
+ options: [
3386
+ "square",
3387
+ "4:3",
3388
+ "3:2",
3389
+ "16:9",
3390
+ "free"
3391
+ ],
3392
+ label: "Aspect Ratio"
3393
+ },
3394
+ {
3395
+ type: "select",
3396
+ key: "galleryCardStyle",
3397
+ options: [
3398
+ "default",
3399
+ "compact",
3400
+ "detailed"
3401
+ ],
3402
+ label: "Card Style"
3403
+ },
3404
+ {
3405
+ type: "toggle",
3406
+ key: "galleryShowLabels",
3407
+ label: "Show Labels"
3408
+ },
3409
+ {
3410
+ type: "select",
3411
+ key: "gallerySortBy",
3412
+ options: [
3413
+ "manual",
3414
+ "date",
3415
+ "name",
3416
+ "rating"
3417
+ ],
3418
+ label: "Sort"
3419
+ }
3420
+ ]
3421
+ },
3422
+ table: {
3423
+ key: "table",
3424
+ label: "Table",
3425
+ icon: "table",
3426
+ description: "Collaborative spreadsheet with custom fields",
3427
+ core: true,
3428
+ supportsChildren: true,
3429
+ childLabel: "Column",
3430
+ grandchildLabel: "Row",
3431
+ defaultMetaFields: [{
3432
+ type: "select",
3433
+ key: "tableMode",
3434
+ options: ["hierarchy", "flat"],
3435
+ label: "Mode"
3436
+ }, {
3437
+ type: "select",
3438
+ key: "tableSortDir",
3439
+ options: ["asc", "desc"],
3440
+ label: "Sort Direction"
3441
+ }]
3442
+ },
3443
+ outline: {
3444
+ key: "outline",
3445
+ label: "Outline",
3446
+ icon: "list-tree",
3447
+ description: "Hierarchical outline with keyboard navigation",
3448
+ core: true,
3449
+ supportsChildren: true,
3450
+ childLabel: "Item",
3451
+ defaultDepth: -1
3452
+ },
3453
+ checklist: {
3454
+ key: "checklist",
3455
+ label: "Checklist",
3456
+ icon: "check-square",
3457
+ description: "Collaborative checklist with sub-tasks, drag-and-drop, and due dates",
3458
+ core: true,
3459
+ supportsChildren: true,
3460
+ childLabel: "Task",
3461
+ defaultDepth: -1,
3462
+ metaSchema: [
3463
+ {
3464
+ type: "toggle",
3465
+ key: "checked",
3466
+ label: "Done"
3467
+ },
3468
+ {
3469
+ type: "select",
3470
+ key: "priority",
3471
+ options: [
3472
+ "none",
3473
+ "low",
3474
+ "medium",
3475
+ "high"
3476
+ ],
3477
+ label: "Priority"
3478
+ },
3479
+ {
3480
+ type: "date",
3481
+ key: "dateEnd",
3482
+ label: "Due date"
3483
+ }
3484
+ ],
3485
+ defaultMetaFields: [{
3486
+ type: "select",
3487
+ key: "checklistFilter",
3488
+ options: [
3489
+ "all",
3490
+ "active",
3491
+ "completed"
3492
+ ],
3493
+ label: "Filter"
3494
+ }, {
3495
+ type: "select",
3496
+ key: "checklistSort",
3497
+ options: [
3498
+ "manual",
3499
+ "priority",
3500
+ "due"
3501
+ ],
3502
+ label: "Sort"
3503
+ }]
3504
+ },
3505
+ graph: {
3506
+ key: "graph",
3507
+ label: "Graph",
3508
+ icon: "git-fork",
3509
+ description: "Force-directed knowledge graph — full document tree as nodes & edges",
3510
+ core: true,
3511
+ supportsChildren: true,
3512
+ childLabel: "Node",
3513
+ defaultMetaFields: [{
3514
+ type: "toggle",
3515
+ key: "showRefEdges",
3516
+ label: "Show Ref Edges",
3517
+ default: true
3518
+ }]
3519
+ },
3520
+ timeline: {
3521
+ key: "timeline",
3522
+ label: "Timeline",
3523
+ icon: "gantt-chart",
3524
+ description: "Gantt-style project timeline with epics and tasks",
3525
+ core: true,
3526
+ supportsChildren: true,
3527
+ childLabel: "Epic",
3528
+ grandchildLabel: "Task",
3529
+ metaSchema: [
3530
+ {
3531
+ type: "daterange",
3532
+ startKey: "dateStart",
3533
+ endKey: "dateEnd"
3534
+ },
3535
+ {
3536
+ type: "slider",
3537
+ key: "taskProgress",
3538
+ min: 0,
3539
+ max: 100,
3540
+ label: "Progress"
3541
+ },
3542
+ {
3543
+ type: "colorPreset",
3544
+ key: "color",
3545
+ presets: [
3546
+ "#6366f1",
3547
+ "#818cf8",
3548
+ "#f97316",
3549
+ "#22c55e",
3550
+ "#3b82f6",
3551
+ "#a855f7"
3552
+ ],
3553
+ label: "Color"
3554
+ }
3555
+ ]
3556
+ },
3557
+ calendar: {
3558
+ key: "calendar",
3559
+ label: "Calendar",
3560
+ icon: "calendar",
3561
+ description: "Event calendar with month, week, and day views",
3562
+ core: true,
3563
+ supportsChildren: true,
3564
+ childLabel: "Event",
3565
+ metaSchema: [
3566
+ {
3567
+ type: "datetimerange",
3568
+ startKey: "datetimeStart",
3569
+ endKey: "datetimeEnd",
3570
+ allDayKey: "allDay"
3571
+ },
3572
+ {
3573
+ type: "colorPreset",
3574
+ key: "color",
3575
+ presets: [
3576
+ "#6366f1",
3577
+ "#ec4899",
3578
+ "#f97316",
3579
+ "#22c55e",
3580
+ "#3b82f6",
3581
+ "#a855f7"
3582
+ ],
3583
+ label: "Color"
3584
+ },
3585
+ {
3586
+ type: "icon",
3587
+ key: "icon",
3588
+ label: "Icon"
3589
+ }
3590
+ ],
3591
+ defaultMetaFields: [
3592
+ {
3593
+ type: "select",
3594
+ key: "calendarWeekStart",
3595
+ options: ["sun", "mon"],
3596
+ label: "Week Starts"
3597
+ },
3598
+ {
3599
+ type: "select",
3600
+ key: "calendarView",
3601
+ options: [
3602
+ "month",
3603
+ "week",
3604
+ "day"
3605
+ ],
3606
+ label: "Default View"
3607
+ },
3608
+ {
3609
+ type: "toggle",
3610
+ key: "calendarShowWeekNumbers",
3611
+ label: "Show Week Numbers"
3612
+ }
3613
+ ]
3614
+ },
3615
+ map: {
3616
+ key: "map",
3617
+ label: "Map",
3618
+ icon: "map",
3619
+ description: "Collaborative world map with shared markers",
3620
+ core: true,
3621
+ supportsChildren: true,
3622
+ childLabel: "Location",
3623
+ defaultMetaFields: [{
3624
+ type: "toggle",
3625
+ key: "mapShowLabels",
3626
+ label: "Show Labels",
3627
+ default: true
3628
+ }]
3629
+ },
3630
+ dashboard: {
3631
+ key: "dashboard",
3632
+ label: "Dashboard",
3633
+ icon: "layout-dashboard",
3634
+ description: "Arrange documents as draggable icons with optional widget views",
3635
+ core: true,
3636
+ supportsChildren: true,
3637
+ childLabel: "Item"
3638
+ },
3639
+ call: {
3640
+ key: "call",
3641
+ label: "Call",
3642
+ icon: "phone",
3643
+ description: "Video call room with live audio and screen sharing",
3644
+ core: true,
3645
+ supportsChildren: false
3646
+ },
3647
+ chart: {
3648
+ key: "chart",
3649
+ label: "Chart",
3650
+ icon: "bar-chart-3",
3651
+ description: "Charts — manual data points or aggregation over document trees",
3652
+ core: true,
3653
+ supportsChildren: true,
3654
+ childLabel: "Data Point",
3655
+ grandchildLabel: "Data Point",
3656
+ metaSchema: [
3657
+ {
3658
+ type: "number",
3659
+ key: "number",
3660
+ step: .01,
3661
+ label: "Value"
3662
+ },
3663
+ {
3664
+ type: "colorPreset",
3665
+ key: "color",
3666
+ presets: [
3667
+ "#6366f1",
3668
+ "#ec4899",
3669
+ "#f97316",
3670
+ "#22c55e",
3671
+ "#3b82f6",
3672
+ "#a855f7",
3673
+ "#14b8a6",
3674
+ "#eab308"
3675
+ ],
3676
+ label: "Color"
3677
+ },
3678
+ {
3679
+ type: "tags",
3680
+ key: "tags",
3681
+ label: "Tags"
3682
+ }
3683
+ ],
3684
+ defaultMetaFields: [
3685
+ {
3686
+ type: "select",
3687
+ key: "chartType",
3688
+ options: [
3689
+ "bar",
3690
+ "stacked bar",
3691
+ "line",
3692
+ "donut",
3693
+ "treemap"
3694
+ ],
3695
+ label: "Chart Type"
3696
+ },
3697
+ {
3698
+ type: "select",
3699
+ key: "chartMetric",
3700
+ options: [
3701
+ "value",
3702
+ "type",
3703
+ "tag",
3704
+ "status",
3705
+ "priority",
3706
+ "activity",
3707
+ "completion"
3708
+ ],
3709
+ label: "Metric"
3710
+ },
3711
+ {
3712
+ type: "select",
3713
+ key: "chartColorScheme",
3714
+ options: [
3715
+ "default",
3716
+ "warm",
3717
+ "cool",
3718
+ "mono"
3719
+ ],
3720
+ label: "Colors"
3721
+ },
3722
+ {
3723
+ type: "number",
3724
+ key: "chartLimit",
3725
+ min: 3,
3726
+ max: 30,
3727
+ step: 1,
3728
+ label: "Max Items"
3729
+ },
3730
+ {
3731
+ type: "toggle",
3732
+ key: "chartShowLegend",
3733
+ label: "Show Legend",
3734
+ default: true
3735
+ },
3736
+ {
3737
+ type: "toggle",
3738
+ key: "chartShowValues",
3739
+ label: "Show Values"
3740
+ }
3741
+ ]
3742
+ },
3743
+ sheets: {
3744
+ key: "sheets",
3745
+ label: "Sheets",
3746
+ icon: "grid-3x3",
3747
+ description: "Spreadsheet — cells, formulas, and formatting in a collaborative grid",
3748
+ core: true,
3749
+ supportsChildren: true,
3750
+ childLabel: "Column",
3751
+ grandchildLabel: "Cell",
3752
+ defaultMetaFields: [
3753
+ {
3754
+ type: "number",
3755
+ key: "sheetsDefaultColWidth",
3756
+ min: 40,
3757
+ max: 500,
3758
+ step: 10,
3759
+ label: "Column Width"
3760
+ },
3761
+ {
3762
+ type: "number",
3763
+ key: "sheetsDefaultRowHeight",
3764
+ min: 20,
3765
+ max: 100,
3766
+ step: 2,
3767
+ label: "Row Height"
3768
+ },
3769
+ {
3770
+ type: "toggle",
3771
+ key: "sheetsShowGridlines",
3772
+ label: "Gridlines"
3773
+ }
3774
+ ]
3775
+ },
3776
+ slides: {
3777
+ key: "slides",
3778
+ label: "Slides",
3779
+ icon: "presentation",
3780
+ description: "Presentation slides with two-axis navigation",
3781
+ core: true,
3782
+ supportsChildren: true,
3783
+ childLabel: "Slide",
3784
+ grandchildLabel: "Sub-slide",
3785
+ metaSchema: [{
3786
+ type: "select",
3787
+ key: "slidesTransition",
3788
+ options: [
3789
+ "none",
3790
+ "fade",
3791
+ "slide"
3792
+ ],
3793
+ label: "Transition"
3794
+ }, {
3795
+ type: "colorPreset",
3796
+ key: "color",
3797
+ presets: [
3798
+ "#6366f1",
3799
+ "#ec4899",
3800
+ "#f97316",
3801
+ "#22c55e",
3802
+ "#3b82f6",
3803
+ "#a855f7"
3804
+ ],
3805
+ label: "Accent"
3806
+ }],
3807
+ defaultMetaFields: [{
3808
+ type: "select",
3809
+ key: "slidesTheme",
3810
+ options: ["dark", "light"],
3811
+ label: "Theme"
3812
+ }]
3813
+ },
3814
+ overview: {
3815
+ key: "overview",
3816
+ label: "Overview",
3817
+ icon: "radar",
3818
+ description: "Space home — activity, people, stats, and health at a glance",
3819
+ core: true,
3820
+ supportsChildren: true,
3821
+ childLabel: "Page"
3822
+ },
3823
+ spatial: {
3824
+ key: "spatial",
3825
+ label: "Spatial",
3826
+ icon: "box",
3827
+ description: "3D scene with collaborative objects and real-time presence",
3828
+ core: false,
3829
+ plugin: "spatial",
3830
+ supportsChildren: true,
3831
+ childLabel: "Object",
3832
+ grandchildLabel: "Part",
3833
+ defaultDepth: -1,
3834
+ metaSchema: [
3835
+ {
3836
+ type: "select",
3837
+ key: "spShape",
3838
+ options: [
3839
+ "box",
3840
+ "sphere",
3841
+ "cylinder",
3842
+ "cone",
3843
+ "plane",
3844
+ "torus",
3845
+ "glb"
3846
+ ],
3847
+ label: "Shape"
3848
+ },
3849
+ {
3850
+ type: "colorPreset",
3851
+ key: "color",
3852
+ presets: [
3853
+ "#6366f1",
3854
+ "#ef4444",
3855
+ "#22c55e",
3856
+ "#3b82f6",
3857
+ "#f97316",
3858
+ "#a855f7",
3859
+ "#ec4899",
3860
+ "#14b8a6"
3861
+ ],
3862
+ label: "Color"
3863
+ },
3864
+ {
3865
+ type: "slider",
3866
+ key: "spOpacity",
3867
+ min: 0,
3868
+ max: 100,
3869
+ label: "Opacity"
3870
+ },
3871
+ {
3872
+ type: "number",
3873
+ key: "spX",
3874
+ step: .1,
3875
+ label: "X"
3876
+ },
3877
+ {
3878
+ type: "number",
3879
+ key: "spY",
3880
+ step: .1,
3881
+ label: "Y"
3882
+ },
3883
+ {
3884
+ type: "number",
3885
+ key: "spZ",
3886
+ step: .1,
3887
+ label: "Z"
3888
+ },
3889
+ {
3890
+ type: "number",
3891
+ key: "spRX",
3892
+ min: -180,
3893
+ max: 180,
3894
+ step: 1,
3895
+ label: "Rot X"
3896
+ },
3897
+ {
3898
+ type: "number",
3899
+ key: "spRY",
3900
+ min: -180,
3901
+ max: 180,
3902
+ step: 1,
3903
+ label: "Rot Y"
3904
+ },
3905
+ {
3906
+ type: "number",
3907
+ key: "spRZ",
3908
+ min: -180,
3909
+ max: 180,
3910
+ step: 1,
3911
+ label: "Rot Z"
3912
+ },
3913
+ {
3914
+ type: "number",
3915
+ key: "spSX",
3916
+ min: .01,
3917
+ max: 100,
3918
+ step: .1,
3919
+ label: "Scale X"
3920
+ },
3921
+ {
3922
+ type: "number",
3923
+ key: "spSY",
3924
+ min: .01,
3925
+ max: 100,
3926
+ step: .1,
3927
+ label: "Scale Y"
3928
+ },
3929
+ {
3930
+ type: "number",
3931
+ key: "spSZ",
3932
+ min: .01,
3933
+ max: 100,
3934
+ step: .1,
3935
+ label: "Scale Z"
3936
+ }
3937
+ ],
3938
+ defaultMetaFields: [{
3939
+ type: "toggle",
3940
+ key: "spatialGridVisible",
3941
+ label: "Show Grid",
3942
+ default: true
3943
+ }]
3944
+ },
3945
+ media: {
3946
+ key: "media",
3947
+ label: "Media",
3948
+ icon: "disc-3",
3949
+ description: "Media player with synced listening and playlists",
3950
+ core: false,
3951
+ plugin: "media",
3952
+ supportsChildren: true,
3953
+ childLabel: "Track",
3954
+ defaultDepth: -1,
3955
+ metaSchema: [{
3956
+ type: "tags",
3957
+ key: "tags",
3958
+ label: "Tags"
3959
+ }],
3960
+ defaultMetaFields: [{
3961
+ type: "select",
3962
+ key: "mediaRepeat",
3963
+ options: [
3964
+ "off",
3965
+ "all",
3966
+ "one"
3967
+ ],
3968
+ label: "Repeat"
3969
+ }, {
3970
+ type: "toggle",
3971
+ key: "mediaShuffle",
3972
+ label: "Shuffle"
3973
+ }]
3974
+ },
3975
+ coder: {
3976
+ key: "coder",
3977
+ label: "Coder",
3978
+ icon: "code-2",
3979
+ description: "Collaborative multi-file coding environment",
3980
+ core: false,
3981
+ plugin: "coder",
3982
+ supportsChildren: true,
3983
+ childLabel: "File",
3984
+ defaultDepth: -1,
3985
+ metaSchema: [{
3986
+ type: "select",
3987
+ key: "fileType",
3988
+ options: [
3989
+ "vue",
3990
+ "ts",
3991
+ "js",
3992
+ "css",
3993
+ "json",
3994
+ "folder"
3995
+ ],
3996
+ label: "Type"
3997
+ }, {
3998
+ type: "toggle",
3999
+ key: "entry",
4000
+ label: "Entry Point"
4001
+ }]
4002
+ }
4003
+ };
4004
+ const TYPE_ALIASES = { desktop: "dashboard" };
4005
+ function resolvePageType(key) {
4006
+ if (!key) return void 0;
4007
+ return PAGE_TYPES[TYPE_ALIASES[key] ?? key];
4008
+ }
4009
+
4010
+ //#endregion
4011
+ //#region packages/cli/src/commands/page-types.ts
4012
+ /**
4013
+ * page-types / type-info commands: enumerate Abracadabra page types and their
4014
+ * metadata schemas. Works without a server connection — the catalog is static.
4015
+ */
4016
+ function describeField(f) {
4017
+ const bits = [];
4018
+ bits.push(f.type);
4019
+ if (f.key) bits.push(`key=${f.key}`);
4020
+ if (f.latKey) bits.push(`latKey=${f.latKey},lngKey=${f.lngKey}`);
4021
+ if (f.startKey) bits.push(`startKey=${f.startKey},endKey=${f.endKey}${f.allDayKey ? `,allDayKey=${f.allDayKey}` : ""}`);
4022
+ if (f.options) bits.push(`options=[${f.options.join(", ")}]`);
4023
+ if (f.presets) bits.push(`presets=${f.presets.length}`);
4024
+ if (typeof f.min === "number" || typeof f.max === "number") bits.push(`range=${f.min ?? "?"}..${f.max ?? "?"}`);
4025
+ if (f.step) bits.push(`step=${f.step}`);
4026
+ if (f.unit) bits.push(`unit=${f.unit}`);
4027
+ if (f.default !== void 0) bits.push(`default=${f.default}`);
4028
+ return bits.join(" ");
4029
+ }
4030
+ registerCommand({
4031
+ name: "page-types",
4032
+ aliases: ["types", "doctypes"],
4033
+ description: "List Abracadabra page types and their metadata schemas.",
4034
+ usage: "page-types [key=<type>] [--format=json]",
4035
+ async run(_conn, args) {
4036
+ const key = args.params["key"] || args.params["type"] || args.positional[0];
4037
+ const asJson = args.flags.has("json") || args.params["format"] === "json";
4038
+ if (key) {
4039
+ const info = resolvePageType(key);
4040
+ if (!info) return `Unknown page type "${key}". Run 'abracadabra page-types' to list all.`;
4041
+ if (asJson) return printJson(info);
4042
+ const lines = [
4043
+ `${info.label} (${info.key})${info.core ? "" : ` [plugin: ${info.plugin}]`}`,
4044
+ info.description ? ` ${info.description}` : "",
4045
+ ` icon: ${info.icon}`,
4046
+ ` supportsChildren: ${info.supportsChildren}`
4047
+ ];
4048
+ if (info.childLabel) lines.push(` childLabel: ${info.childLabel}`);
4049
+ if (info.grandchildLabel) lines.push(` grandchildLabel: ${info.grandchildLabel}`);
4050
+ if (info.defaultDepth !== void 0) lines.push(` defaultDepth: ${info.defaultDepth === -1 ? "unlimited" : info.defaultDepth}`);
4051
+ if (info.metaSchema?.length) {
4052
+ lines.push("", ` metaSchema (applies to descendants):`);
4053
+ for (const f of info.metaSchema) lines.push(` - ${describeField(f)}${f.label ? ` "${f.label}"` : ""}`);
4054
+ }
4055
+ if (info.defaultMetaFields?.length) {
4056
+ lines.push("", ` defaultMetaFields (renderer config on this doc):`);
4057
+ for (const f of info.defaultMetaFields) lines.push(` - ${describeField(f)}${f.label ? ` "${f.label}"` : ""}`);
4058
+ }
4059
+ return lines.filter(Boolean).join("\n");
4060
+ }
4061
+ const types = Object.values(PAGE_TYPES);
4062
+ if (asJson) return printJson({
4063
+ types,
4064
+ aliases: TYPE_ALIASES
4065
+ });
4066
+ const coreTypes = types.filter((t) => t.core);
4067
+ const pluginTypes = types.filter((t) => !t.core);
4068
+ const lines = ["Core page types:"];
4069
+ for (const t of coreTypes) {
4070
+ const depth = t.defaultDepth === -1 ? "∞" : t.grandchildLabel ? "2" : t.supportsChildren ? "1" : "0";
4071
+ const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(" → ");
4072
+ lines.push(` ${t.key.padEnd(12)}${(nesting || "—").padEnd(28)}depth=${depth}`);
4073
+ }
4074
+ lines.push("", "Plugin page types (require plugin):");
4075
+ for (const t of pluginTypes) {
4076
+ const depth = t.defaultDepth === -1 ? "∞" : t.grandchildLabel ? "2" : t.supportsChildren ? "1" : "0";
4077
+ const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(" → ");
4078
+ lines.push(` ${t.key.padEnd(12)}${(nesting || "—").padEnd(28)}depth=${depth} [plugin: ${t.plugin}]`);
4079
+ }
4080
+ lines.push("", "Aliases:");
4081
+ for (const [from, to] of Object.entries(TYPE_ALIASES)) lines.push(` ${from} → ${to}`);
4082
+ lines.push("", `Run 'abracadabra page-types <key>' for field-level detail.`);
4083
+ return lines.join("\n");
4084
+ }
4085
+ });
4086
+
3184
4087
  //#endregion
3185
4088
  //#region packages/cli/src/index.ts
3186
4089
  /**
@@ -3201,7 +4104,10 @@ const NO_CONNECT_COMMANDS = new Set([
3201
4104
  "h",
3202
4105
  "?",
3203
4106
  "version",
3204
- "v"
4107
+ "v",
4108
+ "page-types",
4109
+ "types",
4110
+ "doctypes"
3205
4111
  ]);
3206
4112
  async function main() {
3207
4113
  const args = parseArgs(process.argv);