@thinkingos/vsl-sdk 0.1.0 → 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.d.mts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +51 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -60,6 +60,18 @@ interface ElementCss {
|
|
|
60
60
|
pointerEvents?: string;
|
|
61
61
|
overflow?: string;
|
|
62
62
|
height?: string;
|
|
63
|
+
/** Background color (computed) — для sty.bg в VslObject. */
|
|
64
|
+
backgroundColor?: string;
|
|
65
|
+
/** Text/foreground color (computed) — для sty.fg в VslObject. */
|
|
66
|
+
color?: string;
|
|
67
|
+
/** Border shorthand (computed) — для sty.border в VslObject. */
|
|
68
|
+
border?: string;
|
|
69
|
+
/** Border radius (computed) — для sty.radius в VslObject. */
|
|
70
|
+
borderRadius?: string;
|
|
71
|
+
/** Box shadow (computed) — для sty.shadow в VslObject. */
|
|
72
|
+
boxShadow?: string;
|
|
73
|
+
/** Font family (computed) — для sty.font.family в VslObject. */
|
|
74
|
+
fontFamily?: string;
|
|
63
75
|
}
|
|
64
76
|
/** Собственный текст элемента: только прямые текстовые узлы, whitespace-нормализация. */
|
|
65
77
|
declare function ownText(el: Element): string;
|
|
@@ -76,7 +88,7 @@ declare function extractDomTree(root?: Element): ExtractedElement[];
|
|
|
76
88
|
* Семантический тип объекта VSL (поле `t`): L1-теги + L2-роли (T1.1.3/T1.1.4),
|
|
77
89
|
* L3-CSS (T1.5.1), L4-структурные (T1.5.2), L5-vision (T1.5.4).
|
|
78
90
|
*/
|
|
79
|
-
type VslType = 'button' | 'input' | 'link' | 'nav' | 'header' | 'main' | 'container' | 'image' | 'select' | 'textarea' | 'modal' | 'tab' | 'heading' | 'footer' | 'scrollable_container' | 'toolbar' | 'list' | 'grid' | 'form_field' | 'tab_bar' | 'layout' | 'icon' | 'chart' | 'custom_widget' | 'unknown';
|
|
91
|
+
type VslType = 'button' | 'input' | 'file_input' | 'link' | 'nav' | 'header' | 'main' | 'container' | 'image' | 'select' | 'textarea' | 'modal' | 'tab' | 'heading' | 'footer' | 'scrollable_container' | 'toolbar' | 'list' | 'grid' | 'form_field' | 'tab_bar' | 'layout' | 'icon' | 'chart' | 'custom_widget' | 'unknown';
|
|
80
92
|
/** Состояние объекта VSL (поле `st`) — из ARIA-атрибутов (T1.1.4). */
|
|
81
93
|
type VslState = 'checked' | 'expanded' | 'disabled';
|
|
82
94
|
/** Тип визуального фрагмента — выход классификации vision (§2.2.2 Шаг 2). */
|
|
@@ -89,6 +101,29 @@ interface VslFragmentMeta$1 {
|
|
|
89
101
|
hash?: string;
|
|
90
102
|
cached_at?: string;
|
|
91
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Визуальные стили объекта VSL (DESIGN_SYSTEM.md §4.3).
|
|
106
|
+
* Optional: только для визуально значимых элементов.
|
|
107
|
+
* Все значения — computed styles в момент snapshot.
|
|
108
|
+
*/
|
|
109
|
+
interface VslStyle {
|
|
110
|
+
/** Background color (computed). */
|
|
111
|
+
bg?: string;
|
|
112
|
+
/** Text/foreground color (computed). */
|
|
113
|
+
fg?: string;
|
|
114
|
+
/** Border shorthand (computed). */
|
|
115
|
+
border?: string;
|
|
116
|
+
/** Border radius (computed). */
|
|
117
|
+
radius?: string;
|
|
118
|
+
/** Box shadow (computed). */
|
|
119
|
+
shadow?: string;
|
|
120
|
+
/** Font properties. */
|
|
121
|
+
font?: {
|
|
122
|
+
family?: string;
|
|
123
|
+
size?: string;
|
|
124
|
+
weight?: string;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
92
127
|
/**
|
|
93
128
|
* Запись реестра visual_fragments документа (§2.2.2, ARCHITECTURE.md:L265-284).
|
|
94
129
|
* ТОЛЬКО метаданные: base64-данные изображений живут в VisualFragmentStore
|
|
@@ -148,6 +183,12 @@ interface VslObject {
|
|
|
148
183
|
vf?: string;
|
|
149
184
|
/** Метаданные фрагмента (§4.4). */
|
|
150
185
|
vf_meta?: VslFragmentMeta$1;
|
|
186
|
+
/** Визуальные стили (DESIGN_SYSTEM.md §4.3). Optional: только для визуально значимых элементов. */
|
|
187
|
+
sty?: VslStyle;
|
|
188
|
+
/** Accept attribute для file_input (например, '.pdf,.docx'). */
|
|
189
|
+
accept?: string;
|
|
190
|
+
/** Multiple attribute для file_input — разрешена загрузка нескольких файлов. */
|
|
191
|
+
multiple?: boolean;
|
|
151
192
|
}
|
|
152
193
|
interface VslDocument {
|
|
153
194
|
vsl_version: string;
|
|
@@ -250,6 +291,8 @@ interface SegmentedElement {
|
|
|
250
291
|
txt: string | null;
|
|
251
292
|
/** Состояние из ARIA (checked/expanded/disabled) или null. */
|
|
252
293
|
st: VslState | null;
|
|
294
|
+
/** CSS-подмножество для визуальных стилей (передаётся в Builder для sty). */
|
|
295
|
+
css?: ElementCss;
|
|
253
296
|
ch: SegmentedElement[];
|
|
254
297
|
/** Ссылка на визуальный фрагмент (заполняется enrichWithVision, T1.5.4). */
|
|
255
298
|
vf?: string;
|
|
@@ -1055,7 +1098,7 @@ declare const ACTION_TOOL_SCHEMA: {
|
|
|
1055
1098
|
action: {
|
|
1056
1099
|
type: string;
|
|
1057
1100
|
description: string;
|
|
1058
|
-
enum: ("select" | "
|
|
1101
|
+
enum: ("select" | "type" | "click" | "close" | "check" | "uncheck" | "clear" | "scroll" | "hover" | "focus" | "blur" | "drag" | "drop" | "submit" | "reset" | "open" | "expand" | "collapse" | "wait" | "navigate" | "go_back" | "go_forward" | "refresh" | "download")[];
|
|
1059
1102
|
};
|
|
1060
1103
|
target_id: {
|
|
1061
1104
|
type: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,18 @@ interface ElementCss {
|
|
|
60
60
|
pointerEvents?: string;
|
|
61
61
|
overflow?: string;
|
|
62
62
|
height?: string;
|
|
63
|
+
/** Background color (computed) — для sty.bg в VslObject. */
|
|
64
|
+
backgroundColor?: string;
|
|
65
|
+
/** Text/foreground color (computed) — для sty.fg в VslObject. */
|
|
66
|
+
color?: string;
|
|
67
|
+
/** Border shorthand (computed) — для sty.border в VslObject. */
|
|
68
|
+
border?: string;
|
|
69
|
+
/** Border radius (computed) — для sty.radius в VslObject. */
|
|
70
|
+
borderRadius?: string;
|
|
71
|
+
/** Box shadow (computed) — для sty.shadow в VslObject. */
|
|
72
|
+
boxShadow?: string;
|
|
73
|
+
/** Font family (computed) — для sty.font.family в VslObject. */
|
|
74
|
+
fontFamily?: string;
|
|
63
75
|
}
|
|
64
76
|
/** Собственный текст элемента: только прямые текстовые узлы, whitespace-нормализация. */
|
|
65
77
|
declare function ownText(el: Element): string;
|
|
@@ -76,7 +88,7 @@ declare function extractDomTree(root?: Element): ExtractedElement[];
|
|
|
76
88
|
* Семантический тип объекта VSL (поле `t`): L1-теги + L2-роли (T1.1.3/T1.1.4),
|
|
77
89
|
* L3-CSS (T1.5.1), L4-структурные (T1.5.2), L5-vision (T1.5.4).
|
|
78
90
|
*/
|
|
79
|
-
type VslType = 'button' | 'input' | 'link' | 'nav' | 'header' | 'main' | 'container' | 'image' | 'select' | 'textarea' | 'modal' | 'tab' | 'heading' | 'footer' | 'scrollable_container' | 'toolbar' | 'list' | 'grid' | 'form_field' | 'tab_bar' | 'layout' | 'icon' | 'chart' | 'custom_widget' | 'unknown';
|
|
91
|
+
type VslType = 'button' | 'input' | 'file_input' | 'link' | 'nav' | 'header' | 'main' | 'container' | 'image' | 'select' | 'textarea' | 'modal' | 'tab' | 'heading' | 'footer' | 'scrollable_container' | 'toolbar' | 'list' | 'grid' | 'form_field' | 'tab_bar' | 'layout' | 'icon' | 'chart' | 'custom_widget' | 'unknown';
|
|
80
92
|
/** Состояние объекта VSL (поле `st`) — из ARIA-атрибутов (T1.1.4). */
|
|
81
93
|
type VslState = 'checked' | 'expanded' | 'disabled';
|
|
82
94
|
/** Тип визуального фрагмента — выход классификации vision (§2.2.2 Шаг 2). */
|
|
@@ -89,6 +101,29 @@ interface VslFragmentMeta$1 {
|
|
|
89
101
|
hash?: string;
|
|
90
102
|
cached_at?: string;
|
|
91
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Визуальные стили объекта VSL (DESIGN_SYSTEM.md §4.3).
|
|
106
|
+
* Optional: только для визуально значимых элементов.
|
|
107
|
+
* Все значения — computed styles в момент snapshot.
|
|
108
|
+
*/
|
|
109
|
+
interface VslStyle {
|
|
110
|
+
/** Background color (computed). */
|
|
111
|
+
bg?: string;
|
|
112
|
+
/** Text/foreground color (computed). */
|
|
113
|
+
fg?: string;
|
|
114
|
+
/** Border shorthand (computed). */
|
|
115
|
+
border?: string;
|
|
116
|
+
/** Border radius (computed). */
|
|
117
|
+
radius?: string;
|
|
118
|
+
/** Box shadow (computed). */
|
|
119
|
+
shadow?: string;
|
|
120
|
+
/** Font properties. */
|
|
121
|
+
font?: {
|
|
122
|
+
family?: string;
|
|
123
|
+
size?: string;
|
|
124
|
+
weight?: string;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
92
127
|
/**
|
|
93
128
|
* Запись реестра visual_fragments документа (§2.2.2, ARCHITECTURE.md:L265-284).
|
|
94
129
|
* ТОЛЬКО метаданные: base64-данные изображений живут в VisualFragmentStore
|
|
@@ -148,6 +183,12 @@ interface VslObject {
|
|
|
148
183
|
vf?: string;
|
|
149
184
|
/** Метаданные фрагмента (§4.4). */
|
|
150
185
|
vf_meta?: VslFragmentMeta$1;
|
|
186
|
+
/** Визуальные стили (DESIGN_SYSTEM.md §4.3). Optional: только для визуально значимых элементов. */
|
|
187
|
+
sty?: VslStyle;
|
|
188
|
+
/** Accept attribute для file_input (например, '.pdf,.docx'). */
|
|
189
|
+
accept?: string;
|
|
190
|
+
/** Multiple attribute для file_input — разрешена загрузка нескольких файлов. */
|
|
191
|
+
multiple?: boolean;
|
|
151
192
|
}
|
|
152
193
|
interface VslDocument {
|
|
153
194
|
vsl_version: string;
|
|
@@ -250,6 +291,8 @@ interface SegmentedElement {
|
|
|
250
291
|
txt: string | null;
|
|
251
292
|
/** Состояние из ARIA (checked/expanded/disabled) или null. */
|
|
252
293
|
st: VslState | null;
|
|
294
|
+
/** CSS-подмножество для визуальных стилей (передаётся в Builder для sty). */
|
|
295
|
+
css?: ElementCss;
|
|
253
296
|
ch: SegmentedElement[];
|
|
254
297
|
/** Ссылка на визуальный фрагмент (заполняется enrichWithVision, T1.5.4). */
|
|
255
298
|
vf?: string;
|
|
@@ -1055,7 +1098,7 @@ declare const ACTION_TOOL_SCHEMA: {
|
|
|
1055
1098
|
action: {
|
|
1056
1099
|
type: string;
|
|
1057
1100
|
description: string;
|
|
1058
|
-
enum: ("select" | "
|
|
1101
|
+
enum: ("select" | "type" | "click" | "close" | "check" | "uncheck" | "clear" | "scroll" | "hover" | "focus" | "blur" | "drag" | "drop" | "submit" | "reset" | "open" | "expand" | "collapse" | "wait" | "navigate" | "go_back" | "go_forward" | "refresh" | "download")[];
|
|
1059
1102
|
};
|
|
1060
1103
|
target_id: {
|
|
1061
1104
|
type: string;
|
package/dist/index.js
CHANGED
|
@@ -109,7 +109,13 @@ var CSS_PROPERTIES = [
|
|
|
109
109
|
["opacity", "opacity"],
|
|
110
110
|
["pointerEvents", "pointer-events"],
|
|
111
111
|
["overflow", "overflow"],
|
|
112
|
-
["height", "height"]
|
|
112
|
+
["height", "height"],
|
|
113
|
+
["backgroundColor", "background-color"],
|
|
114
|
+
["color", "color"],
|
|
115
|
+
["border", "border"],
|
|
116
|
+
["borderRadius", "border-radius"],
|
|
117
|
+
["boxShadow", "box-shadow"],
|
|
118
|
+
["fontFamily", "font-family"]
|
|
113
119
|
];
|
|
114
120
|
function captureCss(el) {
|
|
115
121
|
const view = viewOf(el);
|
|
@@ -319,14 +325,16 @@ function isAriaHidden(attributes) {
|
|
|
319
325
|
}
|
|
320
326
|
function segmentOne(el) {
|
|
321
327
|
const { attributes } = el;
|
|
328
|
+
const isFileInput = el.tag === "input" && attributes["type"] === "file";
|
|
322
329
|
return {
|
|
323
330
|
tag: el.tag,
|
|
324
331
|
indexPath: el.indexPath,
|
|
325
332
|
rect: el.rect,
|
|
326
333
|
attributes,
|
|
327
|
-
t: resolveLevel1Type(el.tag) ?? resolveAriaRoleType(attributes["role"]) ?? resolveLevel3Type(el.css, attributes),
|
|
334
|
+
t: isFileInput ? "file_input" : resolveLevel1Type(el.tag) ?? resolveAriaRoleType(attributes["role"]) ?? resolveLevel3Type(el.css, attributes),
|
|
328
335
|
txt: attributes["aria-label"] ?? el.text,
|
|
329
336
|
st: resolveSt(attributes),
|
|
337
|
+
css: el.css,
|
|
330
338
|
ch: []
|
|
331
339
|
};
|
|
332
340
|
}
|
|
@@ -379,6 +387,8 @@ function defaultActions(t, st, attributes) {
|
|
|
379
387
|
return ["click", "select"];
|
|
380
388
|
case "textarea":
|
|
381
389
|
return ["click", "type", "clear"];
|
|
390
|
+
case "file_input":
|
|
391
|
+
return ["click", "upload"];
|
|
382
392
|
default:
|
|
383
393
|
return void 0;
|
|
384
394
|
}
|
|
@@ -391,6 +401,39 @@ function baseSemanticScore(el) {
|
|
|
391
401
|
if (el.txt) score += 1;
|
|
392
402
|
return score;
|
|
393
403
|
}
|
|
404
|
+
function extractVisualStyles(css) {
|
|
405
|
+
if (!css) return void 0;
|
|
406
|
+
const style = {};
|
|
407
|
+
let hasContent = false;
|
|
408
|
+
if (css.backgroundColor && css.backgroundColor !== "transparent" && !css.backgroundColor.includes("rgba(0, 0, 0, 0)")) {
|
|
409
|
+
style.bg = css.backgroundColor;
|
|
410
|
+
hasContent = true;
|
|
411
|
+
}
|
|
412
|
+
if (css.color && css.color !== "rgb(0, 0, 0)") {
|
|
413
|
+
style.fg = css.color;
|
|
414
|
+
hasContent = true;
|
|
415
|
+
}
|
|
416
|
+
if (css.border && css.border !== "none" && !css.border.startsWith("0px")) {
|
|
417
|
+
style.border = css.border;
|
|
418
|
+
hasContent = true;
|
|
419
|
+
}
|
|
420
|
+
if (css.borderRadius && css.borderRadius !== "0px") {
|
|
421
|
+
style.radius = css.borderRadius;
|
|
422
|
+
hasContent = true;
|
|
423
|
+
}
|
|
424
|
+
if (css.boxShadow && css.boxShadow !== "none") {
|
|
425
|
+
style.shadow = css.boxShadow;
|
|
426
|
+
hasContent = true;
|
|
427
|
+
}
|
|
428
|
+
if (css.fontFamily || css.fontSize || css.fontWeight) {
|
|
429
|
+
style.font = {};
|
|
430
|
+
if (css.fontFamily) style.font.family = css.fontFamily;
|
|
431
|
+
if (css.fontSize) style.font.size = css.fontSize;
|
|
432
|
+
if (css.fontWeight) style.font.weight = css.fontWeight;
|
|
433
|
+
hasContent = true;
|
|
434
|
+
}
|
|
435
|
+
return hasContent ? style : void 0;
|
|
436
|
+
}
|
|
394
437
|
function toVslObject(el, viewport, includedChildren, textBlocks, counter) {
|
|
395
438
|
const t = el.t ?? "container";
|
|
396
439
|
const object = {
|
|
@@ -417,6 +460,12 @@ function toVslObject(el, viewport, includedChildren, textBlocks, counter) {
|
|
|
417
460
|
if (includedChildren.length > 0) object.ch = includedChildren;
|
|
418
461
|
if (el.vf !== void 0) object.vf = el.vf;
|
|
419
462
|
if (el.vf_meta !== void 0) object.vf_meta = el.vf_meta;
|
|
463
|
+
const sty = extractVisualStyles(el.css);
|
|
464
|
+
if (sty !== void 0) object.sty = sty;
|
|
465
|
+
if (t === "file_input") {
|
|
466
|
+
if (el.attributes["accept"] !== void 0) object.accept = el.attributes["accept"];
|
|
467
|
+
if (el.attributes["multiple"] !== void 0) object.multiple = true;
|
|
468
|
+
}
|
|
420
469
|
return object;
|
|
421
470
|
}
|
|
422
471
|
function convert(el, viewport, textBlocks, counter) {
|