@dryui/cli 0.1.1 → 0.2.0
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/dist/index.js +1187 -585
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3243,8 +3243,8 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3243
3243
|
}
|
|
3244
3244
|
return output.join("");
|
|
3245
3245
|
}
|
|
3246
|
-
function normalizeComponentEncoding(component,
|
|
3247
|
-
const func =
|
|
3246
|
+
function normalizeComponentEncoding(component, esc3) {
|
|
3247
|
+
const func = esc3 !== true ? escape : unescape;
|
|
3248
3248
|
if (component.scheme !== undefined) {
|
|
3249
3249
|
component.scheme = func(component.scheme);
|
|
3250
3250
|
}
|
|
@@ -6518,7 +6518,7 @@ var require_dist = __commonJS((exports, module) => {
|
|
|
6518
6518
|
// package.json
|
|
6519
6519
|
var package_default = {
|
|
6520
6520
|
name: "@dryui/cli",
|
|
6521
|
-
version: "0.
|
|
6521
|
+
version: "0.2.0",
|
|
6522
6522
|
author: "Rob Balfre",
|
|
6523
6523
|
license: "MIT",
|
|
6524
6524
|
repository: {
|
|
@@ -6545,7 +6545,7 @@ var package_default = {
|
|
|
6545
6545
|
},
|
|
6546
6546
|
dependencies: {
|
|
6547
6547
|
"@dryui/feedback-server": "^0.1.0",
|
|
6548
|
-
"@dryui/mcp": "^0.
|
|
6548
|
+
"@dryui/mcp": "^0.2.0"
|
|
6549
6549
|
},
|
|
6550
6550
|
devDependencies: {
|
|
6551
6551
|
"@types/node": "^25.5.0",
|
|
@@ -6554,7 +6554,7 @@ var package_default = {
|
|
|
6554
6554
|
};
|
|
6555
6555
|
// ../mcp/src/spec.json
|
|
6556
6556
|
var spec_default = {
|
|
6557
|
-
version: "0.1.
|
|
6557
|
+
version: "0.1.7",
|
|
6558
6558
|
package: "@dryui/ui",
|
|
6559
6559
|
themeImports: {
|
|
6560
6560
|
default: "@dryui/ui/themes/default.css",
|
|
@@ -6728,6 +6728,12 @@ var spec_default = {
|
|
|
6728
6728
|
name: "data-disabled",
|
|
6729
6729
|
description: "Present when the component or part is disabled."
|
|
6730
6730
|
},
|
|
6731
|
+
{
|
|
6732
|
+
name: "data-group-orientation"
|
|
6733
|
+
},
|
|
6734
|
+
{
|
|
6735
|
+
name: "data-in-group"
|
|
6736
|
+
},
|
|
6731
6737
|
{
|
|
6732
6738
|
name: "data-size"
|
|
6733
6739
|
},
|
|
@@ -7453,6 +7459,13 @@ var spec_default = {
|
|
|
7453
7459
|
]
|
|
7454
7460
|
},
|
|
7455
7461
|
cssVars: {
|
|
7462
|
+
"--dry-btn-accent": "Accent",
|
|
7463
|
+
"--dry-btn-accent-active": "Accent Active",
|
|
7464
|
+
"--dry-btn-accent-fg": "Accent Fg",
|
|
7465
|
+
"--dry-btn-accent-hover": "Accent Hover",
|
|
7466
|
+
"--dry-btn-accent-stroke": "Accent Stroke",
|
|
7467
|
+
"--dry-btn-border": "Border color",
|
|
7468
|
+
"--dry-btn-on-accent": "On Accent",
|
|
7456
7469
|
"--dry-dialog-bg": "Background color",
|
|
7457
7470
|
"--dry-dialog-border": "Border color",
|
|
7458
7471
|
"--dry-dialog-max-width": "Maximum width",
|
|
@@ -8536,6 +8549,9 @@ var spec_default = {
|
|
|
8536
8549
|
name: "data-disabled",
|
|
8537
8550
|
description: "Present when the component or part is disabled."
|
|
8538
8551
|
},
|
|
8552
|
+
{
|
|
8553
|
+
name: "data-indicator"
|
|
8554
|
+
},
|
|
8539
8555
|
{
|
|
8540
8556
|
name: "data-orientation",
|
|
8541
8557
|
description: "Reflects the current horizontal or vertical orientation.",
|
|
@@ -8671,6 +8687,9 @@ var spec_default = {
|
|
|
8671
8687
|
name: "data-disabled",
|
|
8672
8688
|
description: "Present when the component or part is disabled."
|
|
8673
8689
|
},
|
|
8690
|
+
{
|
|
8691
|
+
name: "data-indicator"
|
|
8692
|
+
},
|
|
8674
8693
|
{
|
|
8675
8694
|
name: "data-state",
|
|
8676
8695
|
description: "Reflects whether the collapsible content is expanded or collapsed.",
|
|
@@ -9074,8 +9093,7 @@ var spec_default = {
|
|
|
9074
9093
|
]
|
|
9075
9094
|
},
|
|
9076
9095
|
cssVars: {
|
|
9077
|
-
"--dry-field-gap": "Gap spacing"
|
|
9078
|
-
"--dry-field-label-order": "Label Order"
|
|
9096
|
+
"--dry-field-gap": "Gap spacing"
|
|
9079
9097
|
},
|
|
9080
9098
|
dataAttributes: [
|
|
9081
9099
|
{
|
|
@@ -9848,6 +9866,9 @@ var spec_default = {
|
|
|
9848
9866
|
name: "data-disabled",
|
|
9849
9867
|
description: "Present when the component or part is disabled."
|
|
9850
9868
|
},
|
|
9869
|
+
{
|
|
9870
|
+
name: "data-indicator"
|
|
9871
|
+
},
|
|
9851
9872
|
{
|
|
9852
9873
|
name: "data-invalid",
|
|
9853
9874
|
description: "Present when the current field value is invalid."
|
|
@@ -10971,9 +10992,6 @@ var spec_default = {
|
|
|
10971
10992
|
name: "data-disabled",
|
|
10972
10993
|
description: "Present when the component or part is disabled."
|
|
10973
10994
|
},
|
|
10974
|
-
{
|
|
10975
|
-
name: "data-option-swatch-group-content"
|
|
10976
|
-
},
|
|
10977
10995
|
{
|
|
10978
10996
|
name: "data-option-swatch-group-item"
|
|
10979
10997
|
},
|
|
@@ -11448,6 +11466,9 @@ var spec_default = {
|
|
|
11448
11466
|
},
|
|
11449
11467
|
{
|
|
11450
11468
|
name: "data-tabs-trigger"
|
|
11469
|
+
},
|
|
11470
|
+
{
|
|
11471
|
+
name: "data-tabs-trigger-content"
|
|
11451
11472
|
}
|
|
11452
11473
|
],
|
|
11453
11474
|
example: `<Tabs.Root bind:value={activeTab}>
|
|
@@ -14626,11 +14647,11 @@ var spec_default = {
|
|
|
14626
14647
|
tree: [
|
|
14627
14648
|
"Timeline.Root",
|
|
14628
14649
|
" Timeline.Item",
|
|
14629
|
-
"
|
|
14630
|
-
"
|
|
14631
|
-
"
|
|
14632
|
-
"
|
|
14633
|
-
"
|
|
14650
|
+
" Timeline.Icon",
|
|
14651
|
+
" Timeline.Content",
|
|
14652
|
+
" Timeline.Title",
|
|
14653
|
+
" Timeline.Description",
|
|
14654
|
+
" Timeline.Time"
|
|
14634
14655
|
]
|
|
14635
14656
|
},
|
|
14636
14657
|
cssVars: {
|
|
@@ -14668,12 +14689,14 @@ var spec_default = {
|
|
|
14668
14689
|
}
|
|
14669
14690
|
],
|
|
14670
14691
|
example: `<Timeline.Root>
|
|
14671
|
-
<Timeline.Item
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14692
|
+
<Timeline.Item>
|
|
14693
|
+
<Timeline.Icon />
|
|
14694
|
+
<Timeline.Content>
|
|
14695
|
+
<Timeline.Title>Event title</Timeline.Title>
|
|
14696
|
+
<Timeline.Description>Event description</Timeline.Description>
|
|
14697
|
+
<Timeline.Time>2 hours ago</Timeline.Time>
|
|
14698
|
+
</Timeline.Content>
|
|
14699
|
+
</Timeline.Item>
|
|
14677
14700
|
</Timeline.Root>`
|
|
14678
14701
|
},
|
|
14679
14702
|
Typography: {
|
|
@@ -16372,6 +16395,7 @@ var spec_default = {
|
|
|
16372
16395
|
]
|
|
16373
16396
|
},
|
|
16374
16397
|
cssVars: {
|
|
16398
|
+
"--dry-calendar-grid-gap": "Grid Gap",
|
|
16375
16399
|
"--dry-dp-bg": "Background color",
|
|
16376
16400
|
"--dry-dp-border": "Border color",
|
|
16377
16401
|
"--dry-dp-font-size": "Font size",
|
|
@@ -16379,9 +16403,33 @@ var spec_default = {
|
|
|
16379
16403
|
"--dry-dp-padding-y": "Vertical padding"
|
|
16380
16404
|
},
|
|
16381
16405
|
dataAttributes: [
|
|
16406
|
+
{
|
|
16407
|
+
name: "data-calendar-cell"
|
|
16408
|
+
},
|
|
16409
|
+
{
|
|
16410
|
+
name: "data-calendar-columnheader"
|
|
16411
|
+
},
|
|
16382
16412
|
{
|
|
16383
16413
|
name: "data-calendar-day"
|
|
16384
16414
|
},
|
|
16415
|
+
{
|
|
16416
|
+
name: "data-calendar-day-button"
|
|
16417
|
+
},
|
|
16418
|
+
{
|
|
16419
|
+
name: "data-calendar-header"
|
|
16420
|
+
},
|
|
16421
|
+
{
|
|
16422
|
+
name: "data-calendar-heading"
|
|
16423
|
+
},
|
|
16424
|
+
{
|
|
16425
|
+
name: "data-calendar-nav"
|
|
16426
|
+
},
|
|
16427
|
+
{
|
|
16428
|
+
name: "data-calendar-panel"
|
|
16429
|
+
},
|
|
16430
|
+
{
|
|
16431
|
+
name: "data-calendar-row"
|
|
16432
|
+
},
|
|
16385
16433
|
{
|
|
16386
16434
|
name: "data-disabled",
|
|
16387
16435
|
description: "Present when the component or part is disabled."
|
|
@@ -16395,6 +16443,9 @@ var spec_default = {
|
|
|
16395
16443
|
{
|
|
16396
16444
|
name: "data-dp-trigger"
|
|
16397
16445
|
},
|
|
16446
|
+
{
|
|
16447
|
+
name: "data-indicator"
|
|
16448
|
+
},
|
|
16398
16449
|
{
|
|
16399
16450
|
name: "data-invalid",
|
|
16400
16451
|
description: "Present when the current field value is invalid."
|
|
@@ -16858,9 +16909,33 @@ var spec_default = {
|
|
|
16858
16909
|
},
|
|
16859
16910
|
cssVars: {},
|
|
16860
16911
|
dataAttributes: [
|
|
16912
|
+
{
|
|
16913
|
+
name: "data-calendar-cell"
|
|
16914
|
+
},
|
|
16915
|
+
{
|
|
16916
|
+
name: "data-calendar-columnheader"
|
|
16917
|
+
},
|
|
16861
16918
|
{
|
|
16862
16919
|
name: "data-calendar-day"
|
|
16863
16920
|
},
|
|
16921
|
+
{
|
|
16922
|
+
name: "data-calendar-day-button"
|
|
16923
|
+
},
|
|
16924
|
+
{
|
|
16925
|
+
name: "data-calendar-header"
|
|
16926
|
+
},
|
|
16927
|
+
{
|
|
16928
|
+
name: "data-calendar-heading"
|
|
16929
|
+
},
|
|
16930
|
+
{
|
|
16931
|
+
name: "data-calendar-nav"
|
|
16932
|
+
},
|
|
16933
|
+
{
|
|
16934
|
+
name: "data-calendar-panel"
|
|
16935
|
+
},
|
|
16936
|
+
{
|
|
16937
|
+
name: "data-calendar-row"
|
|
16938
|
+
},
|
|
16864
16939
|
{
|
|
16865
16940
|
name: "data-disabled",
|
|
16866
16941
|
description: "Present when the component or part is disabled."
|
|
@@ -16874,15 +16949,15 @@ var spec_default = {
|
|
|
16874
16949
|
{
|
|
16875
16950
|
name: "data-drp-preset"
|
|
16876
16951
|
},
|
|
16877
|
-
{
|
|
16878
|
-
name: "data-drp-root"
|
|
16879
|
-
},
|
|
16880
16952
|
{
|
|
16881
16953
|
name: "data-drp-trigger"
|
|
16882
16954
|
},
|
|
16883
16955
|
{
|
|
16884
16956
|
name: "data-in-range"
|
|
16885
16957
|
},
|
|
16958
|
+
{
|
|
16959
|
+
name: "data-indicator"
|
|
16960
|
+
},
|
|
16886
16961
|
{
|
|
16887
16962
|
name: "data-outside-month"
|
|
16888
16963
|
},
|
|
@@ -17416,8 +17491,14 @@ var spec_default = {
|
|
|
17416
17491
|
"--dry-range-calendar-day-hover-bg": "Calendar Day Hover Bg",
|
|
17417
17492
|
"--dry-range-calendar-day-radius": "Calendar Day Radius",
|
|
17418
17493
|
"--dry-range-calendar-day-size": "Calendar Day Size",
|
|
17494
|
+
"--dry-range-calendar-heading-color": "Calendar Heading Color",
|
|
17495
|
+
"--dry-range-calendar-nav-bg": "Calendar Nav Bg",
|
|
17496
|
+
"--dry-range-calendar-nav-border": "Calendar Nav Border",
|
|
17497
|
+
"--dry-range-calendar-nav-color": "Calendar Nav Color",
|
|
17419
17498
|
"--dry-range-calendar-outside-color": "Calendar Outside Color",
|
|
17420
17499
|
"--dry-range-calendar-padding": "Calendar Padding",
|
|
17500
|
+
"--dry-range-calendar-panel-bg": "Calendar Panel Bg",
|
|
17501
|
+
"--dry-range-calendar-panel-border": "Calendar Panel Border",
|
|
17421
17502
|
"--dry-range-calendar-radius": "Calendar Radius",
|
|
17422
17503
|
"--dry-range-calendar-range-bg": "Calendar Range Bg",
|
|
17423
17504
|
"--dry-range-calendar-selected-bg": "Calendar Selected Bg",
|
|
@@ -17427,12 +17508,33 @@ var spec_default = {
|
|
|
17427
17508
|
"--dry-range-calendar-today-color": "Calendar Today Color"
|
|
17428
17509
|
},
|
|
17429
17510
|
dataAttributes: [
|
|
17511
|
+
{
|
|
17512
|
+
name: "data-calendar-cell"
|
|
17513
|
+
},
|
|
17514
|
+
{
|
|
17515
|
+
name: "data-calendar-columnheader"
|
|
17516
|
+
},
|
|
17430
17517
|
{
|
|
17431
17518
|
name: "data-calendar-day"
|
|
17432
17519
|
},
|
|
17520
|
+
{
|
|
17521
|
+
name: "data-calendar-day-button"
|
|
17522
|
+
},
|
|
17433
17523
|
{
|
|
17434
17524
|
name: "data-calendar-header"
|
|
17435
17525
|
},
|
|
17526
|
+
{
|
|
17527
|
+
name: "data-calendar-heading"
|
|
17528
|
+
},
|
|
17529
|
+
{
|
|
17530
|
+
name: "data-calendar-nav"
|
|
17531
|
+
},
|
|
17532
|
+
{
|
|
17533
|
+
name: "data-calendar-panel"
|
|
17534
|
+
},
|
|
17535
|
+
{
|
|
17536
|
+
name: "data-calendar-row"
|
|
17537
|
+
},
|
|
17436
17538
|
{
|
|
17437
17539
|
name: "data-disabled",
|
|
17438
17540
|
description: "Present when the component or part is disabled."
|
|
@@ -17455,10 +17557,6 @@ var spec_default = {
|
|
|
17455
17557
|
{
|
|
17456
17558
|
name: "data-range-start"
|
|
17457
17559
|
},
|
|
17458
|
-
{
|
|
17459
|
-
name: "data-selected",
|
|
17460
|
-
description: "Present when the current item is selected."
|
|
17461
|
-
},
|
|
17462
17560
|
{
|
|
17463
17561
|
name: "data-today"
|
|
17464
17562
|
}
|
|
@@ -17590,6 +17688,26 @@ var spec_default = {
|
|
|
17590
17688
|
type: "number",
|
|
17591
17689
|
required: false,
|
|
17592
17690
|
description: "Step interval used when incrementing numeric values."
|
|
17691
|
+
},
|
|
17692
|
+
size: {
|
|
17693
|
+
type: "'sm' | 'md' | 'lg'",
|
|
17694
|
+
required: false,
|
|
17695
|
+
acceptedValues: [
|
|
17696
|
+
"sm",
|
|
17697
|
+
"md",
|
|
17698
|
+
"lg"
|
|
17699
|
+
],
|
|
17700
|
+
description: "Size preset affecting density, spacing, or typography.",
|
|
17701
|
+
default: "'md'"
|
|
17702
|
+
},
|
|
17703
|
+
name: {
|
|
17704
|
+
type: "string",
|
|
17705
|
+
required: false,
|
|
17706
|
+
description: "Field name used during native form submission."
|
|
17707
|
+
},
|
|
17708
|
+
class: {
|
|
17709
|
+
type: "string",
|
|
17710
|
+
required: false
|
|
17593
17711
|
}
|
|
17594
17712
|
},
|
|
17595
17713
|
forwardedProps: {
|
|
@@ -17603,25 +17721,23 @@ var spec_default = {
|
|
|
17603
17721
|
],
|
|
17604
17722
|
note: "Forwards <input> attributes via rest props."
|
|
17605
17723
|
},
|
|
17606
|
-
cssVars: {
|
|
17607
|
-
"--dry-time-input-bg": "Input Bg",
|
|
17608
|
-
"--dry-time-input-border": "Input Border",
|
|
17609
|
-
"--dry-time-input-color": "Input Color",
|
|
17610
|
-
"--dry-time-input-font-size": "Input Font Size",
|
|
17611
|
-
"--dry-time-input-padding-x": "Input Padding X",
|
|
17612
|
-
"--dry-time-input-padding-y": "Input Padding Y",
|
|
17613
|
-
"--dry-time-input-radius": "Input Radius"
|
|
17614
|
-
},
|
|
17724
|
+
cssVars: {},
|
|
17615
17725
|
dataAttributes: [
|
|
17616
17726
|
{
|
|
17617
17727
|
name: "data-disabled",
|
|
17618
17728
|
description: "Present when the component or part is disabled."
|
|
17619
17729
|
},
|
|
17620
17730
|
{
|
|
17621
|
-
name: "data-
|
|
17731
|
+
name: "data-placeholder"
|
|
17732
|
+
},
|
|
17733
|
+
{
|
|
17734
|
+
name: "data-time-display"
|
|
17622
17735
|
},
|
|
17623
17736
|
{
|
|
17624
17737
|
name: "data-time-input-wrapper"
|
|
17738
|
+
},
|
|
17739
|
+
{
|
|
17740
|
+
name: "data-time-separator"
|
|
17625
17741
|
}
|
|
17626
17742
|
],
|
|
17627
17743
|
example: "<TimeInput>Content</TimeInput>"
|
|
@@ -17807,6 +17923,7 @@ var spec_default = {
|
|
|
17807
17923
|
},
|
|
17808
17924
|
cssVars: {
|
|
17809
17925
|
"--dry-tags-input-font-size": "Input Font Size",
|
|
17926
|
+
"--dry-tags-input-gap": "Input Gap",
|
|
17810
17927
|
"--dry-tags-input-tag-font-size": "Input Tag Font Size",
|
|
17811
17928
|
"--dry-tags-input-tag-padding-x": "Input Tag Padding X"
|
|
17812
17929
|
},
|
|
@@ -18078,9 +18195,6 @@ var spec_default = {
|
|
|
18078
18195
|
{
|
|
18079
18196
|
name: "data-dragging"
|
|
18080
18197
|
},
|
|
18081
|
-
{
|
|
18082
|
-
name: "data-file-upload"
|
|
18083
|
-
},
|
|
18084
18198
|
{
|
|
18085
18199
|
name: "data-fu-dropzone"
|
|
18086
18200
|
},
|
|
@@ -19313,6 +19427,7 @@ var spec_default = {
|
|
|
19313
19427
|
"--dry-fab-color": "Text color",
|
|
19314
19428
|
"--dry-fab-gap": "Gap spacing",
|
|
19315
19429
|
"--dry-fab-offset": "Offset",
|
|
19430
|
+
"--dry-fab-position": "Position",
|
|
19316
19431
|
"--dry-fab-shadow": "Box shadow",
|
|
19317
19432
|
"--dry-fab-z-index": "Z Index"
|
|
19318
19433
|
},
|
|
@@ -19705,7 +19820,8 @@ var spec_default = {
|
|
|
19705
19820
|
},
|
|
19706
19821
|
overscan: {
|
|
19707
19822
|
type: "number",
|
|
19708
|
-
required: false
|
|
19823
|
+
required: false,
|
|
19824
|
+
default: "5"
|
|
19709
19825
|
},
|
|
19710
19826
|
children: {
|
|
19711
19827
|
type: "Snippet<[{ item: T; index: number; style: string }]>",
|
|
@@ -20766,7 +20882,8 @@ var spec_default = {
|
|
|
20766
20882
|
placeholder: {
|
|
20767
20883
|
type: "string",
|
|
20768
20884
|
required: false,
|
|
20769
|
-
description: "Hint text shown when no value is selected or entered."
|
|
20885
|
+
description: "Hint text shown when no value is selected or entered.",
|
|
20886
|
+
default: "''"
|
|
20770
20887
|
},
|
|
20771
20888
|
readonly: {
|
|
20772
20889
|
type: "boolean",
|
|
@@ -20852,8 +20969,20 @@ var spec_default = {
|
|
|
20852
20969
|
{
|
|
20853
20970
|
name: "data-part"
|
|
20854
20971
|
},
|
|
20972
|
+
{
|
|
20973
|
+
name: "data-placeholder"
|
|
20974
|
+
},
|
|
20855
20975
|
{
|
|
20856
20976
|
name: "data-readonly"
|
|
20977
|
+
},
|
|
20978
|
+
{
|
|
20979
|
+
name: "data-rte-content"
|
|
20980
|
+
},
|
|
20981
|
+
{
|
|
20982
|
+
name: "data-rte-root"
|
|
20983
|
+
},
|
|
20984
|
+
{
|
|
20985
|
+
name: "data-rte-toolbar"
|
|
20857
20986
|
}
|
|
20858
20987
|
],
|
|
20859
20988
|
example: `<RichTextEditor.Root>
|
|
@@ -23746,18 +23875,6 @@ var spec_default = {
|
|
|
23746
23875
|
"--dry-map-radius": "Border radius"
|
|
23747
23876
|
},
|
|
23748
23877
|
dataAttributes: [
|
|
23749
|
-
{
|
|
23750
|
-
name: "data-map-mapboxgl"
|
|
23751
|
-
},
|
|
23752
|
-
{
|
|
23753
|
-
name: "data-map-maplibregl"
|
|
23754
|
-
},
|
|
23755
|
-
{
|
|
23756
|
-
name: "data-map-marker"
|
|
23757
|
-
},
|
|
23758
|
-
{
|
|
23759
|
-
name: "data-map-popup"
|
|
23760
|
-
},
|
|
23761
23878
|
{
|
|
23762
23879
|
name: "data-map-root"
|
|
23763
23880
|
},
|
|
@@ -23774,7 +23891,7 @@ var spec_default = {
|
|
|
23774
23891
|
},
|
|
23775
23892
|
SystemMap: {
|
|
23776
23893
|
import: "@dryui/ui",
|
|
23777
|
-
description: "Layered architecture diagram
|
|
23894
|
+
description: "Layered architecture diagram that visualizes component nodes, relationships, and dependency layers",
|
|
23778
23895
|
category: "display",
|
|
23779
23896
|
tags: [
|
|
23780
23897
|
"diagram",
|
|
@@ -23845,92 +23962,40 @@ var spec_default = {
|
|
|
23845
23962
|
],
|
|
23846
23963
|
note: "Forwards <div> attributes via rest props."
|
|
23847
23964
|
},
|
|
23848
|
-
cssVars: {
|
|
23849
|
-
"--dry-system-map-bg": "Map Bg",
|
|
23850
|
-
"--dry-system-map-border": "Map Border",
|
|
23851
|
-
"--dry-system-map-shadow": "Map Shadow",
|
|
23852
|
-
"--dry-system-map-surface": "Map Surface",
|
|
23853
|
-
"--dry-system-map-text": "Map Text",
|
|
23854
|
-
"--dry-system-map-text-muted": "Map Text Muted"
|
|
23855
|
-
},
|
|
23965
|
+
cssVars: {},
|
|
23856
23966
|
dataAttributes: [
|
|
23857
23967
|
{
|
|
23858
|
-
name: "data-
|
|
23859
|
-
},
|
|
23860
|
-
{
|
|
23861
|
-
name: "data-dashed"
|
|
23862
|
-
},
|
|
23863
|
-
{
|
|
23864
|
-
name: "data-edge-label"
|
|
23968
|
+
name: "data-connector"
|
|
23865
23969
|
},
|
|
23866
23970
|
{
|
|
23867
|
-
name: "data-
|
|
23971
|
+
name: "data-connector-label"
|
|
23868
23972
|
},
|
|
23869
23973
|
{
|
|
23870
|
-
name: "data-
|
|
23974
|
+
name: "data-connector-line"
|
|
23871
23975
|
},
|
|
23872
23976
|
{
|
|
23873
|
-
name: "data-
|
|
23977
|
+
name: "data-edge-row"
|
|
23874
23978
|
},
|
|
23875
23979
|
{
|
|
23876
|
-
name: "data-
|
|
23877
|
-
},
|
|
23878
|
-
{
|
|
23879
|
-
name: "data-header"
|
|
23880
|
-
},
|
|
23881
|
-
{
|
|
23882
|
-
name: "data-header-badges"
|
|
23883
|
-
},
|
|
23884
|
-
{
|
|
23885
|
-
name: "data-header-text"
|
|
23886
|
-
},
|
|
23887
|
-
{
|
|
23888
|
-
name: "data-lane-meta"
|
|
23889
|
-
},
|
|
23890
|
-
{
|
|
23891
|
-
name: "data-lane-title"
|
|
23892
|
-
},
|
|
23893
|
-
{
|
|
23894
|
-
name: "data-legend"
|
|
23895
|
-
},
|
|
23896
|
-
{
|
|
23897
|
-
name: "data-legend-item"
|
|
23898
|
-
},
|
|
23899
|
-
{
|
|
23900
|
-
name: "data-legend-items"
|
|
23901
|
-
},
|
|
23902
|
-
{
|
|
23903
|
-
name: "data-legend-section"
|
|
23904
|
-
},
|
|
23905
|
-
{
|
|
23906
|
-
name: "data-line-swatch"
|
|
23907
|
-
},
|
|
23908
|
-
{
|
|
23909
|
-
name: "data-map-title"
|
|
23910
|
-
},
|
|
23911
|
-
{
|
|
23912
|
-
name: "data-node-description"
|
|
23980
|
+
name: "data-empty"
|
|
23913
23981
|
},
|
|
23914
23982
|
{
|
|
23915
|
-
name: "data-
|
|
23983
|
+
name: "data-focused"
|
|
23916
23984
|
},
|
|
23917
23985
|
{
|
|
23918
|
-
name: "data-node
|
|
23986
|
+
name: "data-node"
|
|
23919
23987
|
},
|
|
23920
23988
|
{
|
|
23921
|
-
name: "data-
|
|
23989
|
+
name: "data-node-helper"
|
|
23922
23990
|
},
|
|
23923
23991
|
{
|
|
23924
|
-
name: "data-
|
|
23992
|
+
name: "data-node-name"
|
|
23925
23993
|
},
|
|
23926
23994
|
{
|
|
23927
|
-
name: "data-
|
|
23995
|
+
name: "data-orphans"
|
|
23928
23996
|
},
|
|
23929
23997
|
{
|
|
23930
23998
|
name: "data-system-map"
|
|
23931
|
-
},
|
|
23932
|
-
{
|
|
23933
|
-
name: "data-thumbnail-object"
|
|
23934
23999
|
}
|
|
23935
24000
|
],
|
|
23936
24001
|
example: "<SystemMap>Content</SystemMap>"
|
|
@@ -24386,8 +24451,7 @@ var spec_default = {
|
|
|
24386
24451
|
},
|
|
24387
24452
|
blendMode: {
|
|
24388
24453
|
type: "BlendMode",
|
|
24389
|
-
required: false
|
|
24390
|
-
default: "'screen'"
|
|
24454
|
+
required: false
|
|
24391
24455
|
},
|
|
24392
24456
|
children: {
|
|
24393
24457
|
type: "Snippet",
|
|
@@ -29995,7 +30059,7 @@ body { margin: 0; min-height: 100dvh; }
|
|
|
29995
30059
|
},
|
|
29996
30060
|
"simple-content-page": {
|
|
29997
30061
|
name: "simple-content-page",
|
|
29998
|
-
description: "Clean content page with constrained width and vertical rhythm. Use Container for max-width and
|
|
30062
|
+
description: "Clean content page with constrained width and vertical rhythm. Use Container for max-width and CSS grid for vertical spacing. Suitable for blog posts, documentation, settings pages.",
|
|
29999
30063
|
tags: [
|
|
30000
30064
|
"page",
|
|
30001
30065
|
"content",
|
|
@@ -31679,13 +31743,715 @@ body { margin: 0; min-height: 100dvh; }
|
|
|
31679
31743
|
]
|
|
31680
31744
|
};
|
|
31681
31745
|
|
|
31682
|
-
// ../mcp/src/
|
|
31746
|
+
// ../mcp/src/project-planner.ts
|
|
31747
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
31748
|
+
import { dirname, resolve } from "node:path";
|
|
31683
31749
|
var DIR_OVERRIDES = {
|
|
31684
31750
|
QRCode: "qr-code"
|
|
31685
31751
|
};
|
|
31686
31752
|
function componentDir(name) {
|
|
31687
31753
|
return DIR_OVERRIDES[name] ?? name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
31688
31754
|
}
|
|
31755
|
+
function resolveStart(inputPath) {
|
|
31756
|
+
const candidate = resolve(inputPath ?? process.cwd());
|
|
31757
|
+
return existsSync(candidate) && statSync(candidate).isFile() ? dirname(candidate) : candidate;
|
|
31758
|
+
}
|
|
31759
|
+
function findUp(start, fileName) {
|
|
31760
|
+
let current = start;
|
|
31761
|
+
while (true) {
|
|
31762
|
+
const candidate = resolve(current, fileName);
|
|
31763
|
+
if (existsSync(candidate))
|
|
31764
|
+
return candidate;
|
|
31765
|
+
const parent = dirname(current);
|
|
31766
|
+
if (parent === current)
|
|
31767
|
+
return null;
|
|
31768
|
+
current = parent;
|
|
31769
|
+
}
|
|
31770
|
+
}
|
|
31771
|
+
function findUpAny(start, fileNames) {
|
|
31772
|
+
let current = start;
|
|
31773
|
+
while (true) {
|
|
31774
|
+
for (const fileName of fileNames) {
|
|
31775
|
+
const candidate = resolve(current, fileName);
|
|
31776
|
+
if (existsSync(candidate))
|
|
31777
|
+
return candidate;
|
|
31778
|
+
}
|
|
31779
|
+
const parent = dirname(current);
|
|
31780
|
+
if (parent === current)
|
|
31781
|
+
return null;
|
|
31782
|
+
current = parent;
|
|
31783
|
+
}
|
|
31784
|
+
}
|
|
31785
|
+
function detectPackageManager(root) {
|
|
31786
|
+
if (!root)
|
|
31787
|
+
return "unknown";
|
|
31788
|
+
const lockfilePath = findUpAny(root, [
|
|
31789
|
+
"bun.lock",
|
|
31790
|
+
"bun.lockb",
|
|
31791
|
+
"pnpm-lock.yaml",
|
|
31792
|
+
"package-lock.json",
|
|
31793
|
+
"yarn.lock"
|
|
31794
|
+
]);
|
|
31795
|
+
if (!lockfilePath)
|
|
31796
|
+
return "unknown";
|
|
31797
|
+
if (lockfilePath.endsWith("bun.lock") || lockfilePath.endsWith("bun.lockb"))
|
|
31798
|
+
return "bun";
|
|
31799
|
+
if (lockfilePath.endsWith("pnpm-lock.yaml"))
|
|
31800
|
+
return "pnpm";
|
|
31801
|
+
if (lockfilePath.endsWith("package-lock.json"))
|
|
31802
|
+
return "npm";
|
|
31803
|
+
if (lockfilePath.endsWith("yarn.lock"))
|
|
31804
|
+
return "yarn";
|
|
31805
|
+
return "unknown";
|
|
31806
|
+
}
|
|
31807
|
+
function readPackageJson(packageJsonPath) {
|
|
31808
|
+
if (!packageJsonPath)
|
|
31809
|
+
return null;
|
|
31810
|
+
return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
31811
|
+
}
|
|
31812
|
+
function getDependencyNames(pkg) {
|
|
31813
|
+
return new Set([
|
|
31814
|
+
...Object.keys(pkg?.dependencies ?? {}),
|
|
31815
|
+
...Object.keys(pkg?.devDependencies ?? {})
|
|
31816
|
+
]);
|
|
31817
|
+
}
|
|
31818
|
+
function detectFramework(dependencyNames) {
|
|
31819
|
+
if (dependencyNames.has("@sveltejs/kit"))
|
|
31820
|
+
return "sveltekit";
|
|
31821
|
+
if (dependencyNames.has("svelte"))
|
|
31822
|
+
return "svelte";
|
|
31823
|
+
return "unknown";
|
|
31824
|
+
}
|
|
31825
|
+
function hasImport(filePath, importPath) {
|
|
31826
|
+
if (!filePath)
|
|
31827
|
+
return false;
|
|
31828
|
+
return readFileSync(filePath, "utf-8").includes(importPath);
|
|
31829
|
+
}
|
|
31830
|
+
function hasThemeAuto(appHtmlPath) {
|
|
31831
|
+
if (!appHtmlPath)
|
|
31832
|
+
return false;
|
|
31833
|
+
return readFileSync(appHtmlPath, "utf-8").includes("theme-auto");
|
|
31834
|
+
}
|
|
31835
|
+
function hasAnyImport(filePaths, importPath) {
|
|
31836
|
+
return filePaths.some((filePath) => hasImport(filePath, importPath));
|
|
31837
|
+
}
|
|
31838
|
+
function importsAppCss(rootLayoutPath) {
|
|
31839
|
+
if (!rootLayoutPath)
|
|
31840
|
+
return false;
|
|
31841
|
+
const content = readFileSync(rootLayoutPath, "utf-8");
|
|
31842
|
+
return content.includes("app.css");
|
|
31843
|
+
}
|
|
31844
|
+
function buildStatus(framework, hasPackageJson, stepsNeeded) {
|
|
31845
|
+
if (!hasPackageJson || framework === "unknown")
|
|
31846
|
+
return "unsupported";
|
|
31847
|
+
return stepsNeeded === 0 ? "ready" : "partial";
|
|
31848
|
+
}
|
|
31849
|
+
function installCommand(packageManager) {
|
|
31850
|
+
switch (packageManager) {
|
|
31851
|
+
case "bun":
|
|
31852
|
+
return "bun add @dryui/ui";
|
|
31853
|
+
case "pnpm":
|
|
31854
|
+
return "pnpm add @dryui/ui";
|
|
31855
|
+
case "yarn":
|
|
31856
|
+
return "yarn add @dryui/ui";
|
|
31857
|
+
default:
|
|
31858
|
+
return "npm install @dryui/ui";
|
|
31859
|
+
}
|
|
31860
|
+
}
|
|
31861
|
+
function buildThemeImportLines(spec) {
|
|
31862
|
+
return ` import '${spec.themeImports.default}';
|
|
31863
|
+
import '${spec.themeImports.dark}';`;
|
|
31864
|
+
}
|
|
31865
|
+
function buildThemeImportSnippet(spec) {
|
|
31866
|
+
return ["<script>", buildThemeImportLines(spec), "</script>"].join(`
|
|
31867
|
+
`);
|
|
31868
|
+
}
|
|
31869
|
+
function buildRootLayoutSnippet(spec) {
|
|
31870
|
+
return [
|
|
31871
|
+
"<script>",
|
|
31872
|
+
buildThemeImportLines(spec),
|
|
31873
|
+
"",
|
|
31874
|
+
" let { children } = $props();",
|
|
31875
|
+
"</script>",
|
|
31876
|
+
"",
|
|
31877
|
+
"{@render children()}"
|
|
31878
|
+
].join(`
|
|
31879
|
+
`);
|
|
31880
|
+
}
|
|
31881
|
+
function buildThemeImportCssSnippet(spec) {
|
|
31882
|
+
return [`@import '${spec.themeImports.default}';`, `@import '${spec.themeImports.dark}';`].join(`
|
|
31883
|
+
`);
|
|
31884
|
+
}
|
|
31885
|
+
function getSuggestedTarget(root, explicitTarget) {
|
|
31886
|
+
if (explicitTarget)
|
|
31887
|
+
return resolve(root ?? process.cwd(), explicitTarget);
|
|
31888
|
+
if (!root)
|
|
31889
|
+
return null;
|
|
31890
|
+
const rootPage = resolve(root, "src/routes/+page.svelte");
|
|
31891
|
+
return existsSync(rootPage) ? rootPage : null;
|
|
31892
|
+
}
|
|
31893
|
+
function getImportStatement(name, component, subpath = false) {
|
|
31894
|
+
if (subpath && component.import === "@dryui/ui") {
|
|
31895
|
+
return `import { ${name} } from '${component.import}/${componentDir(name)}';`;
|
|
31896
|
+
}
|
|
31897
|
+
return `import { ${name} } from '${component.import}';`;
|
|
31898
|
+
}
|
|
31899
|
+
function findComponent(spec, query) {
|
|
31900
|
+
const exact = spec.components[query];
|
|
31901
|
+
if (exact)
|
|
31902
|
+
return { name: query, def: exact };
|
|
31903
|
+
const lower = query.toLowerCase();
|
|
31904
|
+
for (const [name, def] of Object.entries(spec.components)) {
|
|
31905
|
+
if (name.toLowerCase() === lower)
|
|
31906
|
+
return { name, def };
|
|
31907
|
+
}
|
|
31908
|
+
return null;
|
|
31909
|
+
}
|
|
31910
|
+
function detectProject(spec, inputPath) {
|
|
31911
|
+
const start = resolveStart(inputPath);
|
|
31912
|
+
const packageJsonPath = findUp(start, "package.json");
|
|
31913
|
+
const root = packageJsonPath ? dirname(packageJsonPath) : null;
|
|
31914
|
+
const dependencyNames = getDependencyNames(readPackageJson(packageJsonPath));
|
|
31915
|
+
const framework = detectFramework(dependencyNames);
|
|
31916
|
+
const appHtmlPath = root ? resolve(root, "src/app.html") : null;
|
|
31917
|
+
const appCssPath = root ? resolve(root, "src/app.css") : null;
|
|
31918
|
+
const rootLayoutPath = root ? resolve(root, "src/routes/+layout.svelte") : null;
|
|
31919
|
+
const rootPagePath = root ? resolve(root, "src/routes/+page.svelte") : null;
|
|
31920
|
+
const appHtml = appHtmlPath && existsSync(appHtmlPath) ? appHtmlPath : null;
|
|
31921
|
+
const appCss = appCssPath && existsSync(appCssPath) ? appCssPath : null;
|
|
31922
|
+
const rootLayout = rootLayoutPath && existsSync(rootLayoutPath) ? rootLayoutPath : null;
|
|
31923
|
+
const rootPage = rootPagePath && existsSync(rootPagePath) ? rootPagePath : null;
|
|
31924
|
+
const themeImportFiles = rootLayout && importsAppCss(rootLayout) ? [rootLayout, appCss] : [rootLayout];
|
|
31925
|
+
const defaultImported = hasAnyImport(themeImportFiles, spec.themeImports.default);
|
|
31926
|
+
const darkImported = hasAnyImport(themeImportFiles, spec.themeImports.dark);
|
|
31927
|
+
const themeAuto = appHtml ? hasThemeAuto(appHtml) : false;
|
|
31928
|
+
const stepsNeeded = Number(!dependencyNames.has("@dryui/ui")) + Number(!defaultImported) + Number(!darkImported) + Number(!themeAuto);
|
|
31929
|
+
const warnings = [];
|
|
31930
|
+
if (!packageJsonPath)
|
|
31931
|
+
warnings.push("No package.json found above the provided path.");
|
|
31932
|
+
if (framework === "unknown")
|
|
31933
|
+
warnings.push("DryUI planning currently targets Svelte and SvelteKit projects.");
|
|
31934
|
+
return {
|
|
31935
|
+
inputPath: start,
|
|
31936
|
+
root,
|
|
31937
|
+
packageJsonPath,
|
|
31938
|
+
framework,
|
|
31939
|
+
packageManager: detectPackageManager(root),
|
|
31940
|
+
status: buildStatus(framework, Boolean(packageJsonPath), stepsNeeded),
|
|
31941
|
+
dependencies: {
|
|
31942
|
+
ui: dependencyNames.has("@dryui/ui"),
|
|
31943
|
+
primitives: dependencyNames.has("@dryui/primitives")
|
|
31944
|
+
},
|
|
31945
|
+
files: {
|
|
31946
|
+
appHtml,
|
|
31947
|
+
appCss,
|
|
31948
|
+
rootLayout,
|
|
31949
|
+
rootPage
|
|
31950
|
+
},
|
|
31951
|
+
theme: {
|
|
31952
|
+
defaultImported,
|
|
31953
|
+
darkImported,
|
|
31954
|
+
themeAuto
|
|
31955
|
+
},
|
|
31956
|
+
warnings
|
|
31957
|
+
};
|
|
31958
|
+
}
|
|
31959
|
+
function planInstall(spec, inputPath) {
|
|
31960
|
+
const detection = detectProject(spec, inputPath);
|
|
31961
|
+
const steps = [];
|
|
31962
|
+
if (detection.status === "unsupported") {
|
|
31963
|
+
steps.push({
|
|
31964
|
+
kind: "blocked",
|
|
31965
|
+
status: "blocked",
|
|
31966
|
+
title: "Project detection incomplete",
|
|
31967
|
+
description: detection.warnings.join(" ") || "DryUI install planning requires a Svelte or SvelteKit project with a package.json."
|
|
31968
|
+
});
|
|
31969
|
+
return { detection, steps };
|
|
31970
|
+
}
|
|
31971
|
+
if (!detection.dependencies.ui) {
|
|
31972
|
+
steps.push({
|
|
31973
|
+
kind: "install-package",
|
|
31974
|
+
status: "pending",
|
|
31975
|
+
title: "Install @dryui/ui",
|
|
31976
|
+
description: "Add the styled DryUI package to the current project.",
|
|
31977
|
+
command: installCommand(detection.packageManager)
|
|
31978
|
+
});
|
|
31979
|
+
}
|
|
31980
|
+
if (!detection.theme.defaultImported || !detection.theme.darkImported) {
|
|
31981
|
+
if (detection.files.appCss && detection.files.rootLayout && importsAppCss(detection.files.rootLayout)) {
|
|
31982
|
+
steps.push({
|
|
31983
|
+
kind: "edit-file",
|
|
31984
|
+
status: "pending",
|
|
31985
|
+
title: "Add theme imports to app.css",
|
|
31986
|
+
description: "Prepend the two @import lines from the snippet to the TOP of the existing src/app.css file, before any other CSS rules. Do not create a second file.",
|
|
31987
|
+
path: detection.files.appCss,
|
|
31988
|
+
snippet: buildThemeImportCssSnippet(spec)
|
|
31989
|
+
});
|
|
31990
|
+
} else if (!detection.files.rootLayout) {
|
|
31991
|
+
const path = detection.root ? resolve(detection.root, "src/routes/+layout.svelte") : null;
|
|
31992
|
+
steps.push({
|
|
31993
|
+
kind: "create-file",
|
|
31994
|
+
status: "pending",
|
|
31995
|
+
title: "Create root layout with theme imports",
|
|
31996
|
+
description: "Create the file at the path below with the snippet as its full content. The file must include {@render children()} or pages will not render.",
|
|
31997
|
+
...path ? { path } : {},
|
|
31998
|
+
snippet: buildRootLayoutSnippet(spec)
|
|
31999
|
+
});
|
|
32000
|
+
} else {
|
|
32001
|
+
steps.push({
|
|
32002
|
+
kind: "edit-file",
|
|
32003
|
+
status: "pending",
|
|
32004
|
+
title: "Add theme imports to the root layout",
|
|
32005
|
+
description: "Add the two import lines from the snippet into the EXISTING <script> block in this file. Do not create a second <script> block. If no <script> block exists, add one at the top of the file.",
|
|
32006
|
+
path: detection.files.rootLayout,
|
|
32007
|
+
snippet: buildThemeImportSnippet(spec)
|
|
32008
|
+
});
|
|
32009
|
+
}
|
|
32010
|
+
}
|
|
32011
|
+
if (!detection.files.appHtml) {
|
|
32012
|
+
steps.push({
|
|
32013
|
+
kind: "blocked",
|
|
32014
|
+
status: "blocked",
|
|
32015
|
+
title: "app.html not found",
|
|
32016
|
+
description: "DryUI expects src/app.html so the document can default to theme-auto mode."
|
|
32017
|
+
});
|
|
32018
|
+
} else if (!detection.theme.themeAuto) {
|
|
32019
|
+
steps.push({
|
|
32020
|
+
kind: "edit-file",
|
|
32021
|
+
status: "pending",
|
|
32022
|
+
title: "Set html theme mode to auto",
|
|
32023
|
+
description: 'In src/app.html, find the opening <html> tag (e.g. <html lang="en">) and add class="theme-auto" to it, preserving any existing attributes. Result should be like <html lang="en" class="theme-auto">. Do NOT add a second <html> element.',
|
|
32024
|
+
path: detection.files.appHtml,
|
|
32025
|
+
snippet: 'class="theme-auto"'
|
|
32026
|
+
});
|
|
32027
|
+
}
|
|
32028
|
+
if (steps.length === 0) {
|
|
32029
|
+
steps.push({
|
|
32030
|
+
kind: "note",
|
|
32031
|
+
status: "done",
|
|
32032
|
+
title: "DryUI install plan is complete",
|
|
32033
|
+
description: "The project already has @dryui/ui, theme imports, and theme-auto configured."
|
|
32034
|
+
});
|
|
32035
|
+
}
|
|
32036
|
+
return { detection, steps };
|
|
32037
|
+
}
|
|
32038
|
+
function planAdd(spec, query, options = {}) {
|
|
32039
|
+
const installPlan = planInstall(spec, options.cwd);
|
|
32040
|
+
const component = findComponent(spec, query);
|
|
32041
|
+
if (component) {
|
|
32042
|
+
const target = getSuggestedTarget(installPlan.detection.root, options.target);
|
|
32043
|
+
const steps = [];
|
|
32044
|
+
const warnings = [...installPlan.detection.warnings];
|
|
32045
|
+
if (installPlan.steps.some((step) => step.status === "pending" || step.status === "blocked")) {
|
|
32046
|
+
steps.push({
|
|
32047
|
+
kind: "note",
|
|
32048
|
+
status: "info",
|
|
32049
|
+
title: "Complete install plan first",
|
|
32050
|
+
description: "Apply the install plan before inserting DryUI components into project files."
|
|
32051
|
+
});
|
|
32052
|
+
}
|
|
32053
|
+
steps.push(target ? {
|
|
32054
|
+
kind: "edit-file",
|
|
32055
|
+
status: "pending",
|
|
32056
|
+
title: "Insert component into the target file",
|
|
32057
|
+
description: "Add the import and snippet below to the chosen Svelte file.",
|
|
32058
|
+
path: target,
|
|
32059
|
+
snippet: `${getImportStatement(component.name, component.def, options.subpath)}
|
|
32060
|
+
|
|
32061
|
+
${component.def.example}`
|
|
32062
|
+
} : {
|
|
32063
|
+
kind: "note",
|
|
32064
|
+
status: "info",
|
|
32065
|
+
title: "Choose a target Svelte file",
|
|
32066
|
+
description: "No root page was found. Pick a target file and reuse the import and snippet in this plan."
|
|
32067
|
+
});
|
|
32068
|
+
return {
|
|
32069
|
+
detection: installPlan.detection,
|
|
32070
|
+
installPlan,
|
|
32071
|
+
targetType: "component",
|
|
32072
|
+
name: component.name,
|
|
32073
|
+
importStatement: getImportStatement(component.name, component.def, options.subpath),
|
|
32074
|
+
snippet: component.def.example,
|
|
32075
|
+
target,
|
|
32076
|
+
steps,
|
|
32077
|
+
warnings
|
|
32078
|
+
};
|
|
32079
|
+
}
|
|
32080
|
+
throw new Error(`Unknown component: "${query}"`);
|
|
32081
|
+
}
|
|
32082
|
+
|
|
32083
|
+
// ../mcp/dist/toon.js
|
|
32084
|
+
function esc(value) {
|
|
32085
|
+
if (value.includes(",") || value.includes(`
|
|
32086
|
+
`)) {
|
|
32087
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
32088
|
+
}
|
|
32089
|
+
return value;
|
|
32090
|
+
}
|
|
32091
|
+
function header(resource, count, fields) {
|
|
32092
|
+
return `${resource}[${count}]{${fields.join(",")}}:`;
|
|
32093
|
+
}
|
|
32094
|
+
function row(...values) {
|
|
32095
|
+
return " " + values.map((v) => esc(String(v))).join(",");
|
|
32096
|
+
}
|
|
32097
|
+
function truncate(text, maxLen, hint) {
|
|
32098
|
+
if (text.length <= maxLen)
|
|
32099
|
+
return text;
|
|
32100
|
+
return `(truncated, ${text.length} chars -- ${hint})`;
|
|
32101
|
+
}
|
|
32102
|
+
function buildContextualHelp(ctx) {
|
|
32103
|
+
const hints = [];
|
|
32104
|
+
switch (ctx.command) {
|
|
32105
|
+
case "info":
|
|
32106
|
+
if (ctx.componentName) {
|
|
32107
|
+
hints.push(`compose "${ctx.componentName.toLowerCase()}" -- see composition patterns`);
|
|
32108
|
+
hints.push(`add ${ctx.componentName} -- get starter snippet`);
|
|
32109
|
+
}
|
|
32110
|
+
break;
|
|
32111
|
+
case "list":
|
|
32112
|
+
hints.push("info <Component> -- see full API reference");
|
|
32113
|
+
break;
|
|
32114
|
+
case "compose":
|
|
32115
|
+
if (ctx.componentName) {
|
|
32116
|
+
hints.push(`info ${ctx.componentName} -- full API reference`);
|
|
32117
|
+
hints.push(`add ${ctx.componentName} -- starter snippet`);
|
|
32118
|
+
}
|
|
32119
|
+
break;
|
|
32120
|
+
case "review":
|
|
32121
|
+
if (ctx.hasErrors) {
|
|
32122
|
+
hints.push("info <Component> -- check API for errored component");
|
|
32123
|
+
hints.push("diagnose <file.css> -- check theme if theme warnings present");
|
|
32124
|
+
} else if (ctx.isEmpty) {
|
|
32125
|
+
hints.push("lint . -- check entire workspace");
|
|
32126
|
+
}
|
|
32127
|
+
break;
|
|
32128
|
+
case "diagnose":
|
|
32129
|
+
if (ctx.hasErrors) {
|
|
32130
|
+
hints.push('compose "app shell" -- get correct theme setup');
|
|
32131
|
+
} else if (ctx.isEmpty) {
|
|
32132
|
+
hints.push("review <file.svelte> -- validate component usage");
|
|
32133
|
+
}
|
|
32134
|
+
break;
|
|
32135
|
+
case "doctor":
|
|
32136
|
+
case "lint":
|
|
32137
|
+
if (ctx.hasFindings) {
|
|
32138
|
+
hints.push("lint --max-severity error -- focus on errors only");
|
|
32139
|
+
hints.push("review <file.svelte> -- check specific file");
|
|
32140
|
+
} else if (ctx.isEmpty) {
|
|
32141
|
+
hints.push("detect -- verify project setup");
|
|
32142
|
+
}
|
|
32143
|
+
break;
|
|
32144
|
+
case "detect":
|
|
32145
|
+
if (ctx.status === "partial" || ctx.status === "unsupported") {
|
|
32146
|
+
hints.push("install -- see step-by-step setup plan");
|
|
32147
|
+
} else if (ctx.status === "ready") {
|
|
32148
|
+
hints.push("list -- see available components");
|
|
32149
|
+
hints.push('compose "app shell" -- get root layout template');
|
|
32150
|
+
}
|
|
32151
|
+
break;
|
|
32152
|
+
case "install":
|
|
32153
|
+
hints.push("detect -- verify project after completing steps");
|
|
32154
|
+
break;
|
|
32155
|
+
}
|
|
32156
|
+
return hints;
|
|
32157
|
+
}
|
|
32158
|
+
function formatHelp(hints) {
|
|
32159
|
+
if (hints.length === 0)
|
|
32160
|
+
return "";
|
|
32161
|
+
const lines = [`next[${hints.length}]:`];
|
|
32162
|
+
for (const hint of hints) {
|
|
32163
|
+
lines.push(" " + hint);
|
|
32164
|
+
}
|
|
32165
|
+
return lines.join(`
|
|
32166
|
+
`);
|
|
32167
|
+
}
|
|
32168
|
+
function toonComponent(name, def, opts) {
|
|
32169
|
+
const full = opts?.full ?? false;
|
|
32170
|
+
const lines = [];
|
|
32171
|
+
lines.push(`${name} -- ${def.description}`, `category: ${def.category} | tags: ${def.tags.join(",")}`, `import: import { ${name} } from '${def.import}'`, `compound: ${def.compound}`);
|
|
32172
|
+
if (def.compound && def.structure?.tree.length) {
|
|
32173
|
+
lines.push("", header("structure", def.structure.tree.length, ["node"]));
|
|
32174
|
+
for (const node of def.structure.tree) {
|
|
32175
|
+
lines.push(" " + node);
|
|
32176
|
+
}
|
|
32177
|
+
if (def.structure.note)
|
|
32178
|
+
lines.push(` note: ${def.structure.note}`);
|
|
32179
|
+
}
|
|
32180
|
+
if (def.compound && def.parts) {
|
|
32181
|
+
const partEntries = Object.entries(def.parts);
|
|
32182
|
+
lines.push("", header("parts", partEntries.length, ["part"]));
|
|
32183
|
+
for (const [partName, partDef] of partEntries) {
|
|
32184
|
+
lines.push(` ${name}.${partName}`);
|
|
32185
|
+
const props = Object.entries(partDef.props ?? {});
|
|
32186
|
+
if (props.length > 0) {
|
|
32187
|
+
for (const [propName, propDef] of props) {
|
|
32188
|
+
const flags = [propDef.type];
|
|
32189
|
+
if (propDef.required)
|
|
32190
|
+
flags.push("required");
|
|
32191
|
+
if (propDef.default !== undefined)
|
|
32192
|
+
flags.push(`default:${propDef.default}`);
|
|
32193
|
+
if (propDef.acceptedValues?.length)
|
|
32194
|
+
flags.push(`values:${propDef.acceptedValues.join("|")}`);
|
|
32195
|
+
lines.push(` ${propName}: ${flags.join(" | ")}`);
|
|
32196
|
+
}
|
|
32197
|
+
}
|
|
32198
|
+
}
|
|
32199
|
+
} else if (def.props) {
|
|
32200
|
+
const propEntries = Object.entries(def.props);
|
|
32201
|
+
if (propEntries.length > 0) {
|
|
32202
|
+
lines.push("", header("props", propEntries.length, ["name", "type", "required", "default"]));
|
|
32203
|
+
for (const [propName, propDef] of propEntries) {
|
|
32204
|
+
lines.push(row(propName, propDef.type, propDef.required ? "yes" : "no", propDef.default ?? "-"));
|
|
32205
|
+
}
|
|
32206
|
+
}
|
|
32207
|
+
}
|
|
32208
|
+
const cssEntries = Object.entries(def.cssVars);
|
|
32209
|
+
if (cssEntries.length > 0) {
|
|
32210
|
+
lines.push("", header("css-vars", cssEntries.length, ["name", "description"]));
|
|
32211
|
+
for (const [varName, desc] of cssEntries) {
|
|
32212
|
+
lines.push(row(varName, desc));
|
|
32213
|
+
}
|
|
32214
|
+
}
|
|
32215
|
+
if (def.dataAttributes.length > 0) {
|
|
32216
|
+
lines.push("", header("data-attrs", def.dataAttributes.length, ["name", "values"]));
|
|
32217
|
+
for (const attr of def.dataAttributes) {
|
|
32218
|
+
lines.push(row(attr.name, attr.values?.join("|") ?? "-"));
|
|
32219
|
+
}
|
|
32220
|
+
}
|
|
32221
|
+
if (def.example) {
|
|
32222
|
+
const example = full ? def.example : truncate(def.example, 400, `use add ${name} for full snippet`);
|
|
32223
|
+
lines.push("", "example:", example);
|
|
32224
|
+
}
|
|
32225
|
+
const help = buildContextualHelp({ command: "info", componentName: name });
|
|
32226
|
+
if (help.length > 0) {
|
|
32227
|
+
lines.push("", formatHelp(help));
|
|
32228
|
+
}
|
|
32229
|
+
return lines.join(`
|
|
32230
|
+
`);
|
|
32231
|
+
}
|
|
32232
|
+
function toonComponentList(components, category) {
|
|
32233
|
+
const entries = Object.entries(components);
|
|
32234
|
+
const filtered = category ? entries.filter(([, def]) => def.category.toLowerCase() === category.toLowerCase()) : entries;
|
|
32235
|
+
if (filtered.length === 0) {
|
|
32236
|
+
const cats = [...new Set(entries.map(([, d]) => d.category))].sort();
|
|
32237
|
+
return `components[0]: no matches
|
|
32238
|
+
available categories: ${cats.join(", ")}`;
|
|
32239
|
+
}
|
|
32240
|
+
const groups = {};
|
|
32241
|
+
for (const entry of filtered) {
|
|
32242
|
+
const cat = entry[1].category;
|
|
32243
|
+
(groups[cat] ??= []).push(entry);
|
|
32244
|
+
}
|
|
32245
|
+
const lines = [header("components", filtered.length, ["name", "category", "compound", "description"])];
|
|
32246
|
+
const sortedCats = Object.keys(groups).sort();
|
|
32247
|
+
for (const cat of sortedCats) {
|
|
32248
|
+
const items = groups[cat] ?? [];
|
|
32249
|
+
for (const [name, def] of items) {
|
|
32250
|
+
lines.push(row(name, cat, def.compound, def.description));
|
|
32251
|
+
}
|
|
32252
|
+
}
|
|
32253
|
+
const help = buildContextualHelp({ command: "list" });
|
|
32254
|
+
if (help.length > 0) {
|
|
32255
|
+
lines.push("", formatHelp(help));
|
|
32256
|
+
}
|
|
32257
|
+
return lines.join(`
|
|
32258
|
+
`);
|
|
32259
|
+
}
|
|
32260
|
+
function toonComposition(results, opts) {
|
|
32261
|
+
const full = opts?.full ?? false;
|
|
32262
|
+
const lines = [];
|
|
32263
|
+
const totalMatches = results.componentMatches.length + results.recipeMatches.length;
|
|
32264
|
+
if (totalMatches === 0) {
|
|
32265
|
+
return "matches[0]: none";
|
|
32266
|
+
}
|
|
32267
|
+
for (const comp of results.componentMatches) {
|
|
32268
|
+
lines.push(`-- ${comp.component}: ${comp.useWhen}`);
|
|
32269
|
+
for (const alt of comp.alternatives) {
|
|
32270
|
+
const snippet = full ? alt.snippet : truncate(alt.snippet, 500, `use info ${alt.component} for full snippet`);
|
|
32271
|
+
lines.push(` ${alt.rank}. ${alt.component} (${alt.useWhen})`);
|
|
32272
|
+
lines.push(snippet.split(`
|
|
32273
|
+
`).map((l) => " " + l).join(`
|
|
32274
|
+
`));
|
|
32275
|
+
}
|
|
32276
|
+
for (const ap of comp.antiPatterns) {
|
|
32277
|
+
lines.push(` anti-pattern: ${ap.pattern}`);
|
|
32278
|
+
lines.push(` reason: ${ap.reason} | fix: ${ap.fix}`);
|
|
32279
|
+
}
|
|
32280
|
+
if (comp.combinesWith.length) {
|
|
32281
|
+
lines.push(` combines-with: ${comp.combinesWith.join(",")}`);
|
|
32282
|
+
}
|
|
32283
|
+
lines.push("");
|
|
32284
|
+
}
|
|
32285
|
+
for (const recipe of results.recipeMatches) {
|
|
32286
|
+
const snippet = full ? recipe.snippet : truncate(recipe.snippet, 500, `use compose "${recipe.name}" --full for complete code`);
|
|
32287
|
+
lines.push(`-- recipe: ${recipe.name}`);
|
|
32288
|
+
lines.push(` ${recipe.description}`);
|
|
32289
|
+
lines.push(` components: ${recipe.components.join(",")}`);
|
|
32290
|
+
lines.push(" code:");
|
|
32291
|
+
lines.push(snippet.split(`
|
|
32292
|
+
`).map((l) => " " + l).join(`
|
|
32293
|
+
`));
|
|
32294
|
+
lines.push("");
|
|
32295
|
+
}
|
|
32296
|
+
const firstComponent = results.componentMatches[0]?.alternatives[0]?.component ?? results.recipeMatches[0]?.components[0] ?? undefined;
|
|
32297
|
+
const ctx = { command: "compose" };
|
|
32298
|
+
if (firstComponent)
|
|
32299
|
+
ctx.componentName = firstComponent;
|
|
32300
|
+
const help = buildContextualHelp(ctx);
|
|
32301
|
+
if (help.length > 0) {
|
|
32302
|
+
lines.push(formatHelp(help));
|
|
32303
|
+
}
|
|
32304
|
+
return lines.join(`
|
|
32305
|
+
`).trimEnd();
|
|
32306
|
+
}
|
|
32307
|
+
function toonReviewResult(result) {
|
|
32308
|
+
const lines = [];
|
|
32309
|
+
const hasBlockers = result.issues.some((i) => i.severity === "error");
|
|
32310
|
+
const autoFixable = result.issues.filter((i) => i.fix !== null).length;
|
|
32311
|
+
if (result.issues.length === 0) {
|
|
32312
|
+
lines.push("issues[0]: clean");
|
|
32313
|
+
lines.push(`hasBlockers: false | autoFixable: 0`);
|
|
32314
|
+
} else {
|
|
32315
|
+
lines.push(header("issues", result.issues.length, ["severity", "line", "code", "message"]));
|
|
32316
|
+
for (const issue of result.issues) {
|
|
32317
|
+
lines.push(row(issue.severity, issue.line, issue.code, issue.message));
|
|
32318
|
+
if (issue.fix) {
|
|
32319
|
+
lines.push(` fix: ${issue.fix}`);
|
|
32320
|
+
}
|
|
32321
|
+
}
|
|
32322
|
+
lines.push(`hasBlockers: ${hasBlockers} | autoFixable: ${autoFixable}`);
|
|
32323
|
+
}
|
|
32324
|
+
lines.push(result.summary);
|
|
32325
|
+
const help = buildContextualHelp({
|
|
32326
|
+
command: "review",
|
|
32327
|
+
hasErrors: hasBlockers,
|
|
32328
|
+
isEmpty: result.issues.length === 0
|
|
32329
|
+
});
|
|
32330
|
+
if (help.length > 0) {
|
|
32331
|
+
lines.push("", formatHelp(help));
|
|
32332
|
+
}
|
|
32333
|
+
return lines.join(`
|
|
32334
|
+
`);
|
|
32335
|
+
}
|
|
32336
|
+
function toonDiagnoseResult(result) {
|
|
32337
|
+
const lines = [];
|
|
32338
|
+
const { variables } = result;
|
|
32339
|
+
const missingCount = result.issues.filter((i) => i.code === "missing-token").length;
|
|
32340
|
+
const totalRequired = variables.required + missingCount;
|
|
32341
|
+
const coverage = totalRequired > 0 ? Math.round(variables.required / totalRequired * 100) : 100;
|
|
32342
|
+
lines.push(`tokens: ${variables.found} found, ${variables.required} required, ${variables.extra} extra | coverage: ${coverage}%`);
|
|
32343
|
+
if (result.issues.length === 0) {
|
|
32344
|
+
lines.push("issues[0]: clean");
|
|
32345
|
+
} else {
|
|
32346
|
+
lines.push(header("issues", result.issues.length, ["severity", "code", "variable", "message"]));
|
|
32347
|
+
for (const issue of result.issues) {
|
|
32348
|
+
lines.push(row(issue.severity, issue.code, issue.variable, issue.message));
|
|
32349
|
+
if (issue.fix) {
|
|
32350
|
+
lines.push(` fix: ${issue.fix}`);
|
|
32351
|
+
}
|
|
32352
|
+
}
|
|
32353
|
+
}
|
|
32354
|
+
lines.push(result.summary);
|
|
32355
|
+
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
32356
|
+
const help = buildContextualHelp({
|
|
32357
|
+
command: "diagnose",
|
|
32358
|
+
hasErrors,
|
|
32359
|
+
isEmpty: result.issues.length === 0
|
|
32360
|
+
});
|
|
32361
|
+
if (help.length > 0) {
|
|
32362
|
+
lines.push("", formatHelp(help));
|
|
32363
|
+
}
|
|
32364
|
+
return lines.join(`
|
|
32365
|
+
`);
|
|
32366
|
+
}
|
|
32367
|
+
var MAX_FINDINGS_DEFAULT = 50;
|
|
32368
|
+
function toonWorkspaceReport(report, opts) {
|
|
32369
|
+
const full = opts?.full ?? false;
|
|
32370
|
+
const title = opts?.title ?? "workspace";
|
|
32371
|
+
const command = opts?.command ?? (title.includes("lint") ? "lint" : "doctor");
|
|
32372
|
+
const lines = [];
|
|
32373
|
+
lines.push(`${title} | root: ${report.root}`);
|
|
32374
|
+
lines.push(`scanned: ${report.scannedFiles} files | errors: ${report.summary.error} | warnings: ${report.summary.warning} | info: ${report.summary.info}`);
|
|
32375
|
+
if (report.summary.byRule && Object.keys(report.summary.byRule).length > 0) {
|
|
32376
|
+
const sorted = Object.entries(report.summary.byRule).sort(([, a], [, b]) => b - a);
|
|
32377
|
+
const topRule = sorted[0];
|
|
32378
|
+
if (topRule) {
|
|
32379
|
+
lines.push(`top-rule: ${topRule[0]} (${topRule[1]} occurrences)`);
|
|
32380
|
+
}
|
|
32381
|
+
}
|
|
32382
|
+
if (report.findings.length === 0) {
|
|
32383
|
+
lines.push("findings[0]: clean");
|
|
32384
|
+
} else {
|
|
32385
|
+
const findings = full ? report.findings : report.findings.slice(0, MAX_FINDINGS_DEFAULT);
|
|
32386
|
+
const truncated = !full && report.findings.length > MAX_FINDINGS_DEFAULT;
|
|
32387
|
+
lines.push(header("findings", findings.length, ["severity", "rule", "file", "line", "message"]));
|
|
32388
|
+
for (const f of findings) {
|
|
32389
|
+
lines.push(row(f.severity, f.ruleId, f.file, f.line ?? "-", f.message));
|
|
32390
|
+
if (f.suggestedFixes.length > 0) {
|
|
32391
|
+
for (const fix of f.suggestedFixes) {
|
|
32392
|
+
lines.push(` fix: ${fix.description}${fix.replacement ? ` -> ${fix.replacement}` : ""}`);
|
|
32393
|
+
}
|
|
32394
|
+
}
|
|
32395
|
+
}
|
|
32396
|
+
if (truncated) {
|
|
32397
|
+
lines.push(` (showing ${MAX_FINDINGS_DEFAULT} of ${report.findings.length} -- use --full to see all)`);
|
|
32398
|
+
}
|
|
32399
|
+
}
|
|
32400
|
+
if (report.warnings.length > 0) {
|
|
32401
|
+
lines.push("", header("warnings", report.warnings.length, ["message"]));
|
|
32402
|
+
for (const w of report.warnings) {
|
|
32403
|
+
lines.push(" " + w);
|
|
32404
|
+
}
|
|
32405
|
+
}
|
|
32406
|
+
const help = buildContextualHelp({
|
|
32407
|
+
command,
|
|
32408
|
+
hasFindings: report.findings.length > 0,
|
|
32409
|
+
isEmpty: report.findings.length === 0
|
|
32410
|
+
});
|
|
32411
|
+
if (help.length > 0) {
|
|
32412
|
+
lines.push("", formatHelp(help));
|
|
32413
|
+
}
|
|
32414
|
+
return lines.join(`
|
|
32415
|
+
`);
|
|
32416
|
+
}
|
|
32417
|
+
function toonProjectDetection(detection) {
|
|
32418
|
+
const lines = [];
|
|
32419
|
+
lines.push(`project: ${detection.status} | framework: ${detection.framework} | pkg-manager: ${detection.packageManager}`);
|
|
32420
|
+
lines.push(`root: ${detection.root ?? "(not found)"}`);
|
|
32421
|
+
lines.push(`deps: ui=${detection.dependencies.ui}, primitives=${detection.dependencies.primitives}`);
|
|
32422
|
+
lines.push(`theme: default=${detection.theme.defaultImported}, dark=${detection.theme.darkImported}, auto=${detection.theme.themeAuto}`);
|
|
32423
|
+
if (detection.warnings.length > 0) {
|
|
32424
|
+
lines.push(header("warnings", detection.warnings.length, ["message"]));
|
|
32425
|
+
for (const w of detection.warnings) {
|
|
32426
|
+
lines.push(" " + w);
|
|
32427
|
+
}
|
|
32428
|
+
}
|
|
32429
|
+
const help = buildContextualHelp({ command: "detect", status: detection.status });
|
|
32430
|
+
if (help.length > 0) {
|
|
32431
|
+
lines.push("", formatHelp(help));
|
|
32432
|
+
}
|
|
32433
|
+
return lines.join(`
|
|
32434
|
+
`);
|
|
32435
|
+
}
|
|
32436
|
+
function toonError(code, message, suggestions) {
|
|
32437
|
+
const lines = [`error[1]{code,message}: ${esc(code)},${esc(message)}`];
|
|
32438
|
+
if (suggestions?.length) {
|
|
32439
|
+
lines.push(header("suggestions", suggestions.length, ["value"]));
|
|
32440
|
+
for (const s of suggestions) {
|
|
32441
|
+
lines.push(" " + s);
|
|
32442
|
+
}
|
|
32443
|
+
}
|
|
32444
|
+
return lines.join(`
|
|
32445
|
+
`);
|
|
32446
|
+
}
|
|
32447
|
+
|
|
32448
|
+
// ../mcp/src/spec-formatters.ts
|
|
32449
|
+
var DIR_OVERRIDES2 = {
|
|
32450
|
+
QRCode: "qr-code"
|
|
32451
|
+
};
|
|
32452
|
+
function componentDir2(name) {
|
|
32453
|
+
return DIR_OVERRIDES2[name] ?? name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
32454
|
+
}
|
|
31689
32455
|
function pad(str, width) {
|
|
31690
32456
|
return str.length >= width ? str : str + " ".repeat(width - str.length);
|
|
31691
32457
|
}
|
|
@@ -31698,9 +32464,9 @@ function indent(text, spaces) {
|
|
|
31698
32464
|
function getSubpathImport(name, def) {
|
|
31699
32465
|
if (def.import !== "@dryui/ui")
|
|
31700
32466
|
return null;
|
|
31701
|
-
return `import { ${name} } from '${def.import}/${
|
|
32467
|
+
return `import { ${name} } from '${def.import}/${componentDir2(name)}'`;
|
|
31702
32468
|
}
|
|
31703
|
-
function
|
|
32469
|
+
function findComponent2(query, components) {
|
|
31704
32470
|
const exact = components[query];
|
|
31705
32471
|
if (exact)
|
|
31706
32472
|
return { name: query, def: exact };
|
|
@@ -31875,9 +32641,23 @@ function formatSimple(name, def) {
|
|
|
31875
32641
|
}
|
|
31876
32642
|
|
|
31877
32643
|
// src/run.ts
|
|
31878
|
-
|
|
32644
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
32645
|
+
function fileNotFound(filePath, toon) {
|
|
32646
|
+
if (existsSync2(filePath))
|
|
32647
|
+
return null;
|
|
32648
|
+
return {
|
|
32649
|
+
output: "",
|
|
32650
|
+
error: toon ? toonError("not-found", `File not found: ${filePath}`) : `File not found: ${filePath}`,
|
|
32651
|
+
exitCode: 1
|
|
32652
|
+
};
|
|
32653
|
+
}
|
|
32654
|
+
function runCommand(result, mode = "text") {
|
|
31879
32655
|
if (result.error) {
|
|
31880
|
-
|
|
32656
|
+
if (mode === "text") {
|
|
32657
|
+
console.error(result.error);
|
|
32658
|
+
} else {
|
|
32659
|
+
console.log(result.error);
|
|
32660
|
+
}
|
|
31881
32661
|
} else {
|
|
31882
32662
|
console.log(result.output);
|
|
31883
32663
|
}
|
|
@@ -31885,13 +32665,20 @@ function runCommand(result) {
|
|
|
31885
32665
|
}
|
|
31886
32666
|
|
|
31887
32667
|
// src/commands/info.ts
|
|
31888
|
-
function
|
|
31889
|
-
return
|
|
32668
|
+
function findComponent3(spec, query) {
|
|
32669
|
+
return findComponent2(query, spec.components);
|
|
31890
32670
|
}
|
|
31891
|
-
function getInfo(query, spec) {
|
|
31892
|
-
const result =
|
|
32671
|
+
function getInfo(query, spec, options) {
|
|
32672
|
+
const result = findComponent3(spec, query);
|
|
31893
32673
|
if (!result) {
|
|
31894
32674
|
const available = Object.keys(spec.components).sort();
|
|
32675
|
+
if (options?.toon) {
|
|
32676
|
+
return {
|
|
32677
|
+
output: "",
|
|
32678
|
+
error: toonError("not-found", `Unknown component: "${query}"`, available),
|
|
32679
|
+
exitCode: 1
|
|
32680
|
+
};
|
|
32681
|
+
}
|
|
31895
32682
|
const error = [
|
|
31896
32683
|
`Unknown component: "${query}"`,
|
|
31897
32684
|
"",
|
|
@@ -31902,27 +32689,37 @@ function getInfo(query, spec) {
|
|
|
31902
32689
|
return { output: "", error, exitCode: 1 };
|
|
31903
32690
|
}
|
|
31904
32691
|
const { name, def } = result;
|
|
32692
|
+
if (options?.toon) {
|
|
32693
|
+
return { output: toonComponent(name, def, { full: options?.full }), error: null, exitCode: 0 };
|
|
32694
|
+
}
|
|
31905
32695
|
const output = def.compound ? formatCompound(name, def) : formatSimple(name, def);
|
|
31906
32696
|
return { output, error: null, exitCode: 0 };
|
|
31907
32697
|
}
|
|
31908
32698
|
function runInfo(args, spec) {
|
|
31909
32699
|
if (args.length === 0 || args[0] === "--help") {
|
|
31910
|
-
console.log("Usage: dryui info <component>");
|
|
32700
|
+
console.log("Usage: dryui info <component> [--toon] [--full]");
|
|
31911
32701
|
console.log("");
|
|
31912
32702
|
console.log("Show API reference for a DryUI component or composed output.");
|
|
31913
32703
|
console.log("");
|
|
32704
|
+
console.log("Options:");
|
|
32705
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
32706
|
+
console.log(" --full Include full example code (disables truncation)");
|
|
32707
|
+
console.log("");
|
|
31914
32708
|
console.log("Examples:");
|
|
31915
32709
|
console.log(" dryui info Button");
|
|
31916
32710
|
console.log(" dryui info card # case-insensitive");
|
|
31917
|
-
console.log(
|
|
32711
|
+
console.log(" dryui info Button --toon");
|
|
31918
32712
|
process.exit(args[0] === "--help" ? 0 : 1);
|
|
31919
32713
|
}
|
|
31920
|
-
const
|
|
32714
|
+
const toon = args.includes("--toon");
|
|
32715
|
+
const full = args.includes("--full");
|
|
32716
|
+
const query = args.find((a) => !a.startsWith("--"));
|
|
31921
32717
|
if (!query) {
|
|
31922
32718
|
console.error("Error: missing component name");
|
|
31923
32719
|
process.exit(1);
|
|
31924
32720
|
}
|
|
31925
|
-
|
|
32721
|
+
const mode = toon ? "toon" : "text";
|
|
32722
|
+
runCommand(getInfo(query, spec, { toon, full }), mode);
|
|
31926
32723
|
}
|
|
31927
32724
|
|
|
31928
32725
|
// src/format.ts
|
|
@@ -31982,7 +32779,7 @@ function formatWorkspaceReport(report, options) {
|
|
|
31982
32779
|
// src/commands/project-planner.ts
|
|
31983
32780
|
function importStatement(name, def, subpath = false) {
|
|
31984
32781
|
if (subpath && def.import === "@dryui/ui") {
|
|
31985
|
-
return `import { ${name} } from '${def.import}/${
|
|
32782
|
+
return `import { ${name} } from '${def.import}/${componentDir2(name)}';`;
|
|
31986
32783
|
}
|
|
31987
32784
|
return `import { ${name} } from '${def.import}';`;
|
|
31988
32785
|
}
|
|
@@ -32104,7 +32901,7 @@ function formatAddPlan(plan) {
|
|
|
32104
32901
|
`);
|
|
32105
32902
|
}
|
|
32106
32903
|
function buildAddSnippet(query, spec, options = {}) {
|
|
32107
|
-
const component =
|
|
32904
|
+
const component = findComponent3(spec, query);
|
|
32108
32905
|
if (!component) {
|
|
32109
32906
|
return {
|
|
32110
32907
|
output: "",
|
|
@@ -32120,331 +32917,6 @@ function buildAddSnippet(query, spec, options = {}) {
|
|
|
32120
32917
|
};
|
|
32121
32918
|
}
|
|
32122
32919
|
|
|
32123
|
-
// ../mcp/src/project-planner.ts
|
|
32124
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
32125
|
-
import { dirname, resolve } from "node:path";
|
|
32126
|
-
var DIR_OVERRIDES2 = {
|
|
32127
|
-
QRCode: "qr-code"
|
|
32128
|
-
};
|
|
32129
|
-
function componentDir2(name) {
|
|
32130
|
-
return DIR_OVERRIDES2[name] ?? name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
32131
|
-
}
|
|
32132
|
-
function resolveStart(inputPath) {
|
|
32133
|
-
const candidate = resolve(inputPath ?? process.cwd());
|
|
32134
|
-
return existsSync(candidate) && statSync(candidate).isFile() ? dirname(candidate) : candidate;
|
|
32135
|
-
}
|
|
32136
|
-
function findUp(start, fileName) {
|
|
32137
|
-
let current = start;
|
|
32138
|
-
while (true) {
|
|
32139
|
-
const candidate = resolve(current, fileName);
|
|
32140
|
-
if (existsSync(candidate))
|
|
32141
|
-
return candidate;
|
|
32142
|
-
const parent = dirname(current);
|
|
32143
|
-
if (parent === current)
|
|
32144
|
-
return null;
|
|
32145
|
-
current = parent;
|
|
32146
|
-
}
|
|
32147
|
-
}
|
|
32148
|
-
function findUpAny(start, fileNames) {
|
|
32149
|
-
let current = start;
|
|
32150
|
-
while (true) {
|
|
32151
|
-
for (const fileName of fileNames) {
|
|
32152
|
-
const candidate = resolve(current, fileName);
|
|
32153
|
-
if (existsSync(candidate))
|
|
32154
|
-
return candidate;
|
|
32155
|
-
}
|
|
32156
|
-
const parent = dirname(current);
|
|
32157
|
-
if (parent === current)
|
|
32158
|
-
return null;
|
|
32159
|
-
current = parent;
|
|
32160
|
-
}
|
|
32161
|
-
}
|
|
32162
|
-
function detectPackageManager(root) {
|
|
32163
|
-
if (!root)
|
|
32164
|
-
return "unknown";
|
|
32165
|
-
const lockfilePath = findUpAny(root, [
|
|
32166
|
-
"bun.lock",
|
|
32167
|
-
"bun.lockb",
|
|
32168
|
-
"pnpm-lock.yaml",
|
|
32169
|
-
"package-lock.json",
|
|
32170
|
-
"yarn.lock"
|
|
32171
|
-
]);
|
|
32172
|
-
if (!lockfilePath)
|
|
32173
|
-
return "unknown";
|
|
32174
|
-
if (lockfilePath.endsWith("bun.lock") || lockfilePath.endsWith("bun.lockb"))
|
|
32175
|
-
return "bun";
|
|
32176
|
-
if (lockfilePath.endsWith("pnpm-lock.yaml"))
|
|
32177
|
-
return "pnpm";
|
|
32178
|
-
if (lockfilePath.endsWith("package-lock.json"))
|
|
32179
|
-
return "npm";
|
|
32180
|
-
if (lockfilePath.endsWith("yarn.lock"))
|
|
32181
|
-
return "yarn";
|
|
32182
|
-
return "unknown";
|
|
32183
|
-
}
|
|
32184
|
-
function readPackageJson(packageJsonPath) {
|
|
32185
|
-
if (!packageJsonPath)
|
|
32186
|
-
return null;
|
|
32187
|
-
return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
32188
|
-
}
|
|
32189
|
-
function getDependencyNames(pkg) {
|
|
32190
|
-
return new Set([
|
|
32191
|
-
...Object.keys(pkg?.dependencies ?? {}),
|
|
32192
|
-
...Object.keys(pkg?.devDependencies ?? {})
|
|
32193
|
-
]);
|
|
32194
|
-
}
|
|
32195
|
-
function detectFramework(dependencyNames) {
|
|
32196
|
-
if (dependencyNames.has("@sveltejs/kit"))
|
|
32197
|
-
return "sveltekit";
|
|
32198
|
-
if (dependencyNames.has("svelte"))
|
|
32199
|
-
return "svelte";
|
|
32200
|
-
return "unknown";
|
|
32201
|
-
}
|
|
32202
|
-
function hasImport(filePath, importPath) {
|
|
32203
|
-
if (!filePath)
|
|
32204
|
-
return false;
|
|
32205
|
-
return readFileSync(filePath, "utf-8").includes(importPath);
|
|
32206
|
-
}
|
|
32207
|
-
function hasThemeAuto(appHtmlPath) {
|
|
32208
|
-
if (!appHtmlPath)
|
|
32209
|
-
return false;
|
|
32210
|
-
return readFileSync(appHtmlPath, "utf-8").includes("theme-auto");
|
|
32211
|
-
}
|
|
32212
|
-
function hasAnyImport(filePaths, importPath) {
|
|
32213
|
-
return filePaths.some((filePath) => hasImport(filePath, importPath));
|
|
32214
|
-
}
|
|
32215
|
-
function importsAppCss(rootLayoutPath) {
|
|
32216
|
-
if (!rootLayoutPath)
|
|
32217
|
-
return false;
|
|
32218
|
-
const content = readFileSync(rootLayoutPath, "utf-8");
|
|
32219
|
-
return content.includes("app.css");
|
|
32220
|
-
}
|
|
32221
|
-
function buildStatus(framework, hasPackageJson, stepsNeeded) {
|
|
32222
|
-
if (!hasPackageJson || framework === "unknown")
|
|
32223
|
-
return "unsupported";
|
|
32224
|
-
return stepsNeeded === 0 ? "ready" : "partial";
|
|
32225
|
-
}
|
|
32226
|
-
function installCommand(packageManager) {
|
|
32227
|
-
switch (packageManager) {
|
|
32228
|
-
case "bun":
|
|
32229
|
-
return "bun add @dryui/ui";
|
|
32230
|
-
case "pnpm":
|
|
32231
|
-
return "pnpm add @dryui/ui";
|
|
32232
|
-
case "yarn":
|
|
32233
|
-
return "yarn add @dryui/ui";
|
|
32234
|
-
default:
|
|
32235
|
-
return "npm install @dryui/ui";
|
|
32236
|
-
}
|
|
32237
|
-
}
|
|
32238
|
-
function buildThemeImportSnippet(spec) {
|
|
32239
|
-
return [
|
|
32240
|
-
'<script lang="ts">',
|
|
32241
|
-
` import '${spec.themeImports.default}';`,
|
|
32242
|
-
` import '${spec.themeImports.dark}';`,
|
|
32243
|
-
"</script>"
|
|
32244
|
-
].join(`
|
|
32245
|
-
`);
|
|
32246
|
-
}
|
|
32247
|
-
function buildThemeImportCssSnippet(spec) {
|
|
32248
|
-
return [`@import '${spec.themeImports.default}';`, `@import '${spec.themeImports.dark}';`].join(`
|
|
32249
|
-
`);
|
|
32250
|
-
}
|
|
32251
|
-
function getSuggestedTarget(root, explicitTarget) {
|
|
32252
|
-
if (explicitTarget)
|
|
32253
|
-
return resolve(root ?? process.cwd(), explicitTarget);
|
|
32254
|
-
if (!root)
|
|
32255
|
-
return null;
|
|
32256
|
-
const rootPage = resolve(root, "src/routes/+page.svelte");
|
|
32257
|
-
return existsSync(rootPage) ? rootPage : null;
|
|
32258
|
-
}
|
|
32259
|
-
function getImportStatement(name, component, subpath = false) {
|
|
32260
|
-
if (subpath && component.import === "@dryui/ui") {
|
|
32261
|
-
return `import { ${name} } from '${component.import}/${componentDir2(name)}';`;
|
|
32262
|
-
}
|
|
32263
|
-
return `import { ${name} } from '${component.import}';`;
|
|
32264
|
-
}
|
|
32265
|
-
function findComponent3(spec, query) {
|
|
32266
|
-
const exact = spec.components[query];
|
|
32267
|
-
if (exact)
|
|
32268
|
-
return { name: query, def: exact };
|
|
32269
|
-
const lower = query.toLowerCase();
|
|
32270
|
-
for (const [name, def] of Object.entries(spec.components)) {
|
|
32271
|
-
if (name.toLowerCase() === lower)
|
|
32272
|
-
return { name, def };
|
|
32273
|
-
}
|
|
32274
|
-
return null;
|
|
32275
|
-
}
|
|
32276
|
-
function detectProject(spec, inputPath) {
|
|
32277
|
-
const start = resolveStart(inputPath);
|
|
32278
|
-
const packageJsonPath = findUp(start, "package.json");
|
|
32279
|
-
const root = packageJsonPath ? dirname(packageJsonPath) : null;
|
|
32280
|
-
const dependencyNames = getDependencyNames(readPackageJson(packageJsonPath));
|
|
32281
|
-
const framework = detectFramework(dependencyNames);
|
|
32282
|
-
const appHtmlPath = root ? resolve(root, "src/app.html") : null;
|
|
32283
|
-
const appCssPath = root ? resolve(root, "src/app.css") : null;
|
|
32284
|
-
const rootLayoutPath = root ? resolve(root, "src/routes/+layout.svelte") : null;
|
|
32285
|
-
const rootPagePath = root ? resolve(root, "src/routes/+page.svelte") : null;
|
|
32286
|
-
const appHtml = appHtmlPath && existsSync(appHtmlPath) ? appHtmlPath : null;
|
|
32287
|
-
const appCss = appCssPath && existsSync(appCssPath) ? appCssPath : null;
|
|
32288
|
-
const rootLayout = rootLayoutPath && existsSync(rootLayoutPath) ? rootLayoutPath : null;
|
|
32289
|
-
const rootPage = rootPagePath && existsSync(rootPagePath) ? rootPagePath : null;
|
|
32290
|
-
const themeImportFiles = rootLayout && importsAppCss(rootLayout) ? [rootLayout, appCss] : [rootLayout];
|
|
32291
|
-
const defaultImported = hasAnyImport(themeImportFiles, spec.themeImports.default);
|
|
32292
|
-
const darkImported = hasAnyImport(themeImportFiles, spec.themeImports.dark);
|
|
32293
|
-
const stepsNeeded = Number(!dependencyNames.has("@dryui/ui")) + Number(!defaultImported) + Number(!darkImported) + Number(!(appHtml && hasThemeAuto(appHtml)));
|
|
32294
|
-
const warnings = [];
|
|
32295
|
-
if (!packageJsonPath)
|
|
32296
|
-
warnings.push("No package.json found above the provided path.");
|
|
32297
|
-
if (framework === "unknown")
|
|
32298
|
-
warnings.push("DryUI planning currently targets Svelte and SvelteKit projects.");
|
|
32299
|
-
return {
|
|
32300
|
-
inputPath: start,
|
|
32301
|
-
root,
|
|
32302
|
-
packageJsonPath,
|
|
32303
|
-
framework,
|
|
32304
|
-
packageManager: detectPackageManager(root),
|
|
32305
|
-
status: buildStatus(framework, Boolean(packageJsonPath), stepsNeeded),
|
|
32306
|
-
dependencies: {
|
|
32307
|
-
ui: dependencyNames.has("@dryui/ui"),
|
|
32308
|
-
primitives: dependencyNames.has("@dryui/primitives")
|
|
32309
|
-
},
|
|
32310
|
-
files: {
|
|
32311
|
-
appHtml,
|
|
32312
|
-
appCss,
|
|
32313
|
-
rootLayout,
|
|
32314
|
-
rootPage
|
|
32315
|
-
},
|
|
32316
|
-
theme: {
|
|
32317
|
-
defaultImported,
|
|
32318
|
-
darkImported,
|
|
32319
|
-
themeAuto: hasThemeAuto(appHtml)
|
|
32320
|
-
},
|
|
32321
|
-
warnings
|
|
32322
|
-
};
|
|
32323
|
-
}
|
|
32324
|
-
function planInstall(spec, inputPath) {
|
|
32325
|
-
const detection = detectProject(spec, inputPath);
|
|
32326
|
-
const steps = [];
|
|
32327
|
-
if (detection.status === "unsupported") {
|
|
32328
|
-
steps.push({
|
|
32329
|
-
kind: "blocked",
|
|
32330
|
-
status: "blocked",
|
|
32331
|
-
title: "Project detection incomplete",
|
|
32332
|
-
description: detection.warnings.join(" ") || "DryUI install planning requires a Svelte or SvelteKit project with a package.json."
|
|
32333
|
-
});
|
|
32334
|
-
return { detection, steps };
|
|
32335
|
-
}
|
|
32336
|
-
if (!detection.dependencies.ui) {
|
|
32337
|
-
steps.push({
|
|
32338
|
-
kind: "install-package",
|
|
32339
|
-
status: "pending",
|
|
32340
|
-
title: "Install @dryui/ui",
|
|
32341
|
-
description: "Add the styled DryUI package to the current project.",
|
|
32342
|
-
command: installCommand(detection.packageManager)
|
|
32343
|
-
});
|
|
32344
|
-
}
|
|
32345
|
-
if (!detection.theme.defaultImported || !detection.theme.darkImported) {
|
|
32346
|
-
if (detection.files.appCss && detection.files.rootLayout && importsAppCss(detection.files.rootLayout)) {
|
|
32347
|
-
steps.push({
|
|
32348
|
-
kind: "edit-file",
|
|
32349
|
-
status: "pending",
|
|
32350
|
-
title: "Add theme imports to app.css",
|
|
32351
|
-
description: "Ensure the app-level stylesheet imports both default and dark DryUI themes.",
|
|
32352
|
-
path: detection.files.appCss,
|
|
32353
|
-
snippet: buildThemeImportCssSnippet(spec)
|
|
32354
|
-
});
|
|
32355
|
-
} else if (!detection.files.rootLayout) {
|
|
32356
|
-
const path = detection.root ? resolve(detection.root, "src/routes/+layout.svelte") : null;
|
|
32357
|
-
steps.push({
|
|
32358
|
-
kind: "create-file",
|
|
32359
|
-
status: "pending",
|
|
32360
|
-
title: "Create root layout with theme imports",
|
|
32361
|
-
description: "Create src/routes/+layout.svelte and add the required DryUI theme imports.",
|
|
32362
|
-
...path ? { path } : {},
|
|
32363
|
-
snippet: buildThemeImportSnippet(spec)
|
|
32364
|
-
});
|
|
32365
|
-
} else {
|
|
32366
|
-
steps.push({
|
|
32367
|
-
kind: "edit-file",
|
|
32368
|
-
status: "pending",
|
|
32369
|
-
title: "Add theme imports to the root layout",
|
|
32370
|
-
description: "Ensure the root layout imports both default and dark DryUI themes.",
|
|
32371
|
-
path: detection.files.rootLayout,
|
|
32372
|
-
snippet: buildThemeImportSnippet(spec)
|
|
32373
|
-
});
|
|
32374
|
-
}
|
|
32375
|
-
}
|
|
32376
|
-
if (!detection.files.appHtml) {
|
|
32377
|
-
steps.push({
|
|
32378
|
-
kind: "blocked",
|
|
32379
|
-
status: "blocked",
|
|
32380
|
-
title: "app.html not found",
|
|
32381
|
-
description: "DryUI expects src/app.html so the document can default to theme-auto mode."
|
|
32382
|
-
});
|
|
32383
|
-
} else if (!detection.theme.themeAuto) {
|
|
32384
|
-
steps.push({
|
|
32385
|
-
kind: "edit-file",
|
|
32386
|
-
status: "pending",
|
|
32387
|
-
title: "Set html theme mode to auto",
|
|
32388
|
-
description: 'Add class="theme-auto" to the html element in src/app.html.',
|
|
32389
|
-
path: detection.files.appHtml,
|
|
32390
|
-
snippet: '<html class="theme-auto">'
|
|
32391
|
-
});
|
|
32392
|
-
}
|
|
32393
|
-
if (steps.length === 0) {
|
|
32394
|
-
steps.push({
|
|
32395
|
-
kind: "note",
|
|
32396
|
-
status: "done",
|
|
32397
|
-
title: "DryUI install plan is complete",
|
|
32398
|
-
description: "The project already has @dryui/ui, theme imports, and theme-auto configured."
|
|
32399
|
-
});
|
|
32400
|
-
}
|
|
32401
|
-
return { detection, steps };
|
|
32402
|
-
}
|
|
32403
|
-
function planAdd(spec, query, options = {}) {
|
|
32404
|
-
const installPlan = planInstall(spec, options.cwd);
|
|
32405
|
-
const component = findComponent3(spec, query);
|
|
32406
|
-
if (component) {
|
|
32407
|
-
const target = getSuggestedTarget(installPlan.detection.root, options.target);
|
|
32408
|
-
const steps = [];
|
|
32409
|
-
const warnings = [...installPlan.detection.warnings];
|
|
32410
|
-
if (installPlan.steps.some((step) => step.status === "pending" || step.status === "blocked")) {
|
|
32411
|
-
steps.push({
|
|
32412
|
-
kind: "note",
|
|
32413
|
-
status: "info",
|
|
32414
|
-
title: "Complete install plan first",
|
|
32415
|
-
description: "Apply the install plan before inserting DryUI components into project files."
|
|
32416
|
-
});
|
|
32417
|
-
}
|
|
32418
|
-
steps.push(target ? {
|
|
32419
|
-
kind: "edit-file",
|
|
32420
|
-
status: "pending",
|
|
32421
|
-
title: "Insert component into the target file",
|
|
32422
|
-
description: "Add the import and snippet below to the chosen Svelte file.",
|
|
32423
|
-
path: target,
|
|
32424
|
-
snippet: `${getImportStatement(component.name, component.def, options.subpath)}
|
|
32425
|
-
|
|
32426
|
-
${component.def.example}`
|
|
32427
|
-
} : {
|
|
32428
|
-
kind: "note",
|
|
32429
|
-
status: "info",
|
|
32430
|
-
title: "Choose a target Svelte file",
|
|
32431
|
-
description: "No root page was found. Pick a target file and reuse the import and snippet in this plan."
|
|
32432
|
-
});
|
|
32433
|
-
return {
|
|
32434
|
-
detection: installPlan.detection,
|
|
32435
|
-
installPlan,
|
|
32436
|
-
targetType: "component",
|
|
32437
|
-
name: component.name,
|
|
32438
|
-
importStatement: getImportStatement(component.name, component.def, options.subpath),
|
|
32439
|
-
snippet: component.def.example,
|
|
32440
|
-
target,
|
|
32441
|
-
steps,
|
|
32442
|
-
warnings
|
|
32443
|
-
};
|
|
32444
|
-
}
|
|
32445
|
-
throw new Error(`Unknown component: "${query}"`);
|
|
32446
|
-
}
|
|
32447
|
-
|
|
32448
32920
|
// src/commands/add.ts
|
|
32449
32921
|
function parseProjectInput(positionals, spec) {
|
|
32450
32922
|
const first = positionals[0];
|
|
@@ -32456,8 +32928,8 @@ function parseProjectInput(positionals, spec) {
|
|
|
32456
32928
|
return { query: first };
|
|
32457
32929
|
}
|
|
32458
32930
|
if (positionals.length === 2) {
|
|
32459
|
-
const firstIsQuery = Boolean(
|
|
32460
|
-
const secondIsQuery = Boolean(
|
|
32931
|
+
const firstIsQuery = Boolean(findComponent3(spec, first));
|
|
32932
|
+
const secondIsQuery = Boolean(findComponent3(spec, second));
|
|
32461
32933
|
if (firstIsQuery && !secondIsQuery) {
|
|
32462
32934
|
return { query: first, cwd: second };
|
|
32463
32935
|
}
|
|
@@ -32584,6 +33056,7 @@ function runAdd(args, spec) {
|
|
|
32584
33056
|
// src/commands/detect.ts
|
|
32585
33057
|
function parseDetectArgs(args) {
|
|
32586
33058
|
let json = false;
|
|
33059
|
+
let toon = false;
|
|
32587
33060
|
let path;
|
|
32588
33061
|
for (let index = 0;index < args.length; index++) {
|
|
32589
33062
|
const arg = args[index];
|
|
@@ -32593,6 +33066,10 @@ function parseDetectArgs(args) {
|
|
|
32593
33066
|
json = true;
|
|
32594
33067
|
continue;
|
|
32595
33068
|
}
|
|
33069
|
+
if (arg === "--toon") {
|
|
33070
|
+
toon = true;
|
|
33071
|
+
continue;
|
|
33072
|
+
}
|
|
32596
33073
|
if (arg.startsWith("--")) {
|
|
32597
33074
|
continue;
|
|
32598
33075
|
}
|
|
@@ -32600,24 +33077,29 @@ function parseDetectArgs(args) {
|
|
|
32600
33077
|
path = arg;
|
|
32601
33078
|
}
|
|
32602
33079
|
}
|
|
32603
|
-
return { json, path };
|
|
33080
|
+
return { json, toon, path };
|
|
32604
33081
|
}
|
|
32605
33082
|
function getDetect(inputPath, spec, options = {}) {
|
|
32606
33083
|
const detection = detectProject(spec, inputPath);
|
|
33084
|
+
if (options.toon) {
|
|
33085
|
+
return { output: toonProjectDetection(detection), error: null, exitCode: 0 };
|
|
33086
|
+
}
|
|
32607
33087
|
return options.json ? { output: JSON.stringify(detection, null, 2), error: null, exitCode: 0 } : { output: formatProjectDetection(detection), error: null, exitCode: 0 };
|
|
32608
33088
|
}
|
|
32609
33089
|
function runDetect(args, spec) {
|
|
32610
33090
|
if (args[0] === "--help") {
|
|
32611
|
-
console.log("Usage: dryui detect [--json] [path]");
|
|
33091
|
+
console.log("Usage: dryui detect [--json] [--toon] [path]");
|
|
32612
33092
|
console.log("");
|
|
32613
33093
|
console.log("Detect the current DryUI project setup.");
|
|
32614
33094
|
console.log("");
|
|
32615
33095
|
console.log("Options:");
|
|
32616
33096
|
console.log(" --json Output raw JSON instead of formatted text");
|
|
33097
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
32617
33098
|
process.exit(0);
|
|
32618
33099
|
}
|
|
32619
|
-
const { json, path } = parseDetectArgs(args);
|
|
32620
|
-
|
|
33100
|
+
const { json, toon, path } = parseDetectArgs(args);
|
|
33101
|
+
const mode = toon ? "toon" : json ? "json" : "text";
|
|
33102
|
+
runCommand(getDetect(path, spec, { json, toon }), mode);
|
|
32621
33103
|
}
|
|
32622
33104
|
|
|
32623
33105
|
// src/commands/install.ts
|
|
@@ -32724,7 +33206,14 @@ function groupByCategory(spec) {
|
|
|
32724
33206
|
}
|
|
32725
33207
|
return groups;
|
|
32726
33208
|
}
|
|
32727
|
-
function getList(category, spec, options
|
|
33209
|
+
function getList(category, spec, options) {
|
|
33210
|
+
if (options?.toon) {
|
|
33211
|
+
return {
|
|
33212
|
+
output: toonComponentList(spec.components, category ?? undefined),
|
|
33213
|
+
error: null,
|
|
33214
|
+
exitCode: 0
|
|
33215
|
+
};
|
|
33216
|
+
}
|
|
32728
33217
|
const sections = [];
|
|
32729
33218
|
const validCategories = getCategories(spec);
|
|
32730
33219
|
if (category && !validCategories.includes(category)) {
|
|
@@ -32758,18 +33247,20 @@ function getList(category, spec, options = {}) {
|
|
|
32758
33247
|
}
|
|
32759
33248
|
function runList(args, spec) {
|
|
32760
33249
|
if (args[0] === "--help") {
|
|
32761
|
-
console.log("Usage: dryui list [--category <category>]");
|
|
33250
|
+
console.log("Usage: dryui list [--category <category>] [--toon]");
|
|
32762
33251
|
console.log("");
|
|
32763
33252
|
console.log("List DryUI components.");
|
|
32764
33253
|
console.log("");
|
|
32765
33254
|
console.log("Options:");
|
|
32766
33255
|
console.log(" --category <cat> Filter by category");
|
|
33256
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
32767
33257
|
console.log("");
|
|
32768
33258
|
console.log("Categories:");
|
|
32769
33259
|
const cats = getCategories(spec);
|
|
32770
33260
|
console.log(` ${cats.join(", ")}`);
|
|
32771
33261
|
process.exit(0);
|
|
32772
33262
|
}
|
|
33263
|
+
const toon = args.includes("--toon");
|
|
32773
33264
|
let filterCategory = null;
|
|
32774
33265
|
const catIdx = args.indexOf("--category");
|
|
32775
33266
|
if (catIdx !== -1) {
|
|
@@ -32780,11 +33271,12 @@ function runList(args, spec) {
|
|
|
32780
33271
|
}
|
|
32781
33272
|
filterCategory = catValue.toLowerCase();
|
|
32782
33273
|
}
|
|
32783
|
-
|
|
33274
|
+
const mode = toon ? "toon" : "text";
|
|
33275
|
+
runCommand(getList(filterCategory, spec, { toon }), mode);
|
|
32784
33276
|
}
|
|
32785
33277
|
|
|
32786
33278
|
// src/commands/review.ts
|
|
32787
|
-
import { readFileSync as readFileSync2
|
|
33279
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
32788
33280
|
|
|
32789
33281
|
// ../mcp/src/utils.ts
|
|
32790
33282
|
function buildLineOffsets(text) {
|
|
@@ -33485,12 +33977,19 @@ function reviewComponent(code, spec, filename) {
|
|
|
33485
33977
|
|
|
33486
33978
|
// src/commands/review.ts
|
|
33487
33979
|
function getReview(filePath, spec, options) {
|
|
33488
|
-
|
|
33489
|
-
|
|
33490
|
-
|
|
33980
|
+
const missing = fileNotFound(filePath, options?.toon);
|
|
33981
|
+
if (missing)
|
|
33982
|
+
return missing;
|
|
33491
33983
|
const code = readFileSync2(filePath, "utf-8");
|
|
33492
33984
|
const filename = filePath.split("/").pop();
|
|
33493
33985
|
const result = reviewComponent(code, spec, filename);
|
|
33986
|
+
if (options?.toon) {
|
|
33987
|
+
return {
|
|
33988
|
+
output: toonReviewResult(result),
|
|
33989
|
+
error: null,
|
|
33990
|
+
exitCode: result.issues.some((i) => i.severity === "error") ? 1 : 0
|
|
33991
|
+
};
|
|
33992
|
+
}
|
|
33494
33993
|
if (options?.json) {
|
|
33495
33994
|
return {
|
|
33496
33995
|
output: JSON.stringify(result, null, 2),
|
|
@@ -33517,7 +34016,7 @@ function getReview(filePath, spec, options) {
|
|
|
33517
34016
|
}
|
|
33518
34017
|
function runReview(args, spec) {
|
|
33519
34018
|
if (args.length === 0 || args[0] === "--help") {
|
|
33520
|
-
console.log("Usage: dryui review [--json] <file.svelte>");
|
|
34019
|
+
console.log("Usage: dryui review [--json] [--toon] <file.svelte>");
|
|
33521
34020
|
console.log("");
|
|
33522
34021
|
console.log("Validate a Svelte component against the DryUI spec.");
|
|
33523
34022
|
console.log("Checks for incorrect component usage, missing props,");
|
|
@@ -33525,20 +34024,23 @@ function runReview(args, spec) {
|
|
|
33525
34024
|
console.log("");
|
|
33526
34025
|
console.log("Options:");
|
|
33527
34026
|
console.log(" --json Output raw JSON instead of formatted text");
|
|
34027
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
33528
34028
|
process.exit(args[0] === "--help" ? 0 : 1);
|
|
33529
34029
|
}
|
|
33530
34030
|
const jsonMode = args.includes("--json");
|
|
33531
|
-
const
|
|
34031
|
+
const toon = args.includes("--toon");
|
|
34032
|
+
const fileArgs = args.filter((a) => !a.startsWith("--"));
|
|
33532
34033
|
const filePath = fileArgs[0];
|
|
33533
34034
|
if (!filePath) {
|
|
33534
34035
|
console.error("Error: missing file path");
|
|
33535
34036
|
process.exit(1);
|
|
33536
34037
|
}
|
|
33537
|
-
|
|
34038
|
+
const mode = toon ? "toon" : jsonMode ? "json" : "text";
|
|
34039
|
+
runCommand(getReview(filePath, spec, { json: jsonMode, toon }), mode);
|
|
33538
34040
|
}
|
|
33539
34041
|
|
|
33540
34042
|
// src/commands/diagnose.ts
|
|
33541
|
-
import { readFileSync as readFileSync3
|
|
34043
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
33542
34044
|
|
|
33543
34045
|
// ../mcp/src/theme-checker.ts
|
|
33544
34046
|
function capture(match, index) {
|
|
@@ -34294,11 +34796,18 @@ function diagnoseTheme(css, spec) {
|
|
|
34294
34796
|
|
|
34295
34797
|
// src/commands/diagnose.ts
|
|
34296
34798
|
function getDiagnose(filePath, spec, options) {
|
|
34297
|
-
|
|
34298
|
-
|
|
34299
|
-
|
|
34799
|
+
const missing = fileNotFound(filePath, options?.toon);
|
|
34800
|
+
if (missing)
|
|
34801
|
+
return missing;
|
|
34300
34802
|
const css = readFileSync3(filePath, "utf-8");
|
|
34301
34803
|
const result = diagnoseTheme(css, spec);
|
|
34804
|
+
if (options?.toon) {
|
|
34805
|
+
return {
|
|
34806
|
+
output: toonDiagnoseResult(result),
|
|
34807
|
+
error: null,
|
|
34808
|
+
exitCode: result.issues.some((i) => i.severity === "error") ? 1 : 0
|
|
34809
|
+
};
|
|
34810
|
+
}
|
|
34302
34811
|
if (options?.json) {
|
|
34303
34812
|
return {
|
|
34304
34813
|
output: JSON.stringify(result, null, 2),
|
|
@@ -34331,26 +34840,29 @@ function getDiagnose(filePath, spec, options) {
|
|
|
34331
34840
|
}
|
|
34332
34841
|
function runDiagnose(args, spec) {
|
|
34333
34842
|
if (args.length === 0 || args[0] === "--help") {
|
|
34334
|
-
console.log("Usage: dryui diagnose [--json] <file.css>");
|
|
34843
|
+
console.log("Usage: dryui diagnose [--json] [--toon] <file.css>");
|
|
34335
34844
|
console.log("");
|
|
34336
34845
|
console.log("Validate theme CSS for missing tokens, value errors,");
|
|
34337
34846
|
console.log("contrast issues, and component token problems.");
|
|
34338
34847
|
console.log("");
|
|
34339
34848
|
console.log("Options:");
|
|
34340
34849
|
console.log(" --json Output raw JSON instead of formatted text");
|
|
34850
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
34341
34851
|
process.exit(args[0] === "--help" ? 0 : 1);
|
|
34342
34852
|
}
|
|
34343
34853
|
const jsonMode = args.includes("--json");
|
|
34344
|
-
const
|
|
34854
|
+
const toon = args.includes("--toon");
|
|
34855
|
+
const fileArgs = args.filter((a) => !a.startsWith("--"));
|
|
34345
34856
|
const filePath = fileArgs[0];
|
|
34346
34857
|
if (!filePath) {
|
|
34347
34858
|
console.error("Error: missing file path");
|
|
34348
34859
|
process.exit(1);
|
|
34349
34860
|
}
|
|
34350
|
-
|
|
34861
|
+
const mode = toon ? "toon" : jsonMode ? "json" : "text";
|
|
34862
|
+
runCommand(getDiagnose(filePath, spec, { json: jsonMode, toon }), mode);
|
|
34351
34863
|
}
|
|
34352
34864
|
|
|
34353
|
-
//
|
|
34865
|
+
// ../mcp/dist/composition-search.js
|
|
34354
34866
|
var STOP_WORDS = new Set([
|
|
34355
34867
|
"a",
|
|
34356
34868
|
"an",
|
|
@@ -34416,81 +34928,58 @@ function scoreText(tokens, text) {
|
|
|
34416
34928
|
const lower = text.toLowerCase();
|
|
34417
34929
|
return tokens.reduce((score, t) => score + (lower.includes(t) ? 1 : 0), 0);
|
|
34418
34930
|
}
|
|
34419
|
-
function
|
|
34420
|
-
if (!spec.composition) {
|
|
34421
|
-
return {
|
|
34422
|
-
output: "",
|
|
34423
|
-
error: "No composition data available. Rebuild the MCP package.",
|
|
34424
|
-
exitCode: 1
|
|
34425
|
-
};
|
|
34426
|
-
}
|
|
34931
|
+
function searchComposition(composition, query) {
|
|
34427
34932
|
const q = query.toLowerCase();
|
|
34428
34933
|
const tokens = tokenize(query);
|
|
34429
34934
|
const exactComponentMatches = [];
|
|
34430
34935
|
const exactRecipeMatches = [];
|
|
34431
|
-
for (const comp of Object.values(
|
|
34936
|
+
for (const comp of Object.values(composition.components)) {
|
|
34432
34937
|
if (comp.component.toLowerCase().includes(q) || comp.useWhen.toLowerCase().includes(q) || comp.alternatives.some((a) => a.component.toLowerCase().includes(q) || a.useWhen.toLowerCase().includes(q)) || comp.antiPatterns.some((ap) => ap.pattern.toLowerCase().includes(q))) {
|
|
34433
34938
|
exactComponentMatches.push(comp);
|
|
34434
34939
|
}
|
|
34435
34940
|
}
|
|
34436
|
-
for (const recipe of Object.values(
|
|
34941
|
+
for (const recipe of Object.values(composition.recipes)) {
|
|
34437
34942
|
if (recipe.name.toLowerCase().includes(q) || recipe.description.toLowerCase().includes(q) || recipe.tags.some((t) => t.toLowerCase().includes(q)) || recipe.components.some((c) => c.toLowerCase().includes(q))) {
|
|
34438
34943
|
exactRecipeMatches.push(recipe);
|
|
34439
34944
|
}
|
|
34440
34945
|
}
|
|
34441
|
-
let componentMatches;
|
|
34442
|
-
let recipeMatches;
|
|
34443
34946
|
if (exactComponentMatches.length || exactRecipeMatches.length) {
|
|
34444
|
-
componentMatches
|
|
34445
|
-
|
|
34446
|
-
|
|
34447
|
-
|
|
34448
|
-
|
|
34449
|
-
|
|
34450
|
-
|
|
34451
|
-
|
|
34452
|
-
|
|
34453
|
-
|
|
34454
|
-
|
|
34455
|
-
|
|
34456
|
-
|
|
34457
|
-
|
|
34458
|
-
|
|
34459
|
-
|
|
34460
|
-
|
|
34461
|
-
|
|
34462
|
-
|
|
34463
|
-
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
|
|
34467
|
-
|
|
34468
|
-
|
|
34469
|
-
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
|
|
34473
|
-
componentMatches
|
|
34474
|
-
recipeMatches
|
|
34475
|
-
}
|
|
34476
|
-
|
|
34477
|
-
|
|
34478
|
-
output: "",
|
|
34479
|
-
error: `No composition guidance found for "${query}".
|
|
34480
|
-
|
|
34481
|
-
Try:
|
|
34482
|
-
- A component name (e.g. "DatePicker", "Avatar")
|
|
34483
|
-
- A UI concept (e.g. "date input", "image placeholder")
|
|
34484
|
-
- A pattern name (e.g. "search-form", "dashboard-page")`,
|
|
34485
|
-
exitCode: 1
|
|
34486
|
-
};
|
|
34487
|
-
}
|
|
34947
|
+
return { componentMatches: exactComponentMatches, recipeMatches: exactRecipeMatches };
|
|
34948
|
+
}
|
|
34949
|
+
if (!tokens.length) {
|
|
34950
|
+
return { componentMatches: [], recipeMatches: [] };
|
|
34951
|
+
}
|
|
34952
|
+
const scoredComponents = [];
|
|
34953
|
+
for (const comp of Object.values(composition.components)) {
|
|
34954
|
+
const corpus = [
|
|
34955
|
+
comp.component,
|
|
34956
|
+
comp.useWhen,
|
|
34957
|
+
...comp.alternatives.flatMap((a) => [a.component, a.useWhen]),
|
|
34958
|
+
...comp.antiPatterns.map((ap) => ap.pattern),
|
|
34959
|
+
...comp.combinesWith
|
|
34960
|
+
].join(" ");
|
|
34961
|
+
const score = scoreText(tokens, corpus);
|
|
34962
|
+
if (score > 0)
|
|
34963
|
+
scoredComponents.push({ comp, score });
|
|
34964
|
+
}
|
|
34965
|
+
const scoredRecipes = [];
|
|
34966
|
+
for (const recipe of Object.values(composition.recipes)) {
|
|
34967
|
+
const corpus = [recipe.name, recipe.description, ...recipe.tags, ...recipe.components].join(" ");
|
|
34968
|
+
const score = scoreText(tokens, corpus);
|
|
34969
|
+
if (score > 0)
|
|
34970
|
+
scoredRecipes.push({ recipe, score });
|
|
34971
|
+
}
|
|
34972
|
+
scoredComponents.sort((a, b) => b.score - a.score);
|
|
34973
|
+
scoredRecipes.sort((a, b) => b.score - a.score);
|
|
34974
|
+
const minScore = Math.max(1, Math.floor(tokens.length * 0.3));
|
|
34975
|
+
return {
|
|
34976
|
+
componentMatches: scoredComponents.filter((s) => s.score >= minScore).slice(0, 10).map((s) => s.comp),
|
|
34977
|
+
recipeMatches: scoredRecipes.filter((s) => s.score >= minScore).slice(0, 5).map((s) => s.recipe)
|
|
34978
|
+
};
|
|
34979
|
+
}
|
|
34980
|
+
function formatCompositionResult(results) {
|
|
34488
34981
|
const lines = [];
|
|
34489
|
-
|
|
34490
|
-
lines.push(' and dark.css. app.html needs <html class="theme-auto">.');
|
|
34491
|
-
lines.push(' Not set up? Run: dryui compose "app shell"');
|
|
34492
|
-
lines.push("");
|
|
34493
|
-
for (const comp of componentMatches) {
|
|
34982
|
+
for (const comp of results.componentMatches) {
|
|
34494
34983
|
lines.push(`── ${comp.component} ──────────────────────────────`);
|
|
34495
34984
|
lines.push(`[DEV GUIDANCE — do not render as page content]`);
|
|
34496
34985
|
lines.push(`Use: ${comp.component} — ${comp.useWhen}`);
|
|
@@ -34513,7 +35002,7 @@ Try:
|
|
|
34513
35002
|
}
|
|
34514
35003
|
lines.push("");
|
|
34515
35004
|
}
|
|
34516
|
-
for (const recipe of recipeMatches) {
|
|
35005
|
+
for (const recipe of results.recipeMatches) {
|
|
34517
35006
|
lines.push(`── Recipe: ${recipe.name} ──────────────────────────────`);
|
|
34518
35007
|
lines.push(`[DEV GUIDANCE — do not render as page content]`);
|
|
34519
35008
|
lines.push(recipe.description);
|
|
@@ -34523,29 +35012,88 @@ Try:
|
|
|
34523
35012
|
lines.push(recipe.snippet);
|
|
34524
35013
|
lines.push("");
|
|
34525
35014
|
}
|
|
34526
|
-
return
|
|
34527
|
-
`)
|
|
35015
|
+
return lines.join(`
|
|
35016
|
+
`);
|
|
35017
|
+
}
|
|
35018
|
+
|
|
35019
|
+
// src/commands/compose.ts
|
|
35020
|
+
var SETUP_PREAMBLE = [
|
|
35021
|
+
"⚠ SETUP: Root +layout.svelte must import '@dryui/ui/themes/default.css'",
|
|
35022
|
+
' and dark.css. app.html needs <html class="theme-auto">.',
|
|
35023
|
+
' Not set up? Run: dryui compose "app shell"',
|
|
35024
|
+
""
|
|
35025
|
+
].join(`
|
|
35026
|
+
`);
|
|
35027
|
+
function getCompose(query, spec, options) {
|
|
35028
|
+
if (!spec.composition) {
|
|
35029
|
+
return {
|
|
35030
|
+
output: "",
|
|
35031
|
+
error: "No composition data available. Rebuild the MCP package.",
|
|
35032
|
+
exitCode: 1
|
|
35033
|
+
};
|
|
35034
|
+
}
|
|
35035
|
+
const results = searchComposition(spec.composition, query);
|
|
35036
|
+
if (!results.componentMatches.length && !results.recipeMatches.length) {
|
|
35037
|
+
if (options?.toon) {
|
|
35038
|
+
return {
|
|
35039
|
+
output: "",
|
|
35040
|
+
error: toonError("no-results", `No composition guidance for "${query}"`, [
|
|
35041
|
+
"Try a component name (DatePicker, Avatar)",
|
|
35042
|
+
"Try a UI concept (date input, image placeholder)",
|
|
35043
|
+
"Try a pattern name (search-form, dashboard-page)"
|
|
35044
|
+
]),
|
|
35045
|
+
exitCode: 1
|
|
35046
|
+
};
|
|
35047
|
+
}
|
|
35048
|
+
return {
|
|
35049
|
+
output: "",
|
|
35050
|
+
error: `No composition guidance found for "${query}".
|
|
35051
|
+
|
|
35052
|
+
Try:
|
|
35053
|
+
- A component name (e.g. "DatePicker", "Avatar")
|
|
35054
|
+
- A UI concept (e.g. "date input", "image placeholder")
|
|
35055
|
+
- A pattern name (e.g. "search-form", "dashboard-page")`,
|
|
35056
|
+
exitCode: 1
|
|
35057
|
+
};
|
|
35058
|
+
}
|
|
35059
|
+
if (options?.toon) {
|
|
35060
|
+
return {
|
|
35061
|
+
output: toonComposition(results, { full: options?.full }),
|
|
35062
|
+
error: null,
|
|
35063
|
+
exitCode: 0
|
|
35064
|
+
};
|
|
35065
|
+
}
|
|
35066
|
+
const output = SETUP_PREAMBLE + `
|
|
35067
|
+
` + formatCompositionResult(results);
|
|
35068
|
+
return { output: output.trimEnd(), error: null, exitCode: 0 };
|
|
34528
35069
|
}
|
|
34529
35070
|
function runCompose(args, spec) {
|
|
34530
35071
|
if (args.length === 0 || args[0] === "--help") {
|
|
34531
|
-
console.log("Usage: dryui compose <query>");
|
|
35072
|
+
console.log("Usage: dryui compose <query> [--toon] [--full]");
|
|
34532
35073
|
console.log("");
|
|
34533
35074
|
console.log("Look up composition guidance for building UIs with DryUI.");
|
|
34534
35075
|
console.log("Returns ranked component alternatives, anti-patterns, and recipes.");
|
|
34535
35076
|
console.log("");
|
|
35077
|
+
console.log("Options:");
|
|
35078
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
35079
|
+
console.log(" --full Include full code snippets (disables truncation)");
|
|
35080
|
+
console.log("");
|
|
34536
35081
|
console.log("Examples:");
|
|
34537
35082
|
console.log(' dryui compose "search form"');
|
|
34538
35083
|
console.log(' dryui compose "hotel card"');
|
|
34539
|
-
console.log(' dryui compose "travel booking"');
|
|
35084
|
+
console.log(' dryui compose "travel booking" --toon');
|
|
34540
35085
|
process.exit(args[0] === "--help" ? 0 : 1);
|
|
34541
35086
|
}
|
|
34542
|
-
const
|
|
34543
|
-
|
|
35087
|
+
const toon = args.includes("--toon");
|
|
35088
|
+
const full = args.includes("--full");
|
|
35089
|
+
const query = args.filter((a) => !a.startsWith("--")).join(" ").trim();
|
|
35090
|
+
const mode = toon ? "toon" : "text";
|
|
35091
|
+
runCommand(getCompose(query, spec, { toon, full }), mode);
|
|
34544
35092
|
}
|
|
34545
35093
|
|
|
34546
35094
|
// ../mcp/src/workspace-audit.ts
|
|
34547
35095
|
import { execFileSync } from "node:child_process";
|
|
34548
|
-
import { existsSync as
|
|
35096
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync, realpathSync, statSync as statSync2 } from "node:fs";
|
|
34549
35097
|
import { dirname as dirname2, relative, resolve as resolve2 } from "node:path";
|
|
34550
35098
|
var DEFAULT_INCLUDE = [
|
|
34551
35099
|
"packages/ui",
|
|
@@ -34578,7 +35126,7 @@ function normalizePath(path) {
|
|
|
34578
35126
|
}
|
|
34579
35127
|
function resolveRoot(inputPath) {
|
|
34580
35128
|
const candidate = resolve2(inputPath ?? process.cwd());
|
|
34581
|
-
if (
|
|
35129
|
+
if (existsSync3(candidate) && statSync2(candidate).isFile()) {
|
|
34582
35130
|
return dirname2(candidate);
|
|
34583
35131
|
}
|
|
34584
35132
|
return candidate;
|
|
@@ -34649,7 +35197,7 @@ function collectChangedFiles(root) {
|
|
|
34649
35197
|
}
|
|
34650
35198
|
}
|
|
34651
35199
|
function defaultInclude(root) {
|
|
34652
|
-
const included = DEFAULT_INCLUDE.filter((entry) =>
|
|
35200
|
+
const included = DEFAULT_INCLUDE.filter((entry) => existsSync3(resolve2(root, entry)));
|
|
34653
35201
|
return included.length > 0 ? included : ["."];
|
|
34654
35202
|
}
|
|
34655
35203
|
function isDefaultExcluded(path) {
|
|
@@ -34823,6 +35371,8 @@ function parseWorkspaceArgs(args) {
|
|
|
34823
35371
|
const exclude = [];
|
|
34824
35372
|
let path;
|
|
34825
35373
|
let json = false;
|
|
35374
|
+
let toon = false;
|
|
35375
|
+
let full = false;
|
|
34826
35376
|
let changed = false;
|
|
34827
35377
|
let maxSeverity = "info";
|
|
34828
35378
|
for (let index = 0;index < args.length; index++) {
|
|
@@ -34833,6 +35383,14 @@ function parseWorkspaceArgs(args) {
|
|
|
34833
35383
|
json = true;
|
|
34834
35384
|
continue;
|
|
34835
35385
|
}
|
|
35386
|
+
if (arg === "--toon") {
|
|
35387
|
+
toon = true;
|
|
35388
|
+
continue;
|
|
35389
|
+
}
|
|
35390
|
+
if (arg === "--full") {
|
|
35391
|
+
full = true;
|
|
35392
|
+
continue;
|
|
35393
|
+
}
|
|
34836
35394
|
if (arg === "--changed") {
|
|
34837
35395
|
changed = true;
|
|
34838
35396
|
continue;
|
|
@@ -34861,7 +35419,7 @@ function parseWorkspaceArgs(args) {
|
|
|
34861
35419
|
if (!path)
|
|
34862
35420
|
path = arg;
|
|
34863
35421
|
}
|
|
34864
|
-
return { path, options: { json, include, exclude, maxSeverity, changed } };
|
|
35422
|
+
return { path, options: { json, toon, full, include, exclude, maxSeverity, changed } };
|
|
34865
35423
|
}
|
|
34866
35424
|
|
|
34867
35425
|
// src/commands/doctor.ts
|
|
@@ -34874,6 +35432,13 @@ function getDoctor(inputPath, spec, options = {}) {
|
|
|
34874
35432
|
...options.maxSeverity ? { maxSeverity: options.maxSeverity } : {},
|
|
34875
35433
|
...options.changed === undefined ? {} : { changed: options.changed }
|
|
34876
35434
|
});
|
|
35435
|
+
if (options.toon) {
|
|
35436
|
+
return {
|
|
35437
|
+
output: toonWorkspaceReport(report, { title: "doctor", command: "doctor", full: options.full }),
|
|
35438
|
+
error: null,
|
|
35439
|
+
exitCode: 0
|
|
35440
|
+
};
|
|
35441
|
+
}
|
|
34877
35442
|
return {
|
|
34878
35443
|
output: formatWorkspaceReport(report, {
|
|
34879
35444
|
title: "DryUI workspace doctor",
|
|
@@ -34893,13 +35458,18 @@ function getDoctor(inputPath, spec, options = {}) {
|
|
|
34893
35458
|
}
|
|
34894
35459
|
function runDoctor(args, spec) {
|
|
34895
35460
|
if (args[0] === "--help") {
|
|
34896
|
-
console.log("Usage: dryui doctor [path] [--include <glob>] [--exclude <glob>] [--max-severity <level>] [--changed]");
|
|
35461
|
+
console.log("Usage: dryui doctor [path] [--toon] [--full] [--include <glob>] [--exclude <glob>] [--max-severity <level>] [--changed]");
|
|
34897
35462
|
console.log("");
|
|
34898
35463
|
console.log("Inspect workspace health with human-readable findings.");
|
|
35464
|
+
console.log("");
|
|
35465
|
+
console.log("Options:");
|
|
35466
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
35467
|
+
console.log(" --full Show all findings (disables truncation at 50)");
|
|
34899
35468
|
process.exit(0);
|
|
34900
35469
|
}
|
|
34901
35470
|
const { path, options } = parseWorkspaceArgs(args);
|
|
34902
|
-
|
|
35471
|
+
const mode = options.toon ? "toon" : "text";
|
|
35472
|
+
runCommand(getDoctor(path, spec, options), mode);
|
|
34903
35473
|
}
|
|
34904
35474
|
|
|
34905
35475
|
// src/commands/lint.ts
|
|
@@ -34912,6 +35482,13 @@ function getLint(inputPath, spec, options = {}) {
|
|
|
34912
35482
|
...options.changed === undefined ? {} : { changed: options.changed },
|
|
34913
35483
|
...options.maxSeverity ? { maxSeverity: options.maxSeverity } : {}
|
|
34914
35484
|
});
|
|
35485
|
+
if (options.toon) {
|
|
35486
|
+
return {
|
|
35487
|
+
output: toonWorkspaceReport(report, { title: "lint", command: "lint", full: options.full }),
|
|
35488
|
+
error: null,
|
|
35489
|
+
exitCode: report.findings.length > 0 ? 1 : 0
|
|
35490
|
+
};
|
|
35491
|
+
}
|
|
34915
35492
|
if (options.json) {
|
|
34916
35493
|
return {
|
|
34917
35494
|
output: JSON.stringify(report, null, 2),
|
|
@@ -34934,23 +35511,28 @@ function getLint(inputPath, spec, options = {}) {
|
|
|
34934
35511
|
}
|
|
34935
35512
|
function runLint(args, spec) {
|
|
34936
35513
|
if (args[0] === "--help") {
|
|
34937
|
-
console.log("Usage: dryui lint [path] [--json] [--include <glob>] [--exclude <glob>] [--max-severity <level>] [--changed]");
|
|
35514
|
+
console.log("Usage: dryui lint [path] [--json] [--toon] [--full] [--include <glob>] [--exclude <glob>] [--max-severity <level>] [--changed]");
|
|
34938
35515
|
console.log("");
|
|
34939
35516
|
console.log("Print deterministic workspace findings.");
|
|
35517
|
+
console.log("");
|
|
35518
|
+
console.log("Options:");
|
|
35519
|
+
console.log(" --toon Output in TOON format (token-optimized for agents)");
|
|
35520
|
+
console.log(" --full Show all findings (disables truncation at 50)");
|
|
34940
35521
|
process.exit(0);
|
|
34941
35522
|
}
|
|
34942
35523
|
const { path, options } = parseWorkspaceArgs(args);
|
|
34943
|
-
|
|
35524
|
+
const mode = options.toon ? "toon" : options.json ? "json" : "text";
|
|
35525
|
+
runCommand(getLint(path, spec, options), mode);
|
|
34944
35526
|
}
|
|
34945
35527
|
|
|
34946
35528
|
// src/commands/feedback.ts
|
|
34947
|
-
import { existsSync as
|
|
35529
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
34948
35530
|
import { spawnSync } from "node:child_process";
|
|
34949
35531
|
import { dirname as dirname4, resolve as resolve3 } from "node:path";
|
|
34950
35532
|
import { fileURLToPath } from "node:url";
|
|
34951
35533
|
|
|
34952
35534
|
// ../feedback-server/src/config.ts
|
|
34953
|
-
import { existsSync as
|
|
35535
|
+
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync5, writeFileSync } from "node:fs";
|
|
34954
35536
|
import { homedir } from "node:os";
|
|
34955
35537
|
import { dirname as dirname3, join } from "node:path";
|
|
34956
35538
|
var DEFAULT_FEEDBACK_PORT = 4748;
|
|
@@ -35160,7 +35742,7 @@ __export(exports_util, {
|
|
|
35160
35742
|
finalizeIssue: () => finalizeIssue,
|
|
35161
35743
|
extend: () => extend,
|
|
35162
35744
|
escapeRegex: () => escapeRegex,
|
|
35163
|
-
esc: () =>
|
|
35745
|
+
esc: () => esc2,
|
|
35164
35746
|
defineLazy: () => defineLazy,
|
|
35165
35747
|
createTransparentProxy: () => createTransparentProxy,
|
|
35166
35748
|
cloneDef: () => cloneDef,
|
|
@@ -35311,7 +35893,7 @@ function randomString(length = 10) {
|
|
|
35311
35893
|
}
|
|
35312
35894
|
return str;
|
|
35313
35895
|
}
|
|
35314
|
-
function
|
|
35896
|
+
function esc2(str) {
|
|
35315
35897
|
return JSON.stringify(str);
|
|
35316
35898
|
}
|
|
35317
35899
|
function slugify(input) {
|
|
@@ -36796,10 +37378,10 @@ function isValidJWT(token, algorithm = null) {
|
|
|
36796
37378
|
const tokensParts = token.split(".");
|
|
36797
37379
|
if (tokensParts.length !== 3)
|
|
36798
37380
|
return false;
|
|
36799
|
-
const [
|
|
36800
|
-
if (!
|
|
37381
|
+
const [header2] = tokensParts;
|
|
37382
|
+
if (!header2)
|
|
36801
37383
|
return false;
|
|
36802
|
-
const parsedHeader = JSON.parse(atob(
|
|
37384
|
+
const parsedHeader = JSON.parse(atob(header2));
|
|
36803
37385
|
if ("typ" in parsedHeader && parsedHeader?.typ !== "JWT")
|
|
36804
37386
|
return false;
|
|
36805
37387
|
if (!parsedHeader.alg)
|
|
@@ -37080,7 +37662,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
37080
37662
|
const doc = new Doc(["shape", "payload", "ctx"]);
|
|
37081
37663
|
const normalized = _normalized.value;
|
|
37082
37664
|
const parseStr = (key) => {
|
|
37083
|
-
const k =
|
|
37665
|
+
const k = esc2(key);
|
|
37084
37666
|
return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
37085
37667
|
};
|
|
37086
37668
|
doc.write(`const input = payload.value;`);
|
|
@@ -37092,7 +37674,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
37092
37674
|
doc.write(`const newResult = {};`);
|
|
37093
37675
|
for (const key of normalized.keys) {
|
|
37094
37676
|
const id = ids[key];
|
|
37095
|
-
const k =
|
|
37677
|
+
const k = esc2(key);
|
|
37096
37678
|
const schema = shape[key];
|
|
37097
37679
|
const isOptionalOut = schema?._zod?.optout === "optional";
|
|
37098
37680
|
doc.write(`const ${id} = ${parseStr(key)};`);
|
|
@@ -40676,7 +41258,7 @@ function usage() {
|
|
|
40676
41258
|
`);
|
|
40677
41259
|
}
|
|
40678
41260
|
function resolveServerEntry() {
|
|
40679
|
-
if (
|
|
41261
|
+
if (existsSync5(SERVER_DIST_PATH))
|
|
40680
41262
|
return SERVER_DIST_PATH;
|
|
40681
41263
|
return SERVER_SRC_PATH;
|
|
40682
41264
|
}
|
|
@@ -40774,32 +41356,52 @@ var USAGE = `Usage: dryui <command> [options]
|
|
|
40774
41356
|
|
|
40775
41357
|
Commands:
|
|
40776
41358
|
init Print setup snippets for a new DryUI app
|
|
40777
|
-
detect [--json] [path]
|
|
40778
|
-
|
|
41359
|
+
detect [--json] [--toon] [path]
|
|
41360
|
+
Detect DryUI project setup
|
|
41361
|
+
install [--json] [--toon] [path]
|
|
41362
|
+
Print a project install plan
|
|
40779
41363
|
add <component> Print a copyable starter snippet for a component
|
|
40780
|
-
info <component>
|
|
40781
|
-
list [--category <cat>]
|
|
40782
|
-
|
|
40783
|
-
|
|
40784
|
-
|
|
40785
|
-
|
|
41364
|
+
info <component> [--toon] Show component API reference
|
|
41365
|
+
list [--category <cat>] [--toon]
|
|
41366
|
+
List all components
|
|
41367
|
+
compose <query> [--toon] Look up composition guidance
|
|
41368
|
+
review [--json] [--toon] <file.svelte>
|
|
41369
|
+
Validate a Svelte file against DryUI spec
|
|
41370
|
+
diagnose [--json] [--toon] <file.css>
|
|
41371
|
+
Validate theme CSS
|
|
41372
|
+
doctor [path] [--toon] [--include <glob>] [--exclude <glob>] [--changed]
|
|
40786
41373
|
Inspect workspace health
|
|
40787
|
-
lint [path] [--json] [--
|
|
41374
|
+
lint [path] [--json] [--toon] [--include <glob>] [--exclude <glob>] [--changed]
|
|
40788
41375
|
Print deterministic workspace findings
|
|
40789
41376
|
feedback <subcommand> Start or inspect the feedback server
|
|
40790
41377
|
|
|
40791
41378
|
Options:
|
|
40792
41379
|
--help Show help for a command
|
|
40793
|
-
--version Show version
|
|
41380
|
+
--version Show version
|
|
41381
|
+
--toon Token-optimized output for AI agents (per-command)
|
|
41382
|
+
--full Disable truncation (use with --toon)`;
|
|
40794
41383
|
function main() {
|
|
40795
41384
|
const args = process.argv.slice(2);
|
|
40796
41385
|
const command = args[0];
|
|
40797
|
-
if (
|
|
41386
|
+
if (command === "--version" || command === "-v") {
|
|
41387
|
+
console.log(VERSION);
|
|
41388
|
+
process.exit(0);
|
|
41389
|
+
}
|
|
41390
|
+
if (command === "--help" || command === "-h") {
|
|
40798
41391
|
console.log(USAGE);
|
|
40799
41392
|
process.exit(0);
|
|
40800
41393
|
}
|
|
40801
|
-
if (command
|
|
40802
|
-
|
|
41394
|
+
if (!command) {
|
|
41395
|
+
try {
|
|
41396
|
+
const detection = detectProject(spec_default, undefined);
|
|
41397
|
+
if (detection.status === "ready" || detection.status === "partial") {
|
|
41398
|
+
console.log(`dryui v${VERSION}
|
|
41399
|
+
`);
|
|
41400
|
+
console.log(toonProjectDetection(detection));
|
|
41401
|
+
process.exit(0);
|
|
41402
|
+
}
|
|
41403
|
+
} catch {}
|
|
41404
|
+
console.log(USAGE);
|
|
40803
41405
|
process.exit(0);
|
|
40804
41406
|
}
|
|
40805
41407
|
const commandArgs = args.slice(1);
|