@dooc-dev/dooc 0.0.0-stage → 0.0.2

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.
Files changed (221) hide show
  1. package/README.md +26 -2
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +311 -0
  4. package/dist/code.global.js +285 -0
  5. package/dist/compiler/bundle-urls.d.ts +3 -0
  6. package/dist/compiler/bundle-urls.js +294 -0
  7. package/dist/compiler/bundle.d.ts +2 -0
  8. package/dist/compiler/bundle.js +100 -0
  9. package/dist/compiler/check-prose.d.ts +11 -0
  10. package/dist/compiler/check-prose.js +138 -0
  11. package/dist/compiler/check-types.d.ts +44 -0
  12. package/dist/compiler/check-types.js +1 -0
  13. package/dist/compiler/check.d.ts +5 -0
  14. package/dist/compiler/check.js +450 -0
  15. package/dist/compiler/code-blocks.d.ts +17 -0
  16. package/dist/compiler/code-blocks.js +198 -0
  17. package/dist/compiler/code-languages.d.ts +10 -0
  18. package/dist/compiler/code-languages.js +109 -0
  19. package/dist/compiler/compile.d.ts +95 -0
  20. package/dist/compiler/compile.js +410 -0
  21. package/dist/compiler/config.d.ts +7 -0
  22. package/dist/compiler/config.js +52 -0
  23. package/dist/compiler/dialect.d.ts +24 -0
  24. package/dist/compiler/dialect.js +198 -0
  25. package/dist/compiler/drawio.d.ts +26 -0
  26. package/dist/compiler/drawio.js +176 -0
  27. package/dist/compiler/figures.d.ts +14 -0
  28. package/dist/compiler/figures.js +221 -0
  29. package/dist/compiler/file-cache.d.ts +14 -0
  30. package/dist/compiler/file-cache.js +61 -0
  31. package/dist/compiler/files.d.ts +29 -0
  32. package/dist/compiler/files.js +431 -0
  33. package/dist/compiler/fonts.d.ts +10 -0
  34. package/dist/compiler/fonts.js +54 -0
  35. package/dist/compiler/format.d.ts +1 -0
  36. package/dist/compiler/format.js +42 -0
  37. package/dist/compiler/from-mdast.d.ts +16 -0
  38. package/dist/compiler/from-mdast.js +142 -0
  39. package/dist/compiler/icons.d.ts +14 -0
  40. package/dist/compiler/icons.js +85 -0
  41. package/dist/compiler/language-codes.d.ts +7 -0
  42. package/dist/compiler/language-codes.js +17 -0
  43. package/dist/compiler/locales.d.ts +7 -0
  44. package/dist/compiler/locales.js +67 -0
  45. package/dist/compiler/manifest.d.ts +6 -0
  46. package/dist/compiler/manifest.js +30 -0
  47. package/dist/compiler/ops.d.ts +44 -0
  48. package/dist/compiler/ops.js +362 -0
  49. package/dist/compiler/public-file.d.ts +2 -0
  50. package/dist/compiler/public-file.js +93 -0
  51. package/dist/compiler/serialize.d.ts +3 -0
  52. package/dist/compiler/serialize.js +16 -0
  53. package/dist/compiler/terms.d.ts +9 -0
  54. package/dist/compiler/terms.js +44 -0
  55. package/dist/compiler/textfile-remote.d.ts +12 -0
  56. package/dist/compiler/textfile-remote.js +124 -0
  57. package/dist/compiler/textfile.d.ts +9 -0
  58. package/dist/compiler/textfile.js +113 -0
  59. package/dist/compiler/theme-variants.d.ts +4 -0
  60. package/dist/compiler/theme-variants.js +22 -0
  61. package/dist/compiler/zip.d.ts +6 -0
  62. package/dist/compiler/zip.js +48 -0
  63. package/dist/core/blocks.d.ts +99 -0
  64. package/dist/core/blocks.js +29 -0
  65. package/dist/core/code-file.d.ts +12 -0
  66. package/dist/core/code-file.js +68 -0
  67. package/dist/core/content-metadata.d.ts +48 -0
  68. package/dist/core/content-metadata.js +264 -0
  69. package/dist/core/content-types.d.ts +45 -0
  70. package/dist/core/content-types.js +1 -0
  71. package/dist/core/extension-package.d.ts +34 -0
  72. package/dist/core/extension-package.js +147 -0
  73. package/dist/core/figure-frame.d.ts +12 -0
  74. package/dist/core/figure-frame.js +108 -0
  75. package/dist/core/file-embed.d.ts +13 -0
  76. package/dist/core/file-embed.js +43 -0
  77. package/dist/core/files.d.ts +15 -0
  78. package/dist/core/files.js +59 -0
  79. package/dist/core/flow-base-css.generated.d.ts +1 -0
  80. package/dist/core/flow-base-css.generated.js +4 -0
  81. package/dist/core/flow-css.d.ts +9 -0
  82. package/dist/core/flow-css.js +54 -0
  83. package/dist/core/graph-common.d.ts +32 -0
  84. package/dist/core/graph-common.js +113 -0
  85. package/dist/core/graph.d.ts +117 -0
  86. package/dist/core/graph.js +480 -0
  87. package/dist/core/html.d.ts +29 -0
  88. package/dist/core/html.js +444 -0
  89. package/dist/core/icons.d.ts +2 -0
  90. package/dist/core/icons.js +2 -0
  91. package/dist/core/inline.d.ts +27 -0
  92. package/dist/core/inline.js +42 -0
  93. package/dist/core/language.d.ts +41 -0
  94. package/dist/core/language.js +44 -0
  95. package/dist/core/languages/ja.d.ts +2 -0
  96. package/dist/core/languages/ja.js +5 -0
  97. package/dist/core/markdown.d.ts +27 -0
  98. package/dist/core/markdown.js +154 -0
  99. package/dist/core/previewers.d.ts +37 -0
  100. package/dist/core/previewers.js +103 -0
  101. package/dist/core/routing.d.ts +20 -0
  102. package/dist/core/routing.js +64 -0
  103. package/dist/core/schema-comments.d.ts +14 -0
  104. package/dist/core/schema-comments.js +52 -0
  105. package/dist/core/schema-graph-flow.d.ts +9 -0
  106. package/dist/core/schema-graph-flow.js +379 -0
  107. package/dist/core/schema-graph-mount.d.ts +9 -0
  108. package/dist/core/schema-graph-mount.js +105 -0
  109. package/dist/core/schema-graph.d.ts +254 -0
  110. package/dist/core/schema-graph.js +981 -0
  111. package/dist/core/table-ui.d.ts +2 -0
  112. package/dist/core/table-ui.js +180 -0
  113. package/dist/core/taxonomy.d.ts +12 -0
  114. package/dist/core/taxonomy.js +49 -0
  115. package/dist/core/term-reference.d.ts +5 -0
  116. package/dist/core/term-reference.js +19 -0
  117. package/dist/core/terms-ui.d.ts +6 -0
  118. package/dist/core/terms-ui.js +22 -0
  119. package/dist/core/textfile.d.ts +10 -0
  120. package/dist/core/textfile.js +39 -0
  121. package/dist/core/theme-variants.d.ts +3 -0
  122. package/dist/core/theme-variants.js +37 -0
  123. package/dist/core/toc-ui.d.ts +2 -0
  124. package/dist/core/toc-ui.js +161 -0
  125. package/dist/core/video-ui.d.ts +2 -0
  126. package/dist/core/video-ui.js +253 -0
  127. package/dist/core/workspace.d.ts +15 -0
  128. package/dist/core/workspace.js +28 -0
  129. package/dist/edit.global.js +306 -0
  130. package/dist/flow.global.js +4959 -0
  131. package/dist/index.d.ts +17 -0
  132. package/dist/index.js +31 -0
  133. package/dist/mcp.d.ts +24 -0
  134. package/dist/mcp.js +467 -0
  135. package/dist/plugins/actions.d.ts +45 -0
  136. package/dist/plugins/actions.js +125 -0
  137. package/dist/plugins/blocks.d.ts +93 -0
  138. package/dist/plugins/blocks.js +100 -0
  139. package/dist/plugins/index.d.ts +4 -0
  140. package/dist/plugins/index.js +1 -0
  141. package/dist/plugins/local-storage.d.ts +18 -0
  142. package/dist/plugins/local-storage.js +115 -0
  143. package/dist/plugins/oauth.d.ts +14 -0
  144. package/dist/plugins/oauth.js +170 -0
  145. package/dist/plugins/runtime.d.ts +26 -0
  146. package/dist/plugins/runtime.js +395 -0
  147. package/dist/plugins/types.d.ts +59 -0
  148. package/dist/plugins/types.js +1 -0
  149. package/dist/plugins/view.d.ts +7 -0
  150. package/dist/plugins/view.js +21 -0
  151. package/dist/ui.global.js +78 -0
  152. package/dist/viewer/assets.d.ts +2 -0
  153. package/dist/viewer/assets.js +3 -0
  154. package/dist/viewer/build.d.ts +12 -0
  155. package/dist/viewer/build.js +55 -0
  156. package/dist/viewer/bundle-network.d.ts +2 -0
  157. package/dist/viewer/bundle-network.js +88 -0
  158. package/dist/viewer/code-file.d.ts +20 -0
  159. package/dist/viewer/code-file.js +42 -0
  160. package/dist/viewer/editor-tools.d.ts +38 -0
  161. package/dist/viewer/editor-tools.js +211 -0
  162. package/dist/viewer/extension-pack.d.ts +2 -0
  163. package/dist/viewer/extension-pack.js +36 -0
  164. package/dist/viewer/extensions.d.ts +10 -0
  165. package/dist/viewer/extensions.js +302 -0
  166. package/dist/viewer/file-references.d.ts +14 -0
  167. package/dist/viewer/file-references.js +38 -0
  168. package/dist/viewer/font-picker.d.ts +4 -0
  169. package/dist/viewer/font-picker.js +145 -0
  170. package/dist/viewer/font-settings.d.ts +11 -0
  171. package/dist/viewer/font-settings.js +50 -0
  172. package/dist/viewer/fonts/LICENSE.txt +119 -0
  173. package/dist/viewer/fonts/udev-gothic-regular.woff2 +0 -0
  174. package/dist/viewer/fonts.d.ts +2 -0
  175. package/dist/viewer/fonts.js +13 -0
  176. package/dist/viewer/git-diff.d.ts +3 -0
  177. package/dist/viewer/git-diff.js +33 -0
  178. package/dist/viewer/git-types.d.ts +73 -0
  179. package/dist/viewer/git-types.js +1 -0
  180. package/dist/viewer/git.d.ts +5 -0
  181. package/dist/viewer/git.js +337 -0
  182. package/dist/viewer/hmr.d.ts +53 -0
  183. package/dist/viewer/hmr.js +337 -0
  184. package/dist/viewer/i18n.d.ts +6 -0
  185. package/dist/viewer/i18n.js +65 -0
  186. package/dist/viewer/ja-lint.d.ts +3 -0
  187. package/dist/viewer/ja-lint.js +44 -0
  188. package/dist/viewer/language-picker.d.ts +2 -0
  189. package/dist/viewer/language-picker.js +233 -0
  190. package/dist/viewer/languages.d.ts +11 -0
  191. package/dist/viewer/languages.js +20 -0
  192. package/dist/viewer/locales/eng.json +317 -0
  193. package/dist/viewer/locales/jpn.json +317 -0
  194. package/dist/viewer/locales/zho.json +317 -0
  195. package/dist/viewer/nav-focus.d.ts +2 -0
  196. package/dist/viewer/nav-focus.js +64 -0
  197. package/dist/viewer/plugin-blocks.d.ts +3 -0
  198. package/dist/viewer/plugin-blocks.js +115 -0
  199. package/dist/viewer/plugin-config.d.ts +35 -0
  200. package/dist/viewer/plugin-config.js +57 -0
  201. package/dist/viewer/plugin-view.d.ts +2 -0
  202. package/dist/viewer/plugin-view.js +6 -0
  203. package/dist/viewer/plugins.d.ts +12 -0
  204. package/dist/viewer/plugins.js +267 -0
  205. package/dist/viewer/resize.d.ts +4 -0
  206. package/dist/viewer/resize.js +238 -0
  207. package/dist/viewer/resource-library.d.ts +29 -0
  208. package/dist/viewer/resource-library.js +104 -0
  209. package/dist/viewer/search.d.ts +16 -0
  210. package/dist/viewer/search.js +358 -0
  211. package/dist/viewer/serve.d.ts +210 -0
  212. package/dist/viewer/serve.js +3312 -0
  213. package/dist/viewer/site-icon.d.ts +8 -0
  214. package/dist/viewer/site-icon.js +56 -0
  215. package/dist/viewer/textfile.d.ts +9 -0
  216. package/dist/viewer/textfile.js +50 -0
  217. package/dist/viewer/theme-picker.d.ts +2 -0
  218. package/dist/viewer/theme-picker.js +135 -0
  219. package/dist/viewer/workspace.d.ts +4 -0
  220. package/dist/viewer/workspace.js +47 -0
  221. package/package.json +128 -5
@@ -0,0 +1,253 @@
1
+ /** Self-contained so playback controls also work in exported HTML. */
2
+ export function mountVideos(doc) {
3
+ const mobile = window.matchMedia("(max-width: 600px)");
4
+ const mounted = new WeakMap();
5
+ let nextSettingsId = 0;
6
+ let activeOptions;
7
+ const closeOptions = () => {
8
+ if (activeOptions?.matches(":popover-open"))
9
+ activeOptions.hidePopover();
10
+ };
11
+ const label = (key) => window.__docsTranslate?.(key) ??
12
+ key;
13
+ const name = (element, key) => {
14
+ element.dataset.i18nAriaLabel = key;
15
+ element.dataset.i18nTitle = key;
16
+ element.setAttribute("aria-label", label(key));
17
+ element.title = label(key);
18
+ };
19
+ const icon = (path) => `<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${path}</svg>`;
20
+ const playIcon = icon('<path d="m8 5 11 7-11 7Z"/>');
21
+ const pauseIcon = icon('<path d="M8 5v14M16 5v14"/>');
22
+ const soundIcon = icon('<path d="m11 5-6 4H2v6h3l6 4ZM15 8a6 6 0 0 1 0 8m3-11a10 10 0 0 1 0 14"/>');
23
+ const muteIcon = icon('<path d="m11 5-6 4H2v6h3l6 4Zm5 4 6 6m0-6-6 6"/>');
24
+ const clock = (value) => {
25
+ const seconds = Math.floor(Number.isFinite(value) ? Math.max(0, value) : 0);
26
+ const minutes = Math.floor(seconds / 60);
27
+ return `${minutes >= 60 ? `${Math.floor(minutes / 60)}:` : ""}${minutes >= 60 ? String(minutes % 60).padStart(2, "0") : minutes}:${String(seconds % 60).padStart(2, "0")}`;
28
+ };
29
+ const initialize = () => {
30
+ for (const video of doc.querySelectorAll("video[data-dooc-video]")) {
31
+ if (mounted.has(video) || video.closest("a"))
32
+ continue;
33
+ const player = doc.createElement("div");
34
+ player.className = "video-player";
35
+ video.before(player);
36
+ player.append(video);
37
+ const bar = doc.createElement("div");
38
+ bar.className = "video-controls";
39
+ const button = (key, markup) => {
40
+ const element = doc.createElement("button");
41
+ element.type = "button";
42
+ name(element, key);
43
+ element.innerHTML = markup;
44
+ return element;
45
+ };
46
+ const play = button("Play", playIcon);
47
+ const seek = doc.createElement("input");
48
+ seek.type = "range";
49
+ seek.min = "0";
50
+ seek.max = "0";
51
+ seek.step = "0.1";
52
+ seek.value = "0";
53
+ seek.className = "video-seek";
54
+ name(seek, "Seek");
55
+ const time = doc.createElement("span");
56
+ time.className = "video-time";
57
+ const mute = button("Mute", soundIcon);
58
+ const volume = doc.createElement("input");
59
+ volume.type = "range";
60
+ volume.min = "0";
61
+ volume.max = "1";
62
+ volume.step = "0.05";
63
+ volume.className = "video-volume";
64
+ name(volume, "Volume");
65
+ const settings = button("Video settings", icon('<path d="M4 7h2m6 0h8M4 17h8m6 0h2"/><circle cx="9" cy="7" r="3"/><circle cx="15" cy="17" r="3"/>'));
66
+ settings.setAttribute("aria-expanded", "false");
67
+ const options = doc.createElement("div");
68
+ options.className = "video-settings";
69
+ options.id = `video-settings-${++nextSettingsId}`;
70
+ options.popover = "auto";
71
+ options.setAttribute("role", "dialog");
72
+ name(options, "Video settings");
73
+ settings.setAttribute("aria-haspopup", "dialog");
74
+ settings.setAttribute("aria-controls", options.id);
75
+ const speedLabel = doc.createElement("label");
76
+ const speedText = doc.createElement("span");
77
+ speedText.dataset.i18n = "Playback speed";
78
+ speedText.textContent = label("Playback speed");
79
+ const speed = doc.createElement("input");
80
+ speed.type = "range";
81
+ speed.min = "1";
82
+ speed.max = "5";
83
+ speed.step = "0.25";
84
+ speed.className = "video-speed";
85
+ name(speed, "Playback speed");
86
+ const speedValue = doc.createElement("span");
87
+ speedValue.className = "video-speed-value";
88
+ speedLabel.append(speedText, speedValue, speed);
89
+ options.append(speedLabel);
90
+ const fullscreen = button("Fullscreen", icon('<path d="M9 3H3v6m12-6h6v6M3 15v6h6m12-6v6h-6"/>'));
91
+ fullscreen.hidden = !doc.fullscreenEnabled;
92
+ const status = doc.createElement("p");
93
+ status.className = "video-status";
94
+ status.setAttribute("role", "status");
95
+ status.hidden = true;
96
+ const fail = (key) => {
97
+ status.dataset.i18n = key;
98
+ status.textContent = label(key);
99
+ status.hidden = false;
100
+ };
101
+ const sync = () => {
102
+ const overlay = mobile.matches || !!doc.fullscreenElement?.contains(video);
103
+ video.controls = overlay;
104
+ bar.hidden = overlay;
105
+ if (overlay && options.matches(":popover-open")) {
106
+ options.hidePopover();
107
+ settings.setAttribute("aria-expanded", "false");
108
+ }
109
+ const paused = video.paused || video.ended;
110
+ name(play, paused ? "Play" : "Pause");
111
+ if (play.dataset.paused !== String(paused)) {
112
+ play.innerHTML = paused ? playIcon : pauseIcon;
113
+ play.dataset.paused = String(paused);
114
+ }
115
+ const duration = Number.isFinite(video.duration) ? video.duration : 0;
116
+ seek.disabled = duration <= 0 || !!video.error;
117
+ play.disabled = !!video.error;
118
+ seek.max = String(duration);
119
+ seek.value = String(video.currentTime);
120
+ seek.style.setProperty("--video-progress", `${duration > 0 ? Math.min(100, (video.currentTime / duration) * 100) : 0}%`);
121
+ seek.setAttribute("aria-valuetext", `${clock(video.currentTime)} / ${clock(duration)}`);
122
+ time.textContent = `${clock(video.currentTime)} / ${clock(duration)}`;
123
+ const silent = video.muted || video.volume === 0;
124
+ name(mute, silent ? "Unmute" : "Mute");
125
+ if (mute.dataset.muted !== String(silent)) {
126
+ mute.innerHTML = silent ? muteIcon : soundIcon;
127
+ mute.dataset.muted = String(silent);
128
+ }
129
+ volume.value = String(video.muted ? 0 : video.volume);
130
+ volume.style.setProperty("--video-progress", `${Number(volume.value) * 100}%`);
131
+ volume.setAttribute("aria-valuetext", `${Math.round(Number(volume.value) * 100)}%`);
132
+ speed.value = String(video.playbackRate);
133
+ speed.style.setProperty("--video-progress", `${((Number(speed.value) - 1) / 4) * 100}%`);
134
+ speed.setAttribute("aria-valuetext", `${video.playbackRate}×`);
135
+ speedValue.textContent = `${video.playbackRate}×`;
136
+ };
137
+ play.addEventListener("click", async () => {
138
+ if (!video.paused && !video.ended)
139
+ video.pause();
140
+ else {
141
+ status.hidden = true;
142
+ try {
143
+ await video.play();
144
+ }
145
+ catch {
146
+ fail("Video could not be played");
147
+ }
148
+ }
149
+ });
150
+ seek.addEventListener("input", () => {
151
+ video.currentTime = Number(seek.value);
152
+ sync();
153
+ });
154
+ mute.addEventListener("click", () => {
155
+ if (video.muted || video.volume === 0) {
156
+ video.muted = false;
157
+ if (video.volume === 0)
158
+ video.volume = 1;
159
+ }
160
+ else
161
+ video.muted = true;
162
+ sync();
163
+ });
164
+ volume.addEventListener("input", () => {
165
+ video.volume = Number(volume.value);
166
+ video.muted = video.volume === 0;
167
+ sync();
168
+ });
169
+ settings.addEventListener("click", () => {
170
+ if (options.matches(":popover-open")) {
171
+ options.hidePopover();
172
+ return;
173
+ }
174
+ options.showPopover();
175
+ activeOptions = options;
176
+ const rect = settings.getBoundingClientRect();
177
+ options.style.left = `${Math.max(8, Math.min(rect.right - options.offsetWidth, window.innerWidth - options.offsetWidth - 8))}px`;
178
+ options.style.top = `${Math.max(8, Math.min(rect.bottom + 6, window.innerHeight - options.offsetHeight - 8))}px`;
179
+ settings.setAttribute("aria-expanded", "true");
180
+ speed.focus({ preventScroll: true });
181
+ });
182
+ options.addEventListener("toggle", () => {
183
+ const open = options.matches(":popover-open");
184
+ settings.setAttribute("aria-expanded", String(open));
185
+ if (!open && activeOptions === options)
186
+ activeOptions = undefined;
187
+ });
188
+ options.addEventListener("keydown", (event) => {
189
+ if (event.key !== "Escape")
190
+ return;
191
+ event.preventDefault();
192
+ options.hidePopover();
193
+ settings.setAttribute("aria-expanded", "false");
194
+ settings.focus();
195
+ });
196
+ speed.addEventListener("input", () => {
197
+ video.playbackRate = Number(speed.value);
198
+ sync();
199
+ });
200
+ fullscreen.addEventListener("click", async () => {
201
+ video.controls = true;
202
+ try {
203
+ await video.requestFullscreen();
204
+ }
205
+ catch {
206
+ fail("Fullscreen is unavailable");
207
+ }
208
+ sync();
209
+ });
210
+ for (const type of [
211
+ "loadedmetadata",
212
+ "durationchange",
213
+ "timeupdate",
214
+ "play",
215
+ "pause",
216
+ "ended",
217
+ "volumechange",
218
+ "ratechange",
219
+ "emptied",
220
+ ])
221
+ video.addEventListener(type, sync);
222
+ video.addEventListener("error", () => {
223
+ fail("Video could not be played");
224
+ sync();
225
+ });
226
+ bar.append(play, seek, time, mute, volume, settings, fullscreen);
227
+ player.append(bar, options, status);
228
+ mounted.set(video, sync);
229
+ sync();
230
+ if (video.error)
231
+ fail("Video could not be played");
232
+ }
233
+ };
234
+ const syncAll = () => {
235
+ for (const video of doc.querySelectorAll("video[data-dooc-video]"))
236
+ mounted.get(video)?.();
237
+ };
238
+ mobile.addEventListener("change", syncAll);
239
+ window.addEventListener("resize", closeOptions);
240
+ doc.addEventListener("scroll", (event) => {
241
+ if (event.target instanceof Node && !activeOptions?.contains(event.target))
242
+ closeOptions();
243
+ }, true);
244
+ doc.addEventListener("fullscreenchange", syncAll);
245
+ doc.addEventListener("docs:ui-language", syncAll);
246
+ new MutationObserver((records) => {
247
+ if (records.some((record) => [...record.addedNodes].some((node) => node instanceof Element &&
248
+ (node.matches("video[data-dooc-video]") ||
249
+ node.querySelector("video[data-dooc-video]")))))
250
+ initialize();
251
+ }).observe(doc.documentElement, { childList: true, subtree: true });
252
+ initialize();
253
+ }
@@ -0,0 +1,15 @@
1
+ export interface GitWorkspace {
2
+ protocol: "git";
3
+ branch: string;
4
+ repo?: string;
5
+ }
6
+ export interface StorageWorkspace {
7
+ protocol: "storage";
8
+ folder: string;
9
+ service: string;
10
+ /** Service-owned SVG source, rendered as an image rather than inline markup. */
11
+ icon?: string;
12
+ }
13
+ export type WorkspaceSource = GitWorkspace | StorageWorkspace;
14
+ export declare const workspaceLabel: (workspace: WorkspaceSource) => string;
15
+ export declare const parseWorkspaceSource: (value: unknown) => WorkspaceSource;
@@ -0,0 +1,28 @@
1
+ export const workspaceLabel = (workspace) => workspace.protocol === "git" ? workspace.branch : `${workspace.folder} / ${workspace.service}`;
2
+ export const parseWorkspaceSource = (value) => {
3
+ if (!value || typeof value !== "object" || Array.isArray(value))
4
+ throw new Error("Workspace must be an object");
5
+ const source = value;
6
+ const text = (value) => typeof value === "string" &&
7
+ value.trim().length > 0 &&
8
+ [...value].every((char) => char.charCodeAt(0) >= 32 && char.charCodeAt(0) !== 127);
9
+ if (source.protocol === "git" &&
10
+ text(source.branch) &&
11
+ (source.repo === undefined || text(source.repo)))
12
+ return {
13
+ protocol: "git",
14
+ branch: source.branch,
15
+ ...(source.repo === undefined ? {} : { repo: source.repo }),
16
+ };
17
+ if (source.protocol === "storage" &&
18
+ text(source.folder) &&
19
+ text(source.service) &&
20
+ (source.icon === undefined || typeof source.icon === "string"))
21
+ return {
22
+ protocol: "storage",
23
+ folder: source.folder,
24
+ service: source.service,
25
+ ...(source.icon === undefined ? {} : { icon: source.icon }),
26
+ };
27
+ throw new Error("Workspace requires a Git branch or a storage folder and service");
28
+ };