@thinkingos/vsl-sdk 0.1.1 → 0.3.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 +70 -28
- package/dist/index.d.ts +70 -28
- package/dist/index.js +105 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +105 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -48,7 +48,13 @@ var CSS_PROPERTIES = [
|
|
|
48
48
|
["opacity", "opacity"],
|
|
49
49
|
["pointerEvents", "pointer-events"],
|
|
50
50
|
["overflow", "overflow"],
|
|
51
|
-
["height", "height"]
|
|
51
|
+
["height", "height"],
|
|
52
|
+
["backgroundColor", "background-color"],
|
|
53
|
+
["color", "color"],
|
|
54
|
+
["border", "border"],
|
|
55
|
+
["borderRadius", "border-radius"],
|
|
56
|
+
["boxShadow", "box-shadow"],
|
|
57
|
+
["fontFamily", "font-family"]
|
|
52
58
|
];
|
|
53
59
|
function captureCss(el) {
|
|
54
60
|
const view = viewOf(el);
|
|
@@ -258,14 +264,16 @@ function isAriaHidden(attributes) {
|
|
|
258
264
|
}
|
|
259
265
|
function segmentOne(el) {
|
|
260
266
|
const { attributes } = el;
|
|
267
|
+
const isFileInput = el.tag === "input" && attributes["type"] === "file";
|
|
261
268
|
return {
|
|
262
269
|
tag: el.tag,
|
|
263
270
|
indexPath: el.indexPath,
|
|
264
271
|
rect: el.rect,
|
|
265
272
|
attributes,
|
|
266
|
-
t: resolveLevel1Type(el.tag) ?? resolveAriaRoleType(attributes["role"]) ?? resolveLevel3Type(el.css, attributes),
|
|
273
|
+
t: isFileInput ? "file_input" : resolveLevel1Type(el.tag) ?? resolveAriaRoleType(attributes["role"]) ?? resolveLevel3Type(el.css, attributes),
|
|
267
274
|
txt: attributes["aria-label"] ?? el.text,
|
|
268
275
|
st: resolveSt(attributes),
|
|
276
|
+
css: el.css,
|
|
269
277
|
ch: []
|
|
270
278
|
};
|
|
271
279
|
}
|
|
@@ -318,6 +326,8 @@ function defaultActions(t, st, attributes) {
|
|
|
318
326
|
return ["click", "select"];
|
|
319
327
|
case "textarea":
|
|
320
328
|
return ["click", "type", "clear"];
|
|
329
|
+
case "file_input":
|
|
330
|
+
return ["click", "upload"];
|
|
321
331
|
default:
|
|
322
332
|
return void 0;
|
|
323
333
|
}
|
|
@@ -330,6 +340,39 @@ function baseSemanticScore(el) {
|
|
|
330
340
|
if (el.txt) score += 1;
|
|
331
341
|
return score;
|
|
332
342
|
}
|
|
343
|
+
function extractVisualStyles(css) {
|
|
344
|
+
if (!css) return void 0;
|
|
345
|
+
const style = {};
|
|
346
|
+
let hasContent = false;
|
|
347
|
+
if (css.backgroundColor && css.backgroundColor !== "transparent" && !css.backgroundColor.includes("rgba(0, 0, 0, 0)")) {
|
|
348
|
+
style.bg = css.backgroundColor;
|
|
349
|
+
hasContent = true;
|
|
350
|
+
}
|
|
351
|
+
if (css.color && css.color !== "rgb(0, 0, 0)") {
|
|
352
|
+
style.fg = css.color;
|
|
353
|
+
hasContent = true;
|
|
354
|
+
}
|
|
355
|
+
if (css.border && css.border !== "none" && !css.border.startsWith("0px")) {
|
|
356
|
+
style.border = css.border;
|
|
357
|
+
hasContent = true;
|
|
358
|
+
}
|
|
359
|
+
if (css.borderRadius && css.borderRadius !== "0px") {
|
|
360
|
+
style.radius = css.borderRadius;
|
|
361
|
+
hasContent = true;
|
|
362
|
+
}
|
|
363
|
+
if (css.boxShadow && css.boxShadow !== "none") {
|
|
364
|
+
style.shadow = css.boxShadow;
|
|
365
|
+
hasContent = true;
|
|
366
|
+
}
|
|
367
|
+
if (css.fontFamily || css.fontSize || css.fontWeight) {
|
|
368
|
+
style.font = {};
|
|
369
|
+
if (css.fontFamily) style.font.family = css.fontFamily;
|
|
370
|
+
if (css.fontSize) style.font.size = css.fontSize;
|
|
371
|
+
if (css.fontWeight) style.font.weight = css.fontWeight;
|
|
372
|
+
hasContent = true;
|
|
373
|
+
}
|
|
374
|
+
return hasContent ? style : void 0;
|
|
375
|
+
}
|
|
333
376
|
function toVslObject(el, viewport, includedChildren, textBlocks, counter) {
|
|
334
377
|
const t = el.t ?? "container";
|
|
335
378
|
const object = {
|
|
@@ -356,6 +399,12 @@ function toVslObject(el, viewport, includedChildren, textBlocks, counter) {
|
|
|
356
399
|
if (includedChildren.length > 0) object.ch = includedChildren;
|
|
357
400
|
if (el.vf !== void 0) object.vf = el.vf;
|
|
358
401
|
if (el.vf_meta !== void 0) object.vf_meta = el.vf_meta;
|
|
402
|
+
const sty = extractVisualStyles(el.css);
|
|
403
|
+
if (sty !== void 0) object.sty = sty;
|
|
404
|
+
if (t === "file_input") {
|
|
405
|
+
if (el.attributes["accept"] !== void 0) object.accept = el.attributes["accept"];
|
|
406
|
+
if (el.attributes["multiple"] !== void 0) object.multiple = true;
|
|
407
|
+
}
|
|
359
408
|
return object;
|
|
360
409
|
}
|
|
361
410
|
function convert(el, viewport, textBlocks, counter) {
|
|
@@ -542,6 +591,8 @@ function objectsEqual(a, b) {
|
|
|
542
591
|
return computeContentHash(a) === computeContentHash(b) && computeCoordHash(a) === computeCoordHash(b);
|
|
543
592
|
}
|
|
544
593
|
function tuple2Equal(a, b) {
|
|
594
|
+
if (a === null || a === void 0) return b === null || b === void 0;
|
|
595
|
+
if (b === null || b === void 0) return false;
|
|
545
596
|
return a[0] === b[0] && a[1] === b[1];
|
|
546
597
|
}
|
|
547
598
|
function stringArrayEqual(a, b) {
|
|
@@ -678,6 +729,25 @@ var VslSnapshotSession = class {
|
|
|
678
729
|
constructor(store = createCacheStore()) {
|
|
679
730
|
this.store = store;
|
|
680
731
|
}
|
|
732
|
+
/**
|
|
733
|
+
* Сбрасывает состояние сессии (URL, viewport, документ, версия).
|
|
734
|
+
* Следующий вызов snapshot() вернёт полный документ (как первый вызов).
|
|
735
|
+
*/
|
|
736
|
+
clear() {
|
|
737
|
+
this.store.clear();
|
|
738
|
+
this.lastUrl = null;
|
|
739
|
+
this.lastViewport = null;
|
|
740
|
+
this.lastDocument = null;
|
|
741
|
+
this.version = 0;
|
|
742
|
+
}
|
|
743
|
+
/** Возвращает последний полный документ (не diff). */
|
|
744
|
+
getLastDocument() {
|
|
745
|
+
return this.lastDocument;
|
|
746
|
+
}
|
|
747
|
+
/** Текущая версия документа (инкрементируется при каждом diff). */
|
|
748
|
+
getVersion() {
|
|
749
|
+
return this.version;
|
|
750
|
+
}
|
|
681
751
|
/**
|
|
682
752
|
* Строит VSL из DOM поддерева root (extractDomTree → segmentTree →
|
|
683
753
|
* buildVslDocument) и возвращает полный документ либо дифф (см. шапку).
|
|
@@ -686,6 +756,15 @@ var VslSnapshotSession = class {
|
|
|
686
756
|
const elements = segmentTree(extractDomTree(root));
|
|
687
757
|
return this.commit(elements, this.buildOptions(root, input), input);
|
|
688
758
|
}
|
|
759
|
+
/**
|
|
760
|
+
* Вариант snapshot() для pre-extracted elements (MCP сервер, Node.js контекст).
|
|
761
|
+
* Принимает ExtractedElement[] напрямую (без DOM Element), проходит тот же
|
|
762
|
+
* pipeline: segmentTree → buildVslDocument → cache/diff.
|
|
763
|
+
*/
|
|
764
|
+
snapshotFromElements(extractedElements, input) {
|
|
765
|
+
const elements = segmentTree(extractedElements);
|
|
766
|
+
return this.commit(elements, this.buildOptionsFromInput(input), input);
|
|
767
|
+
}
|
|
689
768
|
/**
|
|
690
769
|
* Vision-вариант конвейера (T1.5.5): segmentTree → enrichWithVision (Level 5
|
|
691
770
|
* fallback — аннотация t + vf/vf_meta на элементах ДО сборки) → buildVslDocument
|
|
@@ -699,6 +778,16 @@ var VslSnapshotSession = class {
|
|
|
699
778
|
const snapshot = this.commit(elements, this.buildOptions(root, input), input);
|
|
700
779
|
return { snapshot, fragments: visionResult.fragments };
|
|
701
780
|
}
|
|
781
|
+
/**
|
|
782
|
+
* Vision-вариант для pre-extracted elements (MCP сервер, Node.js контекст).
|
|
783
|
+
* Полный pipeline: segmentTree → enrichWithVision → buildVslDocument → cache/diff.
|
|
784
|
+
*/
|
|
785
|
+
async snapshotWithVisionFromElements(extractedElements, input, vision) {
|
|
786
|
+
const elements = segmentTree(extractedElements);
|
|
787
|
+
const visionResult = await enrichWithVision(elements, vision);
|
|
788
|
+
const snapshot = this.commit(elements, this.buildOptionsFromInput(input), input);
|
|
789
|
+
return { snapshot, fragments: visionResult.fragments };
|
|
790
|
+
}
|
|
702
791
|
/** BuildOptions из input + портативный title (логика бывшего snapshot()). */
|
|
703
792
|
buildOptions(root, input) {
|
|
704
793
|
const options = {
|
|
@@ -710,6 +799,20 @@ var VslSnapshotSession = class {
|
|
|
710
799
|
if (input.background !== void 0) options.background = input.background;
|
|
711
800
|
return options;
|
|
712
801
|
}
|
|
802
|
+
/**
|
|
803
|
+
* BuildOptions из input без DOM Element (для snapshotFromElements).
|
|
804
|
+
* Title берётся только из input (нет фолбэка на root.ownerDocument.title).
|
|
805
|
+
*/
|
|
806
|
+
buildOptionsFromInput(input) {
|
|
807
|
+
const options = {
|
|
808
|
+
viewport: { width: input.viewport.width, height: input.viewport.height },
|
|
809
|
+
url: input.url
|
|
810
|
+
};
|
|
811
|
+
if (input.title !== void 0) options.title = input.title;
|
|
812
|
+
if (input.timestamp !== void 0) options.timestamp = input.timestamp;
|
|
813
|
+
if (input.background !== void 0) options.background = input.background;
|
|
814
|
+
return options;
|
|
815
|
+
}
|
|
713
816
|
/** Сборка документа + кэш/дифф (логика бывшего snapshot(), см. шапку модуля). */
|
|
714
817
|
commit(elements, options, input) {
|
|
715
818
|
const nextDocument = buildVslDocument(elements, options);
|