@3rtools/tyts-mcp 0.1.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/README.md +103 -0
- package/dist/chrome.d.ts +3 -0
- package/dist/chrome.js +36 -0
- package/dist/chrome.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +23 -0
- package/dist/cli.js.map +1 -0
- package/dist/document.d.ts +76 -0
- package/dist/document.js +101 -0
- package/dist/document.js.map +1 -0
- package/dist/image.d.ts +16 -0
- package/dist/image.js +70 -0
- package/dist/image.js.map +1 -0
- package/dist/schemas.d.ts +490 -0
- package/dist/schemas.js +49 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +197 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +57 -0
- package/dist/session.js +186 -0
- package/dist/session.js.map +1 -0
- package/editor/appicon/Icon 1024.png +0 -0
- package/editor/appicon/Icon 128.png +0 -0
- package/editor/appicon/Icon 16.png +0 -0
- package/editor/appicon/Icon 256.png +0 -0
- package/editor/appicon/Icon 32.png +0 -0
- package/editor/appicon/Icon 512.png +0 -0
- package/editor/appicon/Icon 64.png +0 -0
- package/editor/assets/bootstrap-icons-BeopsB42.woff +0 -0
- package/editor/assets/bootstrap-icons-mSm7cUeB.woff2 +0 -0
- package/editor/assets/html2canvas.esm-DXEQVQnt.js +5 -0
- package/editor/assets/index-Bnr_82GS.js +236 -0
- package/editor/assets/index-DkXpHR6W.css +1 -0
- package/editor/assets/index.es-COZX40-D.js +5 -0
- package/editor/assets/purify.es-C0_7NiBM.js +2 -0
- package/editor/favicon/192.png +0 -0
- package/editor/favicon/512.png +0 -0
- package/editor/favicon/apple-touch-icon.png +0 -0
- package/editor/favicon/favicon.ico +0 -0
- package/editor/favicon/favicon.svg +12 -0
- package/editor/favicon/png/favicon-16x16.png +0 -0
- package/editor/favicon/png/favicon-32x32.png +0 -0
- package/editor/favicon/png/favicon-64x64.png +0 -0
- package/editor/fonts/road-ui/RoadUI-Bold.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Bold.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-BoldOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-BoldOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraBold.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraBold.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraBoldOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraBoldOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraLight.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraLight.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraLightOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-ExtraLightOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-Light.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Light.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-LightOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-LightOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-Medium.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Medium.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-MediumOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-MediumOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-Oblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Oblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-Regular.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Regular.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-SemiBold.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-SemiBold.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-SemiBoldOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-SemiBoldOblique.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-Thin.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-Thin.woff2 +0 -0
- package/editor/fonts/road-ui/RoadUI-ThinOblique.woff +0 -0
- package/editor/fonts/road-ui/RoadUI-ThinOblique.woff2 +0 -0
- package/editor/fonts/road-ui/road-ui.css +113 -0
- package/editor/images/crypto/btc.svg +31 -0
- package/editor/images/crypto/eth.svg +11 -0
- package/editor/images/crypto/trx.svg +11 -0
- package/editor/images/crypto/usdt.svg +8 -0
- package/editor/index.html +23 -0
- package/editor/tyts-embed.js +242 -0
- package/package.json +43 -0
- package/static/harness.html +45 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* Road UI — local web fonts (woff2 + woff) */
|
|
2
|
+
@font-face {
|
|
3
|
+
font-family: 'Road UI';
|
|
4
|
+
src: url('RoadUI-Thin.woff2') format('woff2'), url('RoadUI-Thin.woff') format('woff');
|
|
5
|
+
font-weight: 100;
|
|
6
|
+
font-style: normal;
|
|
7
|
+
font-display: swap;
|
|
8
|
+
}
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'Road UI';
|
|
11
|
+
src: url('RoadUI-ThinOblique.woff2') format('woff2'), url('RoadUI-ThinOblique.woff') format('woff');
|
|
12
|
+
font-weight: 100;
|
|
13
|
+
font-style: italic;
|
|
14
|
+
font-display: swap;
|
|
15
|
+
}
|
|
16
|
+
@font-face {
|
|
17
|
+
font-family: 'Road UI';
|
|
18
|
+
src: url('RoadUI-ExtraLight.woff2') format('woff2'), url('RoadUI-ExtraLight.woff') format('woff');
|
|
19
|
+
font-weight: 200;
|
|
20
|
+
font-style: normal;
|
|
21
|
+
font-display: swap;
|
|
22
|
+
}
|
|
23
|
+
@font-face {
|
|
24
|
+
font-family: 'Road UI';
|
|
25
|
+
src: url('RoadUI-ExtraLightOblique.woff2') format('woff2'), url('RoadUI-ExtraLightOblique.woff') format('woff');
|
|
26
|
+
font-weight: 200;
|
|
27
|
+
font-style: italic;
|
|
28
|
+
font-display: swap;
|
|
29
|
+
}
|
|
30
|
+
@font-face {
|
|
31
|
+
font-family: 'Road UI';
|
|
32
|
+
src: url('RoadUI-Light.woff2') format('woff2'), url('RoadUI-Light.woff') format('woff');
|
|
33
|
+
font-weight: 300;
|
|
34
|
+
font-style: normal;
|
|
35
|
+
font-display: swap;
|
|
36
|
+
}
|
|
37
|
+
@font-face {
|
|
38
|
+
font-family: 'Road UI';
|
|
39
|
+
src: url('RoadUI-LightOblique.woff2') format('woff2'), url('RoadUI-LightOblique.woff') format('woff');
|
|
40
|
+
font-weight: 300;
|
|
41
|
+
font-style: italic;
|
|
42
|
+
font-display: swap;
|
|
43
|
+
}
|
|
44
|
+
@font-face {
|
|
45
|
+
font-family: 'Road UI';
|
|
46
|
+
src: url('RoadUI-Regular.woff2') format('woff2'), url('RoadUI-Regular.woff') format('woff');
|
|
47
|
+
font-weight: 400;
|
|
48
|
+
font-style: normal;
|
|
49
|
+
font-display: swap;
|
|
50
|
+
}
|
|
51
|
+
@font-face {
|
|
52
|
+
font-family: 'Road UI';
|
|
53
|
+
src: url('RoadUI-Oblique.woff2') format('woff2'), url('RoadUI-Oblique.woff') format('woff');
|
|
54
|
+
font-weight: 400;
|
|
55
|
+
font-style: italic;
|
|
56
|
+
font-display: swap;
|
|
57
|
+
}
|
|
58
|
+
@font-face {
|
|
59
|
+
font-family: 'Road UI';
|
|
60
|
+
src: url('RoadUI-Medium.woff2') format('woff2'), url('RoadUI-Medium.woff') format('woff');
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
font-style: normal;
|
|
63
|
+
font-display: swap;
|
|
64
|
+
}
|
|
65
|
+
@font-face {
|
|
66
|
+
font-family: 'Road UI';
|
|
67
|
+
src: url('RoadUI-MediumOblique.woff2') format('woff2'), url('RoadUI-MediumOblique.woff') format('woff');
|
|
68
|
+
font-weight: 500;
|
|
69
|
+
font-style: italic;
|
|
70
|
+
font-display: swap;
|
|
71
|
+
}
|
|
72
|
+
@font-face {
|
|
73
|
+
font-family: 'Road UI';
|
|
74
|
+
src: url('RoadUI-SemiBold.woff2') format('woff2'), url('RoadUI-SemiBold.woff') format('woff');
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
font-style: normal;
|
|
77
|
+
font-display: swap;
|
|
78
|
+
}
|
|
79
|
+
@font-face {
|
|
80
|
+
font-family: 'Road UI';
|
|
81
|
+
src: url('RoadUI-SemiBoldOblique.woff2') format('woff2'), url('RoadUI-SemiBoldOblique.woff') format('woff');
|
|
82
|
+
font-weight: 600;
|
|
83
|
+
font-style: italic;
|
|
84
|
+
font-display: swap;
|
|
85
|
+
}
|
|
86
|
+
@font-face {
|
|
87
|
+
font-family: 'Road UI';
|
|
88
|
+
src: url('RoadUI-Bold.woff2') format('woff2'), url('RoadUI-Bold.woff') format('woff');
|
|
89
|
+
font-weight: 700;
|
|
90
|
+
font-style: normal;
|
|
91
|
+
font-display: swap;
|
|
92
|
+
}
|
|
93
|
+
@font-face {
|
|
94
|
+
font-family: 'Road UI';
|
|
95
|
+
src: url('RoadUI-BoldOblique.woff2') format('woff2'), url('RoadUI-BoldOblique.woff') format('woff');
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
font-style: italic;
|
|
98
|
+
font-display: swap;
|
|
99
|
+
}
|
|
100
|
+
@font-face {
|
|
101
|
+
font-family: 'Road UI';
|
|
102
|
+
src: url('RoadUI-ExtraBold.woff2') format('woff2'), url('RoadUI-ExtraBold.woff') format('woff');
|
|
103
|
+
font-weight: 800;
|
|
104
|
+
font-style: normal;
|
|
105
|
+
font-display: swap;
|
|
106
|
+
}
|
|
107
|
+
@font-face {
|
|
108
|
+
font-family: 'Road UI';
|
|
109
|
+
src: url('RoadUI-ExtraBoldOblique.woff2') format('woff2'), url('RoadUI-ExtraBoldOblique.woff') format('woff');
|
|
110
|
+
font-weight: 800;
|
|
111
|
+
font-style: italic;
|
|
112
|
+
font-display: swap;
|
|
113
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
|
|
5
|
+
<path fill="#F39321" d="M43.43,125.143c7.71-10.766,14.875-21.901,23.562-31.986c15.8-18.343,33.692-34.063,54.18-47.075
|
|
6
|
+
c18.379-11.672,37.761-20.872,58.501-27.305c32.294-10.018,65.26-12.997,98.838-9.165c24.544,2.801,48.191,9.067,70.713,19.215
|
|
7
|
+
c13.633,6.142,26.456,13.731,39.025,21.927c25.328,16.515,45.618,38.014,62.58,62.577c18.116,26.236,29.889,55.421,36.346,86.725
|
|
8
|
+
c4.535,21.983,6.449,44.171,4.503,66.504c-2.399,27.536-8.514,54.086-19.938,79.604c-9.662,21.583-21.589,41.401-36.861,59.301
|
|
9
|
+
c-14.94,17.511-31.788,32.831-51.149,45.461c-13.184,8.6-26.926,16.276-41.434,21.975c-24.274,9.537-49.447,15.986-75.787,17.115
|
|
10
|
+
c-18.545,0.795-36.985,0.483-55.279-2.763c-15.713-2.788-31.049-6.858-46.063-12.496c-14.566-5.47-28.693-11.95-41.709-20.143
|
|
11
|
+
c-18.766-11.812-35.683-26.147-50.737-42.663c-16.773-18.403-30.373-38.808-40.779-61.344
|
|
12
|
+
c-14.7-31.835-21.929-65.401-22.359-100.425c-0.162-13.173,1.349-26.244,3.105-39.283c0.126-0.933-0.002-1.899-0.012-2.851
|
|
13
|
+
c1.536-0.952,1.4-2.618,1.677-4.071c3.906-20.483,10.494-40.059,19.418-58.906C36.933,138.397,41.296,132.307,43.43,125.143z
|
|
14
|
+
M325.157,254.513c6.537-3.474,12.749-5.465,17.658-9.85c18.918-16.899,23.96-56.673-6.747-75.833
|
|
15
|
+
c-9.566-5.969-19.77-10.393-30.77-14.907c1.819-14.731,7.709-28.516,9.622-43.603c-9.076-2.249-17.578-5.234-26.425-6.193
|
|
16
|
+
c-3.617,14.177-7.085,27.769-10.674,41.837c-6.78-2.076-13.761-1.879-20.142-5.473c2.302-14.39,7.773-27.872,9.268-42.314
|
|
17
|
+
c-9.322-1.464-17.216-5.094-26.265-5.485c-3.563,14.209-7.011,27.958-10.586,42.215c-17.944-2.75-34.419-8.921-52.52-12.239
|
|
18
|
+
c-3.977,8.91-5.738,18.311-7.334,28.313c5.896,1.392,11.022,2.623,16.158,3.811c12.965,2.998,16.517,10.086,13.439,21.424
|
|
19
|
+
c-2.19,8.065-4.166,16.189-6.182,24.301c-7.245,29.16-14.432,58.333-21.72,87.482c-1.642,6.567-5.734,8.706-12.398,7.731
|
|
20
|
+
c-6.563-0.96-12.757-3.907-19.99-3.693c-3.136,10.032-9.378,18.871-11.588,29.946c17.236,4.391,33.911,8.639,51.344,13.08
|
|
21
|
+
c-1.312,15.208-7.614,29.125-9.476,44.441c8.739,2.095,16.965,4.066,25.544,6.123c5.653-14.044,6.957-28.803,12.226-43.33
|
|
22
|
+
c6.351,3.265,13.397,2.317,19.612,6.427c-3.387,14.003-6.762,27.952-10.178,42.077c8.986,3.216,17.753,4.528,26.758,6.77
|
|
23
|
+
c3.645-14.604,7.169-28.728,10.578-42.386c2.123-1.091,3.676-0.888,5.143-0.574c14.113,3.021,28.39,3.726,42.676,2.14
|
|
24
|
+
c12.368-1.373,23.343-6.088,32.148-15.372c9.791-10.323,14.71-22.952,17.078-36.535c1.93-11.065,1.436-22.277-5.06-32.071
|
|
25
|
+
C341.263,265.099,334.27,259.243,325.157,254.513z M223.128,312.17c17.411,4.325,34.803,8.95,53.02,5.624
|
|
26
|
+
c9.715-1.774,17.037-6.73,19.985-16.503c2.78-9.218,1.164-17.593-5.673-24.879c-7.11-7.576-16.254-11.514-25.682-14.807
|
|
27
|
+
c-11.264-3.934-22.683-7.508-34.99-8.48c-4.716,19.168-9.293,37.773-13.972,56.788C218.797,310.842,220.933,311.625,223.128,312.17z
|
|
28
|
+
M284.628,231.846c9.628-1.368,17.612-7.738,19.958-16.393c2.869-10.583-0.337-19.865-8.902-26.178
|
|
29
|
+
c-9.718-7.163-20.908-10.807-32.47-13.337c-4.307-0.943-8.544-3.454-13.756-1.759c-4.143,16.837-8.303,33.747-12.599,51.209
|
|
30
|
+
C253.316,229.543,268.47,234.141,284.628,231.846z"/>
|
|
31
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
|
|
5
|
+
<polygon fill="#2F3030" points="249.982,6.554 397.98,251.112 250.53,188.092 "/>
|
|
6
|
+
<polygon fill="#828384" points="102.39,251.112 249.982,6.554 250.53,188.092 "/>
|
|
7
|
+
<polygon fill="#343535" points="249.982,341.285 102.39,251.112 250.53,188.092 "/>
|
|
8
|
+
<polygon fill="#131313" points="397.98,251.112 250.53,188.092 249.982,341.285 "/>
|
|
9
|
+
<polygon fill="#2F3030" points="249.982,372.329 397.98,284.597 249.982,493.13 "/>
|
|
10
|
+
<polygon fill="#828384" points="249.982,372.329 102.39,284.597 249.982,493.13 "/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="trx" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
.st0{fill:#EB0029;}
|
|
7
|
+
</style>
|
|
8
|
+
<path class="st0" d="M389.2,70.2L13.2,1l197.9,498l275.8-336L389.2,70.2z M383.2,100.7l57.5,54.7l-157.3,28.5L383.2,100.7z
|
|
9
|
+
M249.2,178.2L83.4,40.6l271.1,49.9L249.2,178.2z M237.4,202.5l-27,223.6L64.5,59.1L237.4,202.5z M262.4,214.4l174.2-31.6
|
|
10
|
+
L236.8,426.3L262.4,214.4z"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
|
|
3
|
+
<path fill="#50AF95" fill-rule="evenodd" d="M281.6,245.8L281.6,245.8c-1.8,0.1-10.9,0.7-31.3,0.7c-16.2,0-27.7-0.5-31.7-0.7l0,0
|
|
4
|
+
c-62.6-2.8-109.4-13.7-109.4-26.7c0-13.1,46.7-23.9,109.4-26.7V235c4.1,0.3,15.8,1,32,1c19.4,0,29.2-0.8,30.9-1v-42.6
|
|
5
|
+
c62.5,2.8,109.1,13.7,109.1,26.7S344.1,243,281.6,245.8L281.6,245.8L281.6,245.8z M281.6,188v-38.1h87.2V91.8H131.4v58.1h87.2V188
|
|
6
|
+
c-70.9,3.3-124.2,17.3-124.2,34.1s53.3,30.8,124.2,34.1v122.1h63V256.2c70.7-3.3,123.9-17.3,123.9-34.1S352.4,191.3,281.6,188
|
|
7
|
+
L281.6,188L281.6,188z M281.6,188L281.6,188z"/>
|
|
8
|
+
</svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="uk">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Tyts Editor (Embed)</title>
|
|
7
|
+
<link rel="stylesheet" href="./fonts/road-ui/road-ui.css" />
|
|
8
|
+
<style>
|
|
9
|
+
html, body, #root {
|
|
10
|
+
margin: 0;
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
background: #0a0a10;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
<script type="module" crossorigin src="./assets/index-Bnr_82GS.js"></script>
|
|
18
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DkXpHR6W.css">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div id="root"></div>
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/* @3rtools/tyts-embed 0.1.0 — Host SDK для вбудовування редактора ТИЦЬ (Tyts) в iframe через postMessage */
|
|
2
|
+
(function () {
|
|
3
|
+
'use strict';
|
|
4
|
+
/**
|
|
5
|
+
* Tyts embed host SDK — load the editor in an iframe and control it via postMessage.
|
|
6
|
+
*
|
|
7
|
+
* Every request resolves when the editor answers (`tyts:initialized`, `tyts:done`,
|
|
8
|
+
* `tyts:document`, `tyts:exportResult`) or rejects with `{ code, message }`.
|
|
9
|
+
* Security (allowed origins, token) is configured when the editor bundle is built,
|
|
10
|
+
* not by the host page.
|
|
11
|
+
*
|
|
12
|
+
* This file is the single source: `build.mjs` emits it as ESM (`tyts-embed.mjs`)
|
|
13
|
+
* and as a classic script that sets `window.TytsEmbed` (`tyts-embed.js`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const editor = TytsEmbed.create({ container: '#host', src: '/tyts/embed/', onChange(doc, meta) { ... } });
|
|
17
|
+
* await editor.init({ token: 'secret' });
|
|
18
|
+
* await editor.loadImage(await TytsEmbed.fileToDataUrl(file));
|
|
19
|
+
* const png = await editor.export('png');
|
|
20
|
+
* await editor.markSaved();
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
var PROTOCOL = 1;
|
|
24
|
+
var VERSION = '0.1.0';
|
|
25
|
+
var DEFAULT_TIMEOUT_MS = 60000;
|
|
26
|
+
|
|
27
|
+
function createRequestId() {
|
|
28
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID();
|
|
29
|
+
return 'req-' + Date.now() + '-' + Math.random().toString(16).slice(2);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveOrigin(src) {
|
|
33
|
+
try {
|
|
34
|
+
return new URL(src, window.location.href).origin;
|
|
35
|
+
} catch {
|
|
36
|
+
return window.location.origin;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function TytsEmbedInstance(options) {
|
|
41
|
+
this._options = options;
|
|
42
|
+
this._iframe = null;
|
|
43
|
+
this._targetOrigin = '*';
|
|
44
|
+
this._ready = false;
|
|
45
|
+
this._initialized = false;
|
|
46
|
+
this._queuedUntilReady = [];
|
|
47
|
+
this._requests = new Map();
|
|
48
|
+
this._onChange = options.onChange || null;
|
|
49
|
+
this._onReady = options.onReady || null;
|
|
50
|
+
this._onError = options.onError || null;
|
|
51
|
+
this._messageHandler = this._handleMessage.bind(this);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
TytsEmbedInstance.prototype._handleMessage = function (event) {
|
|
55
|
+
if (!this._iframe || event.source !== this._iframe.contentWindow) return;
|
|
56
|
+
if (this._targetOrigin !== '*' && event.origin !== this._targetOrigin) return;
|
|
57
|
+
|
|
58
|
+
var data = event.data;
|
|
59
|
+
if (!data || typeof data.type !== 'string' || data.type.indexOf('tyts:') !== 0) return;
|
|
60
|
+
|
|
61
|
+
if (data.type === 'tyts:ready') {
|
|
62
|
+
if (this._ready) return;
|
|
63
|
+
this._ready = true;
|
|
64
|
+
var queued = this._queuedUntilReady;
|
|
65
|
+
this._queuedUntilReady = [];
|
|
66
|
+
for (var i = 0; i < queued.length; i++) this._post(queued[i]);
|
|
67
|
+
if (this._onReady) this._onReady();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (data.type === 'tyts:change') {
|
|
72
|
+
if (this._onChange) this._onChange(data.document, { dirty: !!data.dirty });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
var pending = data.requestId ? this._requests.get(data.requestId) : null;
|
|
77
|
+
|
|
78
|
+
if (data.type === 'tyts:error') {
|
|
79
|
+
var error = { code: data.error.code, message: data.error.message };
|
|
80
|
+
if (pending) {
|
|
81
|
+
this._requests.delete(data.requestId);
|
|
82
|
+
pending.reject(error);
|
|
83
|
+
} else if (this._onError) {
|
|
84
|
+
this._onError(error);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!pending) return;
|
|
90
|
+
this._requests.delete(data.requestId);
|
|
91
|
+
|
|
92
|
+
if (data.type === 'tyts:initialized') {
|
|
93
|
+
this._initialized = true;
|
|
94
|
+
pending.resolve();
|
|
95
|
+
} else if (data.type === 'tyts:done') {
|
|
96
|
+
pending.resolve();
|
|
97
|
+
} else if (data.type === 'tyts:document') {
|
|
98
|
+
pending.resolve(data.document);
|
|
99
|
+
} else if (data.type === 'tyts:exportResult') {
|
|
100
|
+
pending.resolve({ format: data.format, mime: data.mime, dataUrl: data.dataUrl });
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
TytsEmbedInstance.prototype._post = function (message) {
|
|
105
|
+
if (!this._iframe || !this._iframe.contentWindow) return;
|
|
106
|
+
this._iframe.contentWindow.postMessage(message, this._targetOrigin);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** Send a message with a fresh requestId and resolve on the matching reply. */
|
|
110
|
+
TytsEmbedInstance.prototype._request = function (message, timeoutMs) {
|
|
111
|
+
var self = this;
|
|
112
|
+
var requestId = createRequestId();
|
|
113
|
+
var payload = Object.assign({}, message, { requestId: requestId });
|
|
114
|
+
return new Promise(function (resolve, reject) {
|
|
115
|
+
var timer = setTimeout(function () {
|
|
116
|
+
self._requests.delete(requestId);
|
|
117
|
+
reject({ code: 'timeout', message: 'Request timed out: ' + message.type });
|
|
118
|
+
}, timeoutMs || DEFAULT_TIMEOUT_MS);
|
|
119
|
+
self._requests.set(requestId, {
|
|
120
|
+
resolve: function (value) {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
resolve(value);
|
|
123
|
+
},
|
|
124
|
+
reject: function (err) {
|
|
125
|
+
clearTimeout(timer);
|
|
126
|
+
reject(err);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
if (self._ready) self._post(payload);
|
|
130
|
+
else self._queuedUntilReady.push(payload);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
TytsEmbedInstance.prototype.mount = function () {
|
|
135
|
+
var container = this._options.container;
|
|
136
|
+
var el = typeof container === 'string' ? window.document.querySelector(container) : container;
|
|
137
|
+
if (!el) throw new Error('TytsEmbed: container not found');
|
|
138
|
+
|
|
139
|
+
var src = this._options.src || './';
|
|
140
|
+
this._targetOrigin = this._options.origin || resolveOrigin(src);
|
|
141
|
+
|
|
142
|
+
var iframe = window.document.createElement('iframe');
|
|
143
|
+
iframe.src = src;
|
|
144
|
+
iframe.title = this._options.title || 'Tyts Editor';
|
|
145
|
+
iframe.style.border = '0';
|
|
146
|
+
iframe.style.width = '100%';
|
|
147
|
+
iframe.style.height = '100%';
|
|
148
|
+
iframe.style.display = 'block';
|
|
149
|
+
iframe.setAttribute('allow', 'clipboard-read; clipboard-write');
|
|
150
|
+
el.innerHTML = '';
|
|
151
|
+
el.appendChild(iframe);
|
|
152
|
+
this._iframe = iframe;
|
|
153
|
+
|
|
154
|
+
window.addEventListener('message', this._messageHandler);
|
|
155
|
+
return this;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Open the session. Resolves once the editor confirms (`tyts:initialized`);
|
|
160
|
+
* the optional `document` is loaded before that.
|
|
161
|
+
* @param {{ token?: string, document?: object, timeoutMs?: number }} [config]
|
|
162
|
+
*/
|
|
163
|
+
TytsEmbedInstance.prototype.init = function (config) {
|
|
164
|
+
config = config || {};
|
|
165
|
+
return this._request({
|
|
166
|
+
type: 'tyts:init',
|
|
167
|
+
protocol: PROTOCOL,
|
|
168
|
+
token: config.token,
|
|
169
|
+
document: config.document,
|
|
170
|
+
}, config.timeoutMs);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
TytsEmbedInstance.prototype.loadDocument = function (document) {
|
|
174
|
+
return this._request({ type: 'tyts:loadDocument', document: document });
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
TytsEmbedInstance.prototype.loadImage = function (dataUrl) {
|
|
178
|
+
return this._request({ type: 'tyts:loadImage', dataUrl: dataUrl });
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
TytsEmbedInstance.prototype.getDocument = function () {
|
|
182
|
+
return this._request({ type: 'tyts:getDocument' }, 30000);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
TytsEmbedInstance.prototype.export = function (format, scale) {
|
|
186
|
+
return this._request({
|
|
187
|
+
type: 'tyts:export',
|
|
188
|
+
format: format || 'png',
|
|
189
|
+
scale: scale == null ? 1 : scale,
|
|
190
|
+
}, 120000);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/** Tell the editor the current state is persisted: the next `onChange` reports `dirty: false`. */
|
|
194
|
+
TytsEmbedInstance.prototype.markSaved = function () {
|
|
195
|
+
return this._request({ type: 'tyts:markSaved' });
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
TytsEmbedInstance.prototype.reset = function () {
|
|
199
|
+
return this._request({ type: 'tyts:reset' });
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
TytsEmbedInstance.prototype.destroy = function () {
|
|
203
|
+
window.removeEventListener('message', this._messageHandler);
|
|
204
|
+
this._requests.forEach(function (pending) {
|
|
205
|
+
pending.reject({ code: 'destroyed', message: 'Embed instance destroyed' });
|
|
206
|
+
});
|
|
207
|
+
this._requests.clear();
|
|
208
|
+
this._queuedUntilReady = [];
|
|
209
|
+
if (this._iframe && this._iframe.parentNode) {
|
|
210
|
+
this._iframe.parentNode.removeChild(this._iframe);
|
|
211
|
+
}
|
|
212
|
+
this._iframe = null;
|
|
213
|
+
this._ready = false;
|
|
214
|
+
this._initialized = false;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
function create(options) {
|
|
218
|
+
var instance = new TytsEmbedInstance(options || {});
|
|
219
|
+
return instance.mount();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function fileToDataUrl(file) {
|
|
223
|
+
return new Promise(function (resolve, reject) {
|
|
224
|
+
var reader = new FileReader();
|
|
225
|
+
reader.onload = function () {
|
|
226
|
+
resolve(typeof reader.result === 'string' ? reader.result : '');
|
|
227
|
+
};
|
|
228
|
+
reader.onerror = function () { reject(new Error('Failed to read file')); };
|
|
229
|
+
reader.readAsDataURL(file);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
var TytsEmbed = {
|
|
234
|
+
create: create,
|
|
235
|
+
fileToDataUrl: fileToDataUrl,
|
|
236
|
+
PROTOCOL: PROTOCOL,
|
|
237
|
+
VERSION: VERSION,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
window.TytsEmbed = TytsEmbed;
|
|
242
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@3rtools/tyts-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP-сервер редактора ТИЦЬ (Tyts): агент дає картинку й анотації, отримує готовий PNG/JPEG/PDF",
|
|
5
|
+
"keywords": ["tyts", "mcp", "model-context-protocol", "annotation", "collage", "agent"],
|
|
6
|
+
"homepage": "https://github.com/alexkolodko/tyts#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/alexkolodko/tyts.git",
|
|
10
|
+
"directory": "packages/mcp"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"bin": {
|
|
14
|
+
"tyts-mcp": "./dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"main": "./dist/server.js",
|
|
17
|
+
"types": "./dist/server.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/server.d.ts",
|
|
21
|
+
"import": "./dist/server.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": ["dist", "static", "editor", "README.md"],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json",
|
|
28
|
+
"sync-editor": "node scripts/sync-editor.mjs",
|
|
29
|
+
"prepack": "npm run build && npm run sync-editor",
|
|
30
|
+
"start": "node dist/cli.js"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
34
|
+
"puppeteer-core": "^25.10.0",
|
|
35
|
+
"zod": "^4.5.4"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="uk">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>Tyts MCP harness</title>
|
|
6
|
+
<style>
|
|
7
|
+
html, body { margin: 0; background: #0a0a10; }
|
|
8
|
+
/* Розмір контейнера впливає лише на UI редактора; рендер експорту йде від imageSize. */
|
|
9
|
+
#host { width: 1200px; height: 800px; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="host"></div>
|
|
14
|
+
<script src="./tyts-embed.js"></script>
|
|
15
|
+
<script>
|
|
16
|
+
// Міст для MCP-сервера: усі виклики повертають { ok, value } або { ok:false, error },
|
|
17
|
+
// бо puppeteer не переносить обʼєкти з rejected-промісів.
|
|
18
|
+
const editor = TytsEmbed.create({ container: '#host', src: './index.html', origin: location.origin });
|
|
19
|
+
const wrap = (fn) => async (...args) => {
|
|
20
|
+
try { return { ok: true, value: await fn(...args) }; }
|
|
21
|
+
catch (e) { return { ok: false, error: e && e.code ? { code: e.code, message: e.message } : { code: 'harness_error', message: String(e && e.message || e) } }; }
|
|
22
|
+
};
|
|
23
|
+
const decode = (dataUrl) => new Promise((resolve, reject) => {
|
|
24
|
+
const img = new Image();
|
|
25
|
+
img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });
|
|
26
|
+
img.onerror = () => reject(new Error('Image decode failed'));
|
|
27
|
+
img.src = dataUrl;
|
|
28
|
+
});
|
|
29
|
+
window.__tyts = {
|
|
30
|
+
ready: wrap(() => editor.init())(),
|
|
31
|
+
loadImage: wrap((dataUrl) => editor.loadImage(dataUrl)),
|
|
32
|
+
loadDocument: wrap((doc) => editor.loadDocument(doc)),
|
|
33
|
+
getDocument: wrap(() => editor.getDocument()),
|
|
34
|
+
export: wrap(async (format, scale) => {
|
|
35
|
+
const result = await editor.export(format, scale);
|
|
36
|
+
const size = format === 'pdf' ? null : await decode(result.dataUrl);
|
|
37
|
+
return { dataUrl: result.dataUrl, mime: result.mime, width: size && size.width, height: size && size.height };
|
|
38
|
+
}),
|
|
39
|
+
reset: wrap(() => editor.reset()),
|
|
40
|
+
imageInfo: wrap(decode),
|
|
41
|
+
protocol: TytsEmbed.PROTOCOL,
|
|
42
|
+
};
|
|
43
|
+
</script>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|