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