sbuilder-mcp 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,15 @@ All notable changes to this project are documented in this file.
|
|
|
6
6
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
7
7
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## [0.11.1] - 2026-09-09
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- sb_review now reports `hover_dead` for a node whose element keeps its hover state in a legacy home its own renderer reads instead of the universal `states.hover` slot — a `button`, for instance — naming the sb_set call that moves the values where they will actually paint.
|
|
13
|
+
- npm run codegen now refuses to run against a web_builder checkout with uncommitted changes in the directories it reads (schema/src, editor/src, server/render, server/docs), naming the dirty files instead of silently baking a concurrent session's half-finished work into the committed catalog; `--dirty` overrides it for generating against your own in-progress change.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- The generated element catalog is regenerated from a committed ref, removing a `cart-count` element and its satellite owner that had leaked in from another session's uncommitted platform change; the catalog is back to 108 elements.
|
|
17
|
+
|
|
9
18
|
## [0.11.0] - 2026-09-09
|
|
10
19
|
|
|
11
20
|
### Added
|
package/CHANGELOG.vi.md
CHANGED
|
@@ -6,6 +6,15 @@ Mọi thay đổi đáng chú ý của dự án được ghi lại trong file n
|
|
|
6
6
|
Định dạng dựa trên [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
7
7
|
và dự án tuân theo [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## [0.11.1] - 2026-09-09
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- sb_review giờ báo cáo `hover_dead` cho một node mà element của nó lưu hover state ở nơi cũ mà chính renderer của nó đọc, thay vì slot `states.hover` phổ quát — ví dụ như `button` — và nêu rõ lệnh sb_set để chuyển giá trị tới đúng nơi sẽ thực sự hiển thị.
|
|
13
|
+
- npm run codegen giờ từ chối chạy trên một checkout web_builder có thay đổi chưa commit trong các thư mục mà nó đọc (schema/src, editor/src, server/render, server/docs), nêu tên các file bẩn thay vì âm thầm đưa công việc dở dang của một phiên làm việc đồng thời vào catalog đã commit; `--dirty` cho phép ghi đè khi bạn tự tạo ra thay đổi đang dở dang đó.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Catalog element được sinh lại từ một ref đã commit, loại bỏ một element `cart-count` và chủ sở hữu satellite của nó vốn đã lọt vào từ thay đổi nền tảng chưa commit của một phiên làm việc khác; catalog trở lại 108 element.
|
|
17
|
+
|
|
9
18
|
## [0.11.0] - 2026-09-09
|
|
10
19
|
|
|
11
20
|
### Added
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const ELEMENT_SOURCE = {
|
|
2
|
-
"count":
|
|
2
|
+
"count": 108,
|
|
3
3
|
"docSchemaVersion": 2
|
|
4
4
|
};
|
|
5
5
|
export const ELEMENTS = {
|
|
@@ -1803,8 +1803,7 @@ export const ELEMENTS = {
|
|
|
1803
1803
|
"key": "action",
|
|
1804
1804
|
"label": "Action",
|
|
1805
1805
|
"controls": [
|
|
1806
|
-
"action"
|
|
1807
|
-
"icon_cart_badge"
|
|
1806
|
+
"action"
|
|
1808
1807
|
]
|
|
1809
1808
|
},
|
|
1810
1809
|
{
|
|
@@ -1877,7 +1876,6 @@ export const ELEMENTS = {
|
|
|
1877
1876
|
"icon_color",
|
|
1878
1877
|
"icon_size",
|
|
1879
1878
|
"action",
|
|
1880
|
-
"icon_cart_badge",
|
|
1881
1879
|
"padding",
|
|
1882
1880
|
"margin",
|
|
1883
1881
|
"align_self",
|
|
@@ -13844,166 +13842,6 @@ export const ELEMENTS = {
|
|
|
13844
13842
|
"dynamic"
|
|
13845
13843
|
]
|
|
13846
13844
|
},
|
|
13847
|
-
"cart-count": {
|
|
13848
|
-
"type": "cart-count",
|
|
13849
|
-
"label": "Cart count",
|
|
13850
|
-
"category": "store",
|
|
13851
|
-
"isContainer": false,
|
|
13852
|
-
"isRootOnly": false,
|
|
13853
|
-
"locked": false,
|
|
13854
|
-
"hideInLayer": false,
|
|
13855
|
-
"childAllows": [],
|
|
13856
|
-
"defaults": {
|
|
13857
|
-
"style": {
|
|
13858
|
-
"display": "inline-flex",
|
|
13859
|
-
"alignItems": "center",
|
|
13860
|
-
"justifyContent": "center",
|
|
13861
|
-
"width": "fit-content",
|
|
13862
|
-
"minWidth": "20px",
|
|
13863
|
-
"height": "20px",
|
|
13864
|
-
"paddingLeft": "6px",
|
|
13865
|
-
"paddingRight": "6px",
|
|
13866
|
-
"borderRadius": "999px",
|
|
13867
|
-
"backgroundColor": "#171717",
|
|
13868
|
-
"color": "#ffffff",
|
|
13869
|
-
"fontSize": "12px",
|
|
13870
|
-
"fontWeight": "600",
|
|
13871
|
-
"lineHeight": "1"
|
|
13872
|
-
},
|
|
13873
|
-
"specials": {
|
|
13874
|
-
"placeholder": "0",
|
|
13875
|
-
"hideWhenEmpty": true
|
|
13876
|
-
}
|
|
13877
|
-
},
|
|
13878
|
-
"inspector": [
|
|
13879
|
-
{
|
|
13880
|
-
"tab": "general",
|
|
13881
|
-
"groups": [
|
|
13882
|
-
{
|
|
13883
|
-
"key": "content",
|
|
13884
|
-
"label": "Content",
|
|
13885
|
-
"controls": [
|
|
13886
|
-
"cart_count_placeholder",
|
|
13887
|
-
"cart_count_hide_empty"
|
|
13888
|
-
]
|
|
13889
|
-
},
|
|
13890
|
-
{
|
|
13891
|
-
"key": "size",
|
|
13892
|
-
"label": "Size",
|
|
13893
|
-
"controls": [
|
|
13894
|
-
"width_select",
|
|
13895
|
-
"height_select",
|
|
13896
|
-
"size_bounds"
|
|
13897
|
-
]
|
|
13898
|
-
},
|
|
13899
|
-
{
|
|
13900
|
-
"key": "layout",
|
|
13901
|
-
"label": "Layout",
|
|
13902
|
-
"controls": [
|
|
13903
|
-
"padding",
|
|
13904
|
-
"margin",
|
|
13905
|
-
"vertical",
|
|
13906
|
-
"horizontal"
|
|
13907
|
-
]
|
|
13908
|
-
},
|
|
13909
|
-
{
|
|
13910
|
-
"key": "typography",
|
|
13911
|
-
"label": "Typography",
|
|
13912
|
-
"controls": [
|
|
13913
|
-
"font_family",
|
|
13914
|
-
"font_size",
|
|
13915
|
-
"text_style",
|
|
13916
|
-
"text_color"
|
|
13917
|
-
]
|
|
13918
|
-
},
|
|
13919
|
-
{
|
|
13920
|
-
"key": "background",
|
|
13921
|
-
"label": "Background",
|
|
13922
|
-
"controls": [
|
|
13923
|
-
"bg_color"
|
|
13924
|
-
]
|
|
13925
|
-
},
|
|
13926
|
-
{
|
|
13927
|
-
"key": "shape",
|
|
13928
|
-
"label": "Shape",
|
|
13929
|
-
"controls": [
|
|
13930
|
-
"border",
|
|
13931
|
-
"corner"
|
|
13932
|
-
]
|
|
13933
|
-
}
|
|
13934
|
-
]
|
|
13935
|
-
},
|
|
13936
|
-
{
|
|
13937
|
-
"tab": "advanced",
|
|
13938
|
-
"groups": [
|
|
13939
|
-
{
|
|
13940
|
-
"key": "spacing",
|
|
13941
|
-
"label": "Spacing",
|
|
13942
|
-
"controls": [
|
|
13943
|
-
"padding_margin"
|
|
13944
|
-
]
|
|
13945
|
-
},
|
|
13946
|
-
{
|
|
13947
|
-
"key": "display",
|
|
13948
|
-
"label": "Display",
|
|
13949
|
-
"controls": [
|
|
13950
|
-
"display"
|
|
13951
|
-
]
|
|
13952
|
-
},
|
|
13953
|
-
{
|
|
13954
|
-
"key": "class_css",
|
|
13955
|
-
"label": "Class",
|
|
13956
|
-
"controls": [
|
|
13957
|
-
"class_css"
|
|
13958
|
-
]
|
|
13959
|
-
}
|
|
13960
|
-
]
|
|
13961
|
-
}
|
|
13962
|
-
],
|
|
13963
|
-
"controls": [
|
|
13964
|
-
"cart_count_placeholder",
|
|
13965
|
-
"cart_count_hide_empty",
|
|
13966
|
-
"width_select",
|
|
13967
|
-
"height_select",
|
|
13968
|
-
"size_bounds",
|
|
13969
|
-
"padding",
|
|
13970
|
-
"margin",
|
|
13971
|
-
"vertical",
|
|
13972
|
-
"horizontal",
|
|
13973
|
-
"font_family",
|
|
13974
|
-
"font_size",
|
|
13975
|
-
"text_style",
|
|
13976
|
-
"text_color",
|
|
13977
|
-
"bg_color",
|
|
13978
|
-
"border",
|
|
13979
|
-
"corner",
|
|
13980
|
-
"padding_margin",
|
|
13981
|
-
"display",
|
|
13982
|
-
"class_css"
|
|
13983
|
-
],
|
|
13984
|
-
"description": "The number of items in the shopper's cart, as a small badge. The figure comes from the shopper's own cart in their browser, so it changes the moment they add, remove or re-count a line. Its usual home is the cart icon in the site header, where it is the only evidence on the page that the basket holds anything.",
|
|
13985
|
-
"useWhen": [
|
|
13986
|
-
"a header or navigation bar carries a cart icon and a shopper needs to see the basket is not empty",
|
|
13987
|
-
"building a sticky mobile bar or a mini-cart trigger anywhere outside the cart drawer"
|
|
13988
|
-
],
|
|
13989
|
-
"avoidWhen": [
|
|
13990
|
-
"showing what the cart COSTS — that is a cart-total, which reads a money figure",
|
|
13991
|
-
"showing how many of ONE product a shopper picked — that is the quantity stepper on the product",
|
|
13992
|
-
"showing a past order’s item count; an order is a record, not the live cart"
|
|
13993
|
-
],
|
|
13994
|
-
"contentTips": [
|
|
13995
|
-
"the placeholder is what the badge reads before the shopper’s cart is known, so write it as a real empty-cart count",
|
|
13996
|
-
"leave “hide when empty” on unless the header’s layout must never shift when the first item lands",
|
|
13997
|
-
"to put it on a cart icon, turn the badge on from the icon’s own inspector rather than placing this element and positioning it by hand"
|
|
13998
|
-
],
|
|
13999
|
-
"semantics": [
|
|
14000
|
-
"cart",
|
|
14001
|
-
"count",
|
|
14002
|
-
"badge",
|
|
14003
|
-
"header",
|
|
14004
|
-
"commerce"
|
|
14005
|
-
]
|
|
14006
|
-
},
|
|
14007
13845
|
"cart-total": {
|
|
14008
13846
|
"type": "cart-total",
|
|
14009
13847
|
"label": "Cart total",
|
|
@@ -33839,28 +33677,6 @@ export const TRAIT_WRITES = {
|
|
|
33839
33677
|
}
|
|
33840
33678
|
]
|
|
33841
33679
|
},
|
|
33842
|
-
"cart_count_placeholder": {
|
|
33843
|
-
"key": "cart_count_placeholder",
|
|
33844
|
-
"label": "Empty count",
|
|
33845
|
-
"writes": [
|
|
33846
|
-
{
|
|
33847
|
-
"target": "specials",
|
|
33848
|
-
"writeKey": "placeholder",
|
|
33849
|
-
"type": "string"
|
|
33850
|
-
}
|
|
33851
|
-
]
|
|
33852
|
-
},
|
|
33853
|
-
"cart_count_hide_empty": {
|
|
33854
|
-
"key": "cart_count_hide_empty",
|
|
33855
|
-
"label": "Hide when empty",
|
|
33856
|
-
"writes": [
|
|
33857
|
-
{
|
|
33858
|
-
"target": "specials",
|
|
33859
|
-
"writeKey": "hideWhenEmpty",
|
|
33860
|
-
"type": "boolean"
|
|
33861
|
-
}
|
|
33862
|
-
]
|
|
33863
|
-
},
|
|
33864
33680
|
"cart_total_placeholder": {
|
|
33865
33681
|
"key": "cart_total_placeholder",
|
|
33866
33682
|
"label": "Empty amount",
|
|
@@ -34221,13 +34037,6 @@ export const TRAIT_WRITES = {
|
|
|
34221
34037
|
}
|
|
34222
34038
|
};
|
|
34223
34039
|
export const SATELLITE_RULES = {
|
|
34224
|
-
"icon": [
|
|
34225
|
-
{
|
|
34226
|
-
"type": "cart-count",
|
|
34227
|
-
"configKey": "cartCountId",
|
|
34228
|
-
"optional": true
|
|
34229
|
-
}
|
|
34230
|
-
],
|
|
34231
34040
|
"tab": [
|
|
34232
34041
|
{
|
|
34233
34042
|
"type": "tab-item",
|
|
@@ -60,6 +60,10 @@ export const FIX = {
|
|
|
60
60
|
'{ "overflowX": "visible", "overflowY": "visible" } — or move the pinned node outside it. ' +
|
|
61
61
|
'Sticky resolves against its nearest SCROLLING ancestor, so a clipping one becomes that ' +
|
|
62
62
|
'ancestor and the node pins inside a box that never scrolls.',
|
|
63
|
+
hover_dead: 'Rewrite it: sb_set id "<id>", namespace style, state "hover", keys { … } — sb_set now ' +
|
|
64
|
+
'routes a hover to the home its element declares, and reports where it went. The values ' +
|
|
65
|
+
'currently in states.hover are read by nobody; remove them with the same call\'s `unset` ' +
|
|
66
|
+
'once the working copy is in place.',
|
|
63
67
|
stuck_no_host: 'Pin something: sb_set id "<id>" (or the section it lives in), namespace style, keys ' +
|
|
64
68
|
'{ "position": "sticky" } — sb_set seeds the offset and the layer order with it. Until ' +
|
|
65
69
|
'then the platform compiles no rule for this state at all, so the override is stored, ' +
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { childrenOf, childrenWithSatellites, isOverlay, pageChildren, appBlockRoot, SPEC_GLOBAL_REF, SPEC_APP_BLOCK_REF } from '../../core/tree.js';
|
|
2
2
|
import { STUCK_STATE, stickyBlockedBy, stuckHostOf, isPinnedNode } from './sticky.js';
|
|
3
|
+
import { HOVER_STATE, hoverHome } from './hover.js';
|
|
3
4
|
import { ELEMENTS, BINDING_SOURCES, BOUND_SPECIALS, FIRST_CHILD_ONLY, SATELLITE_RULES, ELEMENT_SEEDS } from '../../catalog/elements.generated.js';
|
|
4
5
|
import { fill } from './findings.js';
|
|
5
6
|
/**
|
|
@@ -224,6 +225,32 @@ export function reviewDesign(doc) {
|
|
|
224
225
|
styled.states?.[STUCK_STATE],
|
|
225
226
|
...Object.values(styled.responsive ?? {}).map((r) => r?.states?.[STUCK_STATE]),
|
|
226
227
|
];
|
|
228
|
+
// A HOVER STORED WHERE NOBODY READS IT. The universal hover state is not the
|
|
229
|
+
// only home: an element whose meta declares a Hover variant keeps it
|
|
230
|
+
// somewhere its own renderer looks, and for a `button` that is the flat
|
|
231
|
+
// `config.stateHover` map. Every hover this server wrote onto a button
|
|
232
|
+
// before it learned that is still sitting in `states.hover`, painting
|
|
233
|
+
// nothing — on a control that is the single most common thing anyone gives
|
|
234
|
+
// a hover to.
|
|
235
|
+
const hoverSlots = [
|
|
236
|
+
styled.states?.[HOVER_STATE],
|
|
237
|
+
...Object.values(styled.responsive ?? {}).map((r) => r?.states?.[HOVER_STATE]),
|
|
238
|
+
];
|
|
239
|
+
const hasHover = hoverSlots.some((slot) => {
|
|
240
|
+
const h = slot;
|
|
241
|
+
return !!h && (Object.keys(h.style ?? {}).length > 0 || Object.keys(h.config ?? {}).length > 0);
|
|
242
|
+
});
|
|
243
|
+
if (hasHover && hoverHome(type) === 'legacy') {
|
|
244
|
+
out.push({
|
|
245
|
+
code: 'hover_dead',
|
|
246
|
+
nodeId: id,
|
|
247
|
+
type,
|
|
248
|
+
problem: `"${type}" keeps its hover in config.stateHover — the flat map its own renderer ` +
|
|
249
|
+
'compiles — and the platform\'s universal hover compiler stands aside for it. These ' +
|
|
250
|
+
'states.hover values are stored, saved, published and painted by nobody.',
|
|
251
|
+
fix: fill('hover_dead', { id }),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
227
254
|
const hasStuck = stuckSlots.some((slot) => {
|
|
228
255
|
const s = slot;
|
|
229
256
|
return !!s && (Object.keys(s.style ?? {}).length > 0 || Object.keys(s.config ?? {}).length > 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sbuilder-mcp",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "MCP server that designs and operates a Store Builder site — pages, data, theme and publish — through the platform's own API and live-edit protocol.",
|
|
5
5
|
"mcpName": "io.github.vuluu2k/sbuilder-mcp",
|
|
6
6
|
"type": "module",
|