@thoughtspot/visual-embed-sdk 1.49.1 → 1.49.3

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 (151) hide show
  1. package/cjs/package.json +4 -10
  2. package/cjs/src/css-variables.d.ts +17 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +7 -1
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +4 -1
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +97 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/conversation.d.ts +8 -0
  11. package/cjs/src/embed/conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/conversation.js +2 -1
  13. package/cjs/src/embed/conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.spec.js +12 -0
  15. package/cjs/src/embed/conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/events.spec.js +5 -0
  17. package/cjs/src/embed/events.spec.js.map +1 -1
  18. package/cjs/src/embed/liveboard.d.ts +6 -0
  19. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  20. package/cjs/src/embed/liveboard.js +4 -1
  21. package/cjs/src/embed/liveboard.js.map +1 -1
  22. package/cjs/src/embed/liveboard.spec.js +11 -0
  23. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  24. package/cjs/src/embed/spotter-viz-utils.d.ts +29 -0
  25. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
  26. package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
  27. package/cjs/src/embed/ts-embed.d.ts +38 -0
  28. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  29. package/cjs/src/embed/ts-embed.js +166 -9
  30. package/cjs/src/embed/ts-embed.js.map +1 -1
  31. package/cjs/src/embed/ts-embed.spec.js +237 -0
  32. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  33. package/cjs/src/index.d.ts +2 -2
  34. package/cjs/src/index.d.ts.map +1 -1
  35. package/cjs/src/index.js.map +1 -1
  36. package/cjs/src/types.d.ts +87 -4
  37. package/cjs/src/types.d.ts.map +1 -1
  38. package/cjs/src/types.js +47 -3
  39. package/cjs/src/types.js.map +1 -1
  40. package/cjs/src/utils/graphql/answerService/answerService.spec.js +15 -0
  41. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  42. package/cjs/src/utils/processTrigger.d.ts.map +1 -1
  43. package/cjs/src/utils/processTrigger.js +6 -5
  44. package/cjs/src/utils/processTrigger.js.map +1 -1
  45. package/cjs/src/utils/processTrigger.spec.js +13 -0
  46. package/cjs/src/utils/processTrigger.spec.js.map +1 -1
  47. package/cjs/src/utils.d.ts +10 -0
  48. package/cjs/src/utils.d.ts.map +1 -1
  49. package/cjs/src/utils.js +25 -4
  50. package/cjs/src/utils.js.map +1 -1
  51. package/cjs/src/utils.spec.js +48 -0
  52. package/cjs/src/utils.spec.js.map +1 -1
  53. package/dist/{index-B6Rn561t.js → index-DsSQndIB.js} +303 -187
  54. package/dist/src/css-variables.d.ts +17 -0
  55. package/dist/src/css-variables.d.ts.map +1 -1
  56. package/dist/src/embed/app.d.ts +7 -1
  57. package/dist/src/embed/app.d.ts.map +1 -1
  58. package/dist/src/embed/conversation.d.ts +8 -0
  59. package/dist/src/embed/conversation.d.ts.map +1 -1
  60. package/dist/src/embed/liveboard.d.ts +6 -0
  61. package/dist/src/embed/liveboard.d.ts.map +1 -1
  62. package/dist/src/embed/spotter-viz-utils.d.ts +29 -0
  63. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
  64. package/dist/src/embed/ts-embed.d.ts +38 -0
  65. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  66. package/dist/src/index.d.ts +2 -2
  67. package/dist/src/index.d.ts.map +1 -1
  68. package/dist/src/types.d.ts +87 -4
  69. package/dist/src/types.d.ts.map +1 -1
  70. package/dist/src/utils/processTrigger.d.ts.map +1 -1
  71. package/dist/src/utils.d.ts +10 -0
  72. package/dist/src/utils.d.ts.map +1 -1
  73. package/dist/tsembed-react.es.js +282 -35
  74. package/dist/tsembed-react.js +583 -220
  75. package/dist/tsembed.es.js +282 -35
  76. package/dist/tsembed.js +583 -220
  77. package/dist/visual-embed-sdk-react-full.d.ts +190 -4
  78. package/dist/visual-embed-sdk-react.d.ts +190 -4
  79. package/dist/visual-embed-sdk.d.ts +190 -4
  80. package/lib/package.json +4 -10
  81. package/lib/src/css-variables.d.ts +17 -0
  82. package/lib/src/css-variables.d.ts.map +1 -1
  83. package/lib/src/embed/app.d.ts +7 -1
  84. package/lib/src/embed/app.d.ts.map +1 -1
  85. package/lib/src/embed/app.js +4 -1
  86. package/lib/src/embed/app.js.map +1 -1
  87. package/lib/src/embed/app.spec.js +97 -0
  88. package/lib/src/embed/app.spec.js.map +1 -1
  89. package/lib/src/embed/conversation.d.ts +8 -0
  90. package/lib/src/embed/conversation.d.ts.map +1 -1
  91. package/lib/src/embed/conversation.js +2 -1
  92. package/lib/src/embed/conversation.js.map +1 -1
  93. package/lib/src/embed/conversation.spec.js +12 -0
  94. package/lib/src/embed/conversation.spec.js.map +1 -1
  95. package/lib/src/embed/events.spec.js +5 -0
  96. package/lib/src/embed/events.spec.js.map +1 -1
  97. package/lib/src/embed/liveboard.d.ts +6 -0
  98. package/lib/src/embed/liveboard.d.ts.map +1 -1
  99. package/lib/src/embed/liveboard.js +4 -1
  100. package/lib/src/embed/liveboard.js.map +1 -1
  101. package/lib/src/embed/liveboard.spec.js +11 -0
  102. package/lib/src/embed/liveboard.spec.js.map +1 -1
  103. package/lib/src/embed/spotter-viz-utils.d.ts +29 -0
  104. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
  105. package/lib/src/embed/spotter-viz-utils.js.map +1 -1
  106. package/lib/src/embed/ts-embed.d.ts +38 -0
  107. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  108. package/lib/src/embed/ts-embed.js +167 -10
  109. package/lib/src/embed/ts-embed.js.map +1 -1
  110. package/lib/src/embed/ts-embed.spec.js +237 -0
  111. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  112. package/lib/src/index.d.ts +2 -2
  113. package/lib/src/index.d.ts.map +1 -1
  114. package/lib/src/index.js.map +1 -1
  115. package/lib/src/types.d.ts +87 -4
  116. package/lib/src/types.d.ts.map +1 -1
  117. package/lib/src/types.js +47 -3
  118. package/lib/src/types.js.map +1 -1
  119. package/lib/src/utils/graphql/answerService/answerService.spec.js +15 -0
  120. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  121. package/lib/src/utils/processTrigger.d.ts.map +1 -1
  122. package/lib/src/utils/processTrigger.js +6 -5
  123. package/lib/src/utils/processTrigger.js.map +1 -1
  124. package/lib/src/utils/processTrigger.spec.js +13 -0
  125. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  126. package/lib/src/utils.d.ts +10 -0
  127. package/lib/src/utils.d.ts.map +1 -1
  128. package/lib/src/utils.js +22 -1
  129. package/lib/src/utils.js.map +1 -1
  130. package/lib/src/utils.spec.js +49 -1
  131. package/lib/src/utils.spec.js.map +1 -1
  132. package/lib/src/visual-embed-sdk.d.ts +190 -4
  133. package/package.json +4 -10
  134. package/src/css-variables.ts +20 -0
  135. package/src/embed/app.spec.ts +109 -0
  136. package/src/embed/app.ts +11 -1
  137. package/src/embed/conversation.spec.ts +17 -0
  138. package/src/embed/conversation.ts +10 -0
  139. package/src/embed/events.spec.ts +7 -0
  140. package/src/embed/liveboard.spec.ts +15 -0
  141. package/src/embed/liveboard.ts +10 -0
  142. package/src/embed/spotter-viz-utils.ts +30 -0
  143. package/src/embed/ts-embed.spec.ts +294 -0
  144. package/src/embed/ts-embed.ts +180 -9
  145. package/src/index.ts +2 -1
  146. package/src/types.ts +86 -3
  147. package/src/utils/graphql/answerService/answerService.spec.ts +18 -0
  148. package/src/utils/processTrigger.spec.ts +23 -0
  149. package/src/utils/processTrigger.ts +8 -6
  150. package/src/utils.spec.ts +63 -0
  151. package/src/utils.ts +25 -1
@@ -1,4 +1,4 @@
1
- /* @thoughtspot/visual-embed-sdk version 1.49.1 */
1
+ /* @thoughtspot/visual-embed-sdk version 1.49.3 */
2
2
  'use client';
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
@@ -163,28 +163,45 @@
163
163
  }
164
164
  return false;
165
165
  };
166
- const merge = (...objects) => objects.reduce((result, current) => {
166
+ const UNSAFE_KEYS = new Set([
167
+ "__proto__",
168
+ "constructor",
169
+ "prototype",
170
+ "toString",
171
+ "valueOf",
172
+ "hasOwnProperty",
173
+ "isPrototypeOf",
174
+ "propertyIsEnumerable",
175
+ "toLocaleString",
176
+ ]);
177
+ const merge$1 = (...objects) => objects.reduce((result, current) => {
178
+ if (current === undefined) {
179
+ return result;
180
+ }
167
181
  if (Array.isArray(current)) {
168
182
  throw new TypeError("Arguments provided to ts-deepmerge must be objects, not arrays.");
169
183
  }
170
184
  Object.keys(current).forEach((key) => {
171
- if (["__proto__", "constructor", "prototype"].includes(key)) {
185
+ if (UNSAFE_KEYS.has(key)) {
172
186
  return;
173
187
  }
174
188
  if (Array.isArray(result[key]) && Array.isArray(current[key])) {
175
- result[key] = merge.options.mergeArrays
176
- ? merge.options.uniqueArrayItems
189
+ result[key] = merge$1.options.mergeArrays
190
+ ? merge$1.options.uniqueArrayItems
177
191
  ? Array.from(new Set(result[key].concat(current[key])))
178
192
  : [...result[key], ...current[key]]
179
193
  : current[key];
180
194
  }
181
195
  else if (isObject$1(result[key]) && isObject$1(current[key])) {
182
- result[key] = merge(result[key], current[key]);
196
+ result[key] = merge$1(result[key], current[key]);
197
+ }
198
+ else if (!isObject$1(result[key]) && isObject$1(current[key])) {
199
+ result[key] = merge$1(current[key], undefined);
183
200
  }
184
201
  else {
185
202
  result[key] =
186
203
  current[key] === undefined
187
- ? merge.options.allowUndefinedOverrides
204
+ ? merge$1.options.allowUndefinedOverrides
188
205
  ? current[key]
189
206
  : result[key]
190
207
  : current[key];
@@ -197,11 +214,11 @@
197
214
  mergeArrays: true,
198
215
  uniqueArrayItems: true,
199
216
  };
200
- merge.options = defaultOptions;
201
- merge.withOptions = (options, ...objects) => {
202
- merge.options = Object.assign(Object.assign({}, defaultOptions), options);
203
- const result = merge(...objects);
204
- merge.options = defaultOptions;
217
+ merge$1.options = defaultOptions;
218
+ merge$1.withOptions = (options, ...objects) => {
219
+ merge$1.options = Object.assign(Object.assign({}, defaultOptions), options);
220
+ const result = merge$1(...objects);
221
+ merge$1.options = defaultOptions;
205
222
  return result;
206
223
  };
207
224
 
@@ -2433,11 +2450,30 @@
2433
2450
  /**
2434
2451
  * Navigate to a specific page in the embedded ThoughtSpot application.
2435
2452
  * This is the same as calling `appEmbed.navigateToPage(path, true)`.
2436
- * @param - `path` - the path to navigate to go forward or back. The path value can
2437
- * be a number; for example, `1`, `-1`.
2453
+ *
2454
+ * Accepts either a plain value or an object with `path`
2455
+ * and an optional `replace` flag.
2456
+ *
2457
+ * @param data - A string path, a numeric history delta, or an object
2458
+ * `{ path: string | number, replace?: boolean }`.
2459
+ * - `path` — the route to navigate to, or a history delta such as `1`
2460
+ * or `-1` (calls `window.history.go()`).
2461
+ * - `replace` — when `true`, replaces the current history entry instead
2462
+ * of pushing a new one (uses `window.location.replace`).
2463
+ *
2438
2464
  * @example
2439
2465
  * ```js
2440
- * appEmbed.navigateToPage(-1)
2466
+ * // Preferred: use navigateToPage directly
2467
+ * appEmbed.navigateToPage(-1);
2468
+ *
2469
+ * // Numeric delta — go back one step
2470
+ * appEmbed.trigger(HostEvent.Navigate, -1);
2471
+ *
2472
+ * // String path — push a new history entry
2473
+ * appEmbed.trigger(HostEvent.Navigate, 'home');
2474
+ *
2475
+ * // Object format — replace current history entry
2476
+ * appEmbed.trigger(HostEvent.Navigate, { path: 'home', replace: true }); // SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
2441
2477
  * ```
2442
2478
  * @version SDK: 1.12.0 | ThoughtSpot: 8.4.0.cl, 8.4.1.sw
2443
2479
  */
@@ -4426,6 +4462,7 @@
4426
4462
  Param["EnableLiveboardDataCache"] = "enableLiveboardDataCache";
4427
4463
  Param["SpotterFileUploadEnabled"] = "spotterFileUploadEnabled";
4428
4464
  Param["SpotterFileUploadFileTypes"] = "spotterFileUploadFileTypes";
4465
+ Param["IsStarterPromptsEnabled"] = "enableStarterPrompts";
4429
4466
  })(Param || (Param = {}));
4430
4467
  /**
4431
4468
  * ThoughtSpot application pages include actions and menu commands
@@ -5068,6 +5105,16 @@
5068
5105
  * @version SDK: 1.9.0 | ThoughtSpot: 8.1.0.cl, 8.4.1.sw
5069
5106
  */
5070
5107
  Action["AddToFavorites"] = "addToFavorites";
5108
+ /**
5109
+ * Remove from Favorites option in home page v3 sidebar.
5110
+ * Allows removing an object from the user's favorites list from home-page v3 sidebar.
5111
+ * @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
5112
+ * @example
5113
+ * ```js
5114
+ * disabledActions: [Action.RemoveFromFavorites]
5115
+ * ```
5116
+ */
5117
+ Action["RemoveFromFavorites"] = "removeFromFavorites";
5071
5118
  /**
5072
5119
  * The edit icon on Liveboards (Classic experience).
5073
5120
  * @example
@@ -6125,6 +6172,20 @@
6125
6172
  * ```
6126
6173
  */
6127
6174
  Action["SpotterViz"] = "spotterViz";
6175
+ /**
6176
+ * The reference-mode toggle button inside the SpotterViz chat input.
6177
+ * When users enable reference mode, clicking tiles, filters, or
6178
+ * parameters adds them as chat context. Hide this action to remove
6179
+ * the reference-mode capability entirely.
6180
+ * Visible by default.
6181
+ * @version SDK: 1.51.0 | ThoughtSpot Cloud: 26.8.0.cl
6182
+ * @example
6183
+ * ```js
6184
+ * hiddenActions: [Action.SpotterVizReferenceMode]
6185
+ * disabledActions: [Action.SpotterVizReferenceMode]
6186
+ * ```
6187
+ */
6188
+ Action["SpotterVizReferenceMode"] = "spotterVizReferenceMode";
6128
6189
  /**
6129
6190
  * Clears browser cache and fetches new data for liveboard ChartViz Containers.
6130
6191
  * Requires `enableLiveboardDataCache` to be enabled.
@@ -6601,7 +6662,7 @@
6601
6662
  TableContentDensity["Compact"] = "COMPACT";
6602
6663
  })(TableContentDensity || (TableContentDensity = {}));
6603
6664
 
6604
- var version$1="1.49.1";var pkg = {version:version$1};
6665
+ var version$1="1.49.3";var pkg = {version:version$1};
6605
6666
 
6606
6667
  const { version } = pkg;
6607
6668
 
@@ -6948,7 +7009,28 @@
6948
7009
  function getDOMNode(domSelector) {
6949
7010
  return typeof domSelector === 'string' ? document.querySelector(domSelector) : domSelector;
6950
7011
  }
6951
- const deepMerge = (target, source) => merge(target, source);
7012
+ /**
7013
+ * Resolves a CSS selector to an element. `document.querySelector` cannot pierce
7014
+ * shadow boundaries, so when the document lookup misses and a reference node is
7015
+ * provided, this also searches the shadow root the reference node lives in —
7016
+ * letting a selector target an element inside the same shadow root as the embed
7017
+ * instead of silently falling back to the light DOM.
7018
+ * @param selector CSS selector string.
7019
+ * @param referenceNode Node whose shadow root is searched when the document lookup misses.
7020
+ */
7021
+ function querySelectorAcrossShadowRoot(selector, referenceNode) {
7022
+ var _a;
7023
+ const fromDocument = document.querySelector(selector);
7024
+ if (fromDocument) {
7025
+ return fromDocument;
7026
+ }
7027
+ const rootNode = (_a = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.getRootNode) === null || _a === void 0 ? void 0 : _a.call(referenceNode);
7028
+ if (typeof ShadowRoot !== 'undefined' && rootNode instanceof ShadowRoot) {
7029
+ return rootNode.querySelector(selector);
7030
+ }
7031
+ return null;
7032
+ }
7033
+ const deepMerge = (target, source) => merge$1(target, source);
6952
7034
  const getOperationNameFromQuery = (query) => {
6953
7035
  const regex = /(?:query|mutation)\s+(\w+)/;
6954
7036
  const matches = query.match(regex);
@@ -19461,8 +19543,14 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
19461
19543
  }
19462
19544
  }
19463
19545
  const channel = new MessageChannel();
19546
+ // Close the messageChannel and resolve the promise if timeout.
19547
+ const timeoutId = setTimeout(() => {
19548
+ channel.port1.close();
19549
+ res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
19550
+ }, TRIGGER_TIMEOUT);
19464
19551
  channel.port1.onmessage = ({ data: responseData }) => {
19465
19552
  var _a;
19553
+ clearTimeout(timeoutId);
19466
19554
  channel.port1.close();
19467
19555
  const error = (responseData === null || responseData === void 0 ? void 0 : responseData.error) || ((_a = responseData === null || responseData === void 0 ? void 0 : responseData.data) === null || _a === void 0 ? void 0 : _a.error);
19468
19556
  if (error) {
@@ -19472,11 +19560,6 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
19472
19560
  res(responseData);
19473
19561
  }
19474
19562
  };
19475
- // Close the messageChannel and resolve the promise if timeout.
19476
- setTimeout(() => {
19477
- channel.port1.close();
19478
- res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
19479
- }, TRIGGER_TIMEOUT);
19480
19563
  return postIframeMessage(iFrame, { type: messageType, data, context }, thoughtSpotHost, channel);
19481
19564
  });
19482
19565
  }
@@ -20241,6 +20324,14 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
20241
20324
  */
20242
20325
  const THOUGHTSPOT_PARAM_PREFIX = 'ts-';
20243
20326
  const TS_EMBED_ID = '_thoughtspot-embed';
20327
+ /**
20328
+ * dataset key used to stash a custom preRenderContainer's original inline
20329
+ * `position` while we override it to `relative`. Stored on the container (not
20330
+ * per-instance) so the override can be reverted on destroy even when multiple
20331
+ * pre-rendered embeds share the same container.
20332
+ */
20333
+ const PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY = 'tsEmbedOriginalPosition';
20334
+ const PRERENDER_WRAPPER_ID_PREFIX = 'tsEmbed-pre-render-wrapper-';
20244
20335
  /**
20245
20336
  * The event id map from v2 event names to v1 event id
20246
20337
  * v1 events are the classic embed events implemented in Blink v1
@@ -20276,6 +20367,8 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
20276
20367
  */
20277
20368
  this.shouldEncodeUrlQueryParams = false;
20278
20369
  this.defaultHiddenActions = [exports.Action.ReportError];
20370
+ this.preRenderContainerEl = null;
20371
+ this.containerScrollListener = null;
20279
20372
  /**
20280
20373
  * Handler for fullscreen change events
20281
20374
  */
@@ -21141,6 +21234,89 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21141
21234
  placeholder.id = id.placeHolder;
21142
21235
  return placeholder;
21143
21236
  }
21237
+ /**
21238
+ * Resolves the configured preRenderContainer to a live element, falling
21239
+ * back to `document.body`. A string selector is re-queried on every call so
21240
+ * a remounted container (E.g.: React replacing the node) resolves to the
21241
+ * fresh element; an element passed directly cannot be re-resolved.
21242
+ */
21243
+ resolvePreRenderContainerTarget() {
21244
+ var _a;
21245
+ const containerConfig = this.viewConfig.preRenderContainer;
21246
+ let container = null;
21247
+ if (typeof containerConfig === 'string') {
21248
+ try {
21249
+ // Resolve against the host's shadow root too, so a selector can
21250
+ // target a container inside the same shadow DOM as the embed —
21251
+ // document.querySelector alone cannot pierce shadow boundaries.
21252
+ container = querySelectorAcrossShadowRoot(containerConfig, this.hostElement);
21253
+ }
21254
+ catch (e) {
21255
+ logger$3.error(`Invalid CSS selector for preRenderContainer: ${containerConfig}`, e);
21256
+ }
21257
+ }
21258
+ else if (containerConfig) {
21259
+ container = containerConfig;
21260
+ }
21261
+ return (_a = container) !== null && _a !== void 0 ? _a : document.body;
21262
+ }
21263
+ /**
21264
+ * Makes the container a positioning context for the absolutely positioned
21265
+ * wrapper, stashing the original inline `position` on the element (once) so
21266
+ * destroy() can restore it exactly, leaving no trace. Recording it on the
21267
+ * element rather than per-instance lets the override be reverted even when
21268
+ * embeds share the same container.
21269
+ */
21270
+ applyPreRenderContainerPositioning(container) {
21271
+ if (container === document.body) {
21272
+ return;
21273
+ }
21274
+ const pos = window.getComputedStyle(container).position;
21275
+ if (pos === 'static') {
21276
+ if (container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY] === undefined) {
21277
+ container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY] = container.style.position;
21278
+ }
21279
+ container.style.position = 'relative';
21280
+ }
21281
+ }
21282
+ /**
21283
+ * Re-attaches the wrapper to a live container when the previously resolved
21284
+ * one has been detached or no longer holds the wrapper — e.g. the host app
21285
+ * remounted a custom preRenderContainer, which would otherwise leave a stale
21286
+ * reference and collapse the wrapper. Only string selectors can be
21287
+ * re-resolved; a container passed as an element is left untouched.
21288
+ */
21289
+ reconcilePreRenderContainer() {
21290
+ const wrapper = this.preRenderWrapper;
21291
+ const stored = this.preRenderContainerEl;
21292
+ // Nothing to reconcile until this instance resolved its container.
21293
+ if (!wrapper || !stored) {
21294
+ return;
21295
+ }
21296
+ const storedIsLive = stored === document.body || document.contains(stored);
21297
+ if (storedIsLive && stored.contains(wrapper)) {
21298
+ return;
21299
+ }
21300
+ const resolved = this.resolvePreRenderContainerTarget();
21301
+ // Re-resolution yielded the same (still stale) element — nothing we can
21302
+ // do, e.g. a detached container passed as an HTMLElement.
21303
+ if (resolved === stored && stored.contains(wrapper)) {
21304
+ return;
21305
+ }
21306
+ if (this.containerScrollListener && stored !== resolved) {
21307
+ if (stored !== document.body) {
21308
+ stored.removeEventListener('scroll', this.containerScrollListener);
21309
+ }
21310
+ if (resolved !== document.body) {
21311
+ resolved.addEventListener('scroll', this.containerScrollListener);
21312
+ }
21313
+ }
21314
+ this.applyPreRenderContainerPositioning(resolved);
21315
+ if (wrapper.parentNode !== resolved) {
21316
+ resolved.appendChild(wrapper);
21317
+ }
21318
+ this.preRenderContainerEl = resolved;
21319
+ }
21144
21320
  insertIntoDOMForPreRender(child) {
21145
21321
  const preRenderChild = this.createPreRenderChild(child);
21146
21322
  const preRenderWrapper = this.createPreRenderWrapper();
@@ -21160,7 +21336,10 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21160
21336
  else {
21161
21337
  this.hidePreRender();
21162
21338
  }
21163
- document.body.appendChild(preRenderWrapper);
21339
+ const targetContainer = this.resolvePreRenderContainerTarget();
21340
+ this.preRenderContainerEl = targetContainer;
21341
+ this.applyPreRenderContainerPositioning(targetContainer);
21342
+ targetContainer.appendChild(preRenderWrapper);
21164
21343
  }
21165
21344
  insertIntoDOM(child) {
21166
21345
  var _a;
@@ -21599,6 +21778,50 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21599
21778
  tsParams = tsParams ? `?${tsParams}` : '';
21600
21779
  return tsParams;
21601
21780
  }
21781
+ /**
21782
+ * Reverts the custom preRenderContainer's `position` to the value it had
21783
+ * before we overrode it to `relative` (see insertIntoDOMForPreRender).
21784
+ *
21785
+ * We restore the original inline value rather than forcing `static`, and we
21786
+ * skip the restore if another preRender wrapper is still mounted inside the
21787
+ * same container — a shared container still needs the positioning context.
21788
+ */
21789
+ restorePreRenderContainerPosition() {
21790
+ const container = this.preRenderContainerEl;
21791
+ if (!container || container === document.body) {
21792
+ return;
21793
+ }
21794
+ // Drop our reference up front so a destroyed embed never pins a
21795
+ // detached container in memory; restoration uses the local handle.
21796
+ this.preRenderContainerEl = null;
21797
+ const originalPosition = container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY];
21798
+ if (originalPosition === undefined) {
21799
+ // We never overrode this container's position; nothing to restore.
21800
+ return;
21801
+ }
21802
+ // This instance's own wrapper has already been removed by now, so any
21803
+ // match here belongs to another embed still sharing the container — it
21804
+ // continues to rely on the positioning context, so leave it in place.
21805
+ const hasOtherWrapper = container.querySelector(`[id^="${PRERENDER_WRAPPER_ID_PREFIX}"]`);
21806
+ if (hasOtherWrapper) {
21807
+ return;
21808
+ }
21809
+ container.style.position = originalPosition;
21810
+ delete container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY];
21811
+ }
21812
+ /**
21813
+ * Detaches and clears the container scroll listener, if one is attached.
21814
+ */
21815
+ removeContainerScrollListener() {
21816
+ if (!this.containerScrollListener) {
21817
+ return;
21818
+ }
21819
+ const customContainer = this.preRenderContainerEl && this.preRenderContainerEl !== document.body
21820
+ ? this.preRenderContainerEl
21821
+ : null;
21822
+ customContainer === null || customContainer === void 0 ? void 0 : customContainer.removeEventListener('scroll', this.containerScrollListener);
21823
+ this.containerScrollListener = null;
21824
+ }
21602
21825
  /**
21603
21826
  * Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
21604
21827
  * @version SDK: 1.19.1 | ThoughtSpot: *
@@ -21607,8 +21830,10 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21607
21830
  var _a, _b, _c;
21608
21831
  try {
21609
21832
  this.removeFullscreenChangeHandler();
21833
+ this.removeContainerScrollListener();
21610
21834
  this.unsubscribeToEvents();
21611
21835
  (_a = this.preRenderWrapper) === null || _a === void 0 ? void 0 : _a.remove();
21836
+ this.restorePreRenderContainerPosition();
21612
21837
  if (!this.isRendered) {
21613
21838
  return;
21614
21839
  }
@@ -21718,15 +21943,19 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21718
21943
  }
21719
21944
  this.hostElement.appendChild(this.insertedDomEl);
21720
21945
  this.syncPreRenderStyle();
21946
+ const customContainer = this.preRenderContainerEl && this.preRenderContainerEl !== document.body
21947
+ ? this.preRenderContainerEl
21948
+ : null;
21949
+ if (customContainer && !this.containerScrollListener) {
21950
+ this.containerScrollListener = () => this.syncPreRenderStyle();
21951
+ customContainer.addEventListener('scroll', this.containerScrollListener);
21952
+ }
21721
21953
  if (!this.viewConfig.doNotTrackPreRenderSize) {
21722
21954
  const observeTarget = (_a = this.insertedDomEl) !== null && _a !== void 0 ? _a : this.hostElement;
21723
21955
  this.resizeObserver = new ResizeObserver((entries) => {
21724
21956
  entries.forEach((entry) => {
21725
- if (entry.contentRect && entry.target === observeTarget) {
21726
- setStyleProperties(this.preRenderWrapper, {
21727
- width: `${entry.contentRect.width}px`,
21728
- height: `${entry.contentRect.height}px`,
21729
- });
21957
+ if (entry.target === observeTarget) {
21958
+ this.syncPreRenderStyle();
21730
21959
  }
21731
21960
  });
21732
21961
  });
@@ -21758,14 +21987,24 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21758
21987
  * is not defined or not found.
21759
21988
  */
21760
21989
  syncPreRenderStyle() {
21990
+ var _a;
21761
21991
  if (!this.isPreRenderConnected() || !this.getPreRenderPlaceHolderElement()) {
21762
21992
  logger$3.error(ERROR_MESSAGE.SYNC_STYLE_CALLED_BEFORE_RENDER);
21763
21993
  return;
21764
21994
  }
21995
+ // Self-heal if the resolved container was remounted/detached, so we
21996
+ // never measure a stale node (which would collapse the wrapper).
21997
+ this.reconcilePreRenderContainer();
21765
21998
  const elBoundingClient = this.getPreRenderPlaceHolderElement().getBoundingClientRect();
21999
+ const containerEl = this.preRenderContainerEl && this.preRenderContainerEl !== document.body
22000
+ ? this.preRenderContainerEl
22001
+ : null;
22002
+ const containerRect = (_a = containerEl === null || containerEl === void 0 ? void 0 : containerEl.getBoundingClientRect()) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
22003
+ const scrollX = containerEl ? containerEl.scrollLeft : window.scrollX;
22004
+ const scrollY = containerEl ? containerEl.scrollTop : window.scrollY;
21766
22005
  setStyleProperties(this.preRenderWrapper, {
21767
- top: `${elBoundingClient.y + window.scrollY}px`,
21768
- left: `${elBoundingClient.x + window.scrollX}px`,
22006
+ top: `${elBoundingClient.y - containerRect.y + scrollY}px`,
22007
+ left: `${elBoundingClient.x - containerRect.x + scrollX}px`,
21769
22008
  width: `${elBoundingClient.width}px`,
21770
22009
  height: `${elBoundingClient.height}px`,
21771
22010
  position: 'absolute',
@@ -21792,6 +22031,7 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21792
22031
  overflow: 'hidden',
21793
22032
  };
21794
22033
  setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
22034
+ this.removeContainerScrollListener();
21795
22035
  if (this.resizeObserver) {
21796
22036
  this.resizeObserver.disconnect();
21797
22037
  }
@@ -21810,7 +22050,7 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
21810
22050
  */
21811
22051
  getPreRenderIds() {
21812
22052
  return {
21813
- wrapper: `tsEmbed-pre-render-wrapper-${this.viewConfig.preRenderId}`,
22053
+ wrapper: `${PRERENDER_WRAPPER_ID_PREFIX}${this.viewConfig.preRenderId}`,
21814
22054
  child: `tsEmbed-pre-render-child-${this.viewConfig.preRenderId}`,
21815
22055
  placeHolder: `tsEmbed-pre-render-placeholder-${this.viewConfig.preRenderId}`,
21816
22056
  };
@@ -22519,12 +22759,15 @@ mutation GetUnsavedAnswerTML($session: BachSessionIdInput!, $exportDependencies:
22519
22759
  }
22520
22760
  // Handle spotterChatConfig params
22521
22761
  if (spotterChatConfig) {
22522
- const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, } = spotterChatConfig;
22762
+ const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, enableStarterPrompts, } = spotterChatConfig;
22523
22763
  setParamIfDefined(params, Param.HideToolResponseCardBranding, hideToolResponseCardBranding, true);
22524
22764
  setParamIfDefined(params, Param.ToolResponseCardBrandingLabel, toolResponseCardBrandingLabel);
22525
22765
  if (spotterFileUploadEnabled !== undefined) {
22526
22766
  params[Param.SpotterFileUploadEnabled] = spotterFileUploadEnabled;
22527
22767
  }
22768
+ if (enableStarterPrompts !== undefined) {
22769
+ params[Param.IsStarterPromptsEnabled] = enableStarterPrompts;
22770
+ }
22528
22771
  if (spotterFileUploadFileTypes !== undefined) {
22529
22772
  params[Param.SpotterFileUploadFileTypes] = JSON.stringify(spotterFileUploadFileTypes);
22530
22773
  }
@@ -23080,12 +23323,15 @@ query GetEurekaVizSnapshots(
23080
23323
  }
23081
23324
  // Handle spotterChatConfig params
23082
23325
  if (spotterChatConfig) {
23083
- const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, } = spotterChatConfig;
23326
+ const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, enableStarterPrompts, } = spotterChatConfig;
23084
23327
  setParamIfDefined(params, Param.HideToolResponseCardBranding, hideToolResponseCardBranding, true);
23085
23328
  setParamIfDefined(params, Param.ToolResponseCardBrandingLabel, toolResponseCardBrandingLabel);
23086
23329
  if (spotterFileUploadEnabled !== undefined) {
23087
23330
  params[Param.SpotterFileUploadEnabled] = spotterFileUploadEnabled;
23088
23331
  }
23332
+ if (enableStarterPrompts !== undefined) {
23333
+ params[Param.IsStarterPromptsEnabled] = enableStarterPrompts;
23334
+ }
23089
23335
  if (spotterFileUploadFileTypes !== undefined) {
23090
23336
  params[Param.SpotterFileUploadFileTypes] = JSON.stringify(spotterFileUploadFileTypes);
23091
23337
  }
@@ -23922,10 +24168,11 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
23922
24168
  setParamIfDefined(queryParams, Param.EnableStopAnswerGenerationEmbed, enableStopAnswerGenerationEmbed, true);
23923
24169
  // Handle spotterChatConfig params
23924
24170
  if (spotterChatConfig) {
23925
- const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, } = spotterChatConfig;
24171
+ const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, enableStarterPrompts, } = spotterChatConfig;
23926
24172
  setParamIfDefined(queryParams, Param.HideToolResponseCardBranding, hideToolResponseCardBranding, true);
23927
24173
  setParamIfDefined(queryParams, Param.ToolResponseCardBrandingLabel, toolResponseCardBrandingLabel);
23928
24174
  setParamIfDefined(queryParams, Param.SpotterFileUploadEnabled, spotterFileUploadEnabled, true);
24175
+ setParamIfDefined(queryParams, Param.IsStarterPromptsEnabled, enableStarterPrompts, true);
23929
24176
  if (spotterFileUploadFileTypes !== undefined) {
23930
24177
  queryParams[Param.SpotterFileUploadFileTypes] = JSON.stringify(spotterFileUploadFileTypes);
23931
24178
  }
@@ -24831,8 +25078,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
24831
25078
  return {
24832
25079
  onAnchor: (source) => {
24833
25080
  aliasObjects.push(source);
24834
- if (!prevAnchors)
24835
- prevAnchors = anchorNames(doc);
25081
+ prevAnchors ?? (prevAnchors = anchorNames(doc));
24836
25082
  const anchor = findNewAnchor(prefix, prevAnchors);
24837
25083
  prevAnchors.add(anchor);
24838
25084
  return anchor;
@@ -24996,23 +25242,38 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
24996
25242
  * Resolve the value of this alias within `doc`, finding the last
24997
25243
  * instance of the `source` anchor before this node.
24998
25244
  */
24999
- resolve(doc) {
25245
+ resolve(doc, ctx) {
25246
+ if (ctx?.maxAliasCount === 0)
25247
+ throw new ReferenceError('Alias resolution is disabled');
25248
+ let nodes;
25249
+ if (ctx?.aliasResolveCache) {
25250
+ nodes = ctx.aliasResolveCache;
25251
+ }
25252
+ else {
25253
+ nodes = [];
25254
+ visit$1(doc, {
25255
+ Node: (_key, node) => {
25256
+ if (isAlias(node) || hasAnchor(node))
25257
+ nodes.push(node);
25258
+ }
25259
+ });
25260
+ if (ctx)
25261
+ ctx.aliasResolveCache = nodes;
25262
+ }
25000
25263
  let found = undefined;
25001
- visit$1(doc, {
25002
- Node: (_key, node) => {
25003
- if (node === this)
25004
- return visit$1.BREAK;
25005
- if (node.anchor === this.source)
25006
- found = node;
25007
- }
25008
- });
25264
+ for (const node of nodes) {
25265
+ if (node === this)
25266
+ break;
25267
+ if (node.anchor === this.source)
25268
+ found = node;
25269
+ }
25009
25270
  return found;
25010
25271
  }
25011
25272
  toJSON(_arg, ctx) {
25012
25273
  if (!ctx)
25013
25274
  return { source: this.source };
25014
25275
  const { anchors, doc, maxAliasCount } = ctx;
25015
- const source = this.resolve(doc);
25276
+ const source = this.resolve(doc, ctx);
25016
25277
  if (!source) {
25017
25278
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
25018
25279
  throw new ReferenceError(msg);
@@ -25024,7 +25285,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25024
25285
  data = anchors.get(source);
25025
25286
  }
25026
25287
  /* istanbul ignore if */
25027
- if (!data || data.res === undefined) {
25288
+ if (data?.res === undefined) {
25028
25289
  const msg = 'This should not happen: Alias anchor was not resolved?';
25029
25290
  throw new ReferenceError(msg);
25030
25291
  }
@@ -25131,8 +25392,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25131
25392
  if (aliasDuplicateObjects && value && typeof value === 'object') {
25132
25393
  ref = sourceObjects.get(value);
25133
25394
  if (ref) {
25134
- if (!ref.anchor)
25135
- ref.anchor = onAnchor(value);
25395
+ ref.anchor ?? (ref.anchor = onAnchor(value));
25136
25396
  return new Alias(ref.anchor);
25137
25397
  }
25138
25398
  else {
@@ -25643,7 +25903,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25643
25903
  const { blockQuote, commentString, lineWidth } = ctx.options;
25644
25904
  // 1. Block can't end in whitespace unless the last line is non-empty.
25645
25905
  // 2. Strings consisting of only whitespace are best rendered explicitly.
25646
- if (!blockQuote || /\n[\t ]+$/.test(value) || /^\s*$/.test(value)) {
25906
+ if (!blockQuote || /\n[\t ]+$/.test(value)) {
25647
25907
  return quotedString(value, ctx);
25648
25908
  }
25649
25909
  const indent = ctx.indent ||
@@ -25703,23 +25963,32 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25703
25963
  start = start.replace(/\n+/g, `$&${indent}`);
25704
25964
  }
25705
25965
  const indentSize = indent ? '2' : '1'; // root is at -1
25706
- let header = (literal ? '|' : '>') + (startWithSpace ? indentSize : '') + chomp;
25966
+ // Leading | or > is added later
25967
+ let header = (startWithSpace ? indentSize : '') + chomp;
25707
25968
  if (comment) {
25708
25969
  header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' '));
25709
25970
  if (onComment)
25710
25971
  onComment();
25711
25972
  }
25712
- if (literal) {
25713
- value = value.replace(/\n+/g, `$&${indent}`);
25714
- return `${header}\n${indent}${start}${value}${end}`;
25973
+ if (!literal) {
25974
+ const foldedValue = value
25975
+ .replace(/\n+/g, '\n$&')
25976
+ .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
25977
+ // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent
25978
+ .replace(/\n+/g, `$&${indent}`);
25979
+ let literalFallback = false;
25980
+ const foldOptions = getFoldOptions(ctx, true);
25981
+ if (blockQuote !== 'folded' && type !== Scalar.BLOCK_FOLDED) {
25982
+ foldOptions.onOverflow = () => {
25983
+ literalFallback = true;
25984
+ };
25985
+ }
25986
+ const body = foldFlowLines(`${start}${foldedValue}${end}`, indent, FOLD_BLOCK, foldOptions);
25987
+ if (!literalFallback)
25988
+ return `>${header}\n${indent}${body}`;
25715
25989
  }
25716
- value = value
25717
- .replace(/\n+/g, '\n$&')
25718
- .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded
25719
- // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent
25720
- .replace(/\n+/g, `$&${indent}`);
25721
- const body = foldFlowLines(`${start}${value}${end}`, indent, FOLD_BLOCK, getFoldOptions(ctx, true));
25722
- return `${header}\n${indent}${body}`;
25990
+ value = value.replace(/\n+/g, `$&${indent}`);
25991
+ return `|${header}\n${indent}${start}${value}${end}`;
25723
25992
  }
25724
25993
  function plainString(item, ctx, onComment, onChompKeep) {
25725
25994
  const { type, value } = item;
@@ -25728,10 +25997,9 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25728
25997
  (inFlow && /[[\]{},]/.test(value))) {
25729
25998
  return quotedString(value, ctx);
25730
25999
  }
25731
- if (!value ||
25732
- /^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
26000
+ if (/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(value)) {
25733
26001
  // not allowed:
25734
- // - empty string, '-' or '?'
26002
+ // - '-' or '?'
25735
26003
  // - start with an indicator character (except [?:-]) or /[?-] /
25736
26004
  // - '\n ', ': ' or ' \n' anywhere
25737
26005
  // - '#' not preceded by a non-space char
@@ -25826,6 +26094,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25826
26094
  nullStr: 'null',
25827
26095
  simpleKeys: false,
25828
26096
  singleQuote: null,
26097
+ trailingComma: false,
25829
26098
  trueStr: 'true',
25830
26099
  verifyAliasOrder: true
25831
26100
  }, doc.schema.toStringOptions, options);
@@ -25860,7 +26129,12 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25860
26129
  let obj;
25861
26130
  if (isScalar$1(item)) {
25862
26131
  obj = item.value;
25863
- const match = tags.filter(t => t.identify?.(obj));
26132
+ let match = tags.filter(t => t.identify?.(obj));
26133
+ if (match.length > 1) {
26134
+ const testMatch = match.filter(t => t.test);
26135
+ if (testMatch.length > 0)
26136
+ match = testMatch;
26137
+ }
25864
26138
  tagObj =
25865
26139
  match.find(t => t.format === item.format) ?? match.find(t => !t.format);
25866
26140
  }
@@ -25869,7 +26143,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25869
26143
  tagObj = tags.find(t => t.nodeClass && obj instanceof t.nodeClass);
25870
26144
  }
25871
26145
  if (!tagObj) {
25872
- const name = obj?.constructor?.name ?? typeof obj;
26146
+ const name = obj?.constructor?.name ?? (obj === null ? 'null' : typeof obj);
25873
26147
  throw new Error(`Tag not resolved for ${name} value`);
25874
26148
  }
25875
26149
  return tagObj;
@@ -25884,7 +26158,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25884
26158
  anchors.add(anchor);
25885
26159
  props.push(`&${anchor}`);
25886
26160
  }
25887
- const tag = node.tag ? node.tag : tagObj.default ? null : tagObj.tag;
26161
+ const tag = node.tag ?? (tagObj.default ? null : tagObj.tag);
25888
26162
  if (tag)
25889
26163
  props.push(doc.directives.tagString(tag));
25890
26164
  return props.join(' ');
@@ -25910,8 +26184,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
25910
26184
  const node = isNode(item)
25911
26185
  ? item
25912
26186
  : ctx.doc.createNode(item, { onTagObj: o => (tagObj = o) });
25913
- if (!tagObj)
25914
- tagObj = getTagObject(ctx.doc.schema.tags, node);
26187
+ tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node));
25915
26188
  const props = stringifyProps(node, tagObj, ctx);
25916
26189
  if (props.length > 0)
25917
26190
  ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
@@ -26025,7 +26298,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26025
26298
  ws += `\n${indentComment(cs, ctx.indent)}`;
26026
26299
  }
26027
26300
  if (valueStr === '' && !ctx.inFlow) {
26028
- if (ws === '\n')
26301
+ if (ws === '\n' && valueComment)
26029
26302
  ws = '\n\n';
26030
26303
  }
26031
26304
  else {
@@ -26073,54 +26346,10 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26073
26346
 
26074
26347
  function warn(logLevel, warning) {
26075
26348
  if (logLevel === 'debug' || logLevel === 'warn') {
26076
- if (typeof process !== 'undefined' && process.emitWarning)
26077
- process.emitWarning(warning);
26078
- else
26079
- console.warn(warning);
26349
+ console.warn(warning);
26080
26350
  }
26081
26351
  }
26082
26352
 
26083
- const MERGE_KEY = '<<';
26084
- function addPairToJSMap(ctx, map, { key, value }) {
26085
- if (ctx?.doc.schema.merge && isMergeKey(key)) {
26086
- value = isAlias(value) ? value.resolve(ctx.doc) : value;
26087
- if (isSeq(value))
26088
- for (const it of value.items)
26089
- mergeToJSMap(ctx, map, it);
26090
- else if (Array.isArray(value))
26091
- for (const it of value)
26092
- mergeToJSMap(ctx, map, it);
26093
- else
26094
- mergeToJSMap(ctx, map, value);
26095
- }
26096
- else {
26097
- const jsKey = toJS(key, '', ctx);
26098
- if (map instanceof Map) {
26099
- map.set(jsKey, toJS(value, jsKey, ctx));
26100
- }
26101
- else if (map instanceof Set) {
26102
- map.add(jsKey);
26103
- }
26104
- else {
26105
- const stringKey = stringifyKey(key, jsKey, ctx);
26106
- const jsValue = toJS(value, stringKey, ctx);
26107
- if (stringKey in map)
26108
- Object.defineProperty(map, stringKey, {
26109
- value: jsValue,
26110
- writable: true,
26111
- enumerable: true,
26112
- configurable: true
26113
- });
26114
- else
26115
- map[stringKey] = jsValue;
26116
- }
26117
- }
26118
- return map;
26119
- }
26120
- const isMergeKey = (key) => key === MERGE_KEY ||
26121
- (isScalar$1(key) &&
26122
- key.value === MERGE_KEY &&
26123
- (!key.type || key.type === Scalar.PLAIN));
26124
26353
  // If the value associated with a merge key is a single mapping node, each of
26125
26354
  // its key/value pairs is inserted into the current mapping, unless the key
26126
26355
  // already exists in it. If the value associated with the merge key is a
@@ -26128,8 +26357,36 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26128
26357
  // of these nodes is merged in turn according to its order in the sequence.
26129
26358
  // Keys in mapping nodes earlier in the sequence override keys specified in
26130
26359
  // later mapping nodes. -- http://yaml.org/type/merge.html
26131
- function mergeToJSMap(ctx, map, value) {
26132
- const source = ctx && isAlias(value) ? value.resolve(ctx.doc) : value;
26360
+ const MERGE_KEY = '<<';
26361
+ const merge = {
26362
+ identify: value => value === MERGE_KEY ||
26363
+ (typeof value === 'symbol' && value.description === MERGE_KEY),
26364
+ default: 'key',
26365
+ tag: 'tag:yaml.org,2002:merge',
26366
+ test: /^<<$/,
26367
+ resolve: () => Object.assign(new Scalar(Symbol(MERGE_KEY)), {
26368
+ addToJSMap: addMergeToJSMap
26369
+ }),
26370
+ stringify: () => MERGE_KEY
26371
+ };
26372
+ const isMergeKey = (ctx, key) => (merge.identify(key) ||
26373
+ (isScalar$1(key) &&
26374
+ (!key.type || key.type === Scalar.PLAIN) &&
26375
+ merge.identify(key.value))) &&
26376
+ ctx?.doc.schema.tags.some(tag => tag.tag === merge.tag && tag.default);
26377
+ function addMergeToJSMap(ctx, map, value) {
26378
+ const source = resolveAliasValue(ctx, value);
26379
+ if (isSeq(source))
26380
+ for (const it of source.items)
26381
+ mergeValue(ctx, map, it);
26382
+ else if (Array.isArray(source))
26383
+ for (const it of source)
26384
+ mergeValue(ctx, map, it);
26385
+ else
26386
+ mergeValue(ctx, map, source);
26387
+ }
26388
+ function mergeValue(ctx, map, value) {
26389
+ const source = resolveAliasValue(ctx, value);
26133
26390
  if (!isMap(source))
26134
26391
  throw new Error('Merge sources must be maps or map aliases');
26135
26392
  const srcMap = source.toJSON(null, ctx, Map);
@@ -26152,9 +26409,44 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26152
26409
  }
26153
26410
  return map;
26154
26411
  }
26412
+ function resolveAliasValue(ctx, value) {
26413
+ return ctx && isAlias(value) ? value.resolve(ctx.doc, ctx) : value;
26414
+ }
26415
+
26416
+ function addPairToJSMap(ctx, map, { key, value }) {
26417
+ if (isNode(key) && key.addToJSMap)
26418
+ key.addToJSMap(ctx, map, value);
26419
+ // TODO: Should drop this special case for bare << handling
26420
+ else if (isMergeKey(ctx, key))
26421
+ addMergeToJSMap(ctx, map, value);
26422
+ else {
26423
+ const jsKey = toJS(key, '', ctx);
26424
+ if (map instanceof Map) {
26425
+ map.set(jsKey, toJS(value, jsKey, ctx));
26426
+ }
26427
+ else if (map instanceof Set) {
26428
+ map.add(jsKey);
26429
+ }
26430
+ else {
26431
+ const stringKey = stringifyKey(key, jsKey, ctx);
26432
+ const jsValue = toJS(value, stringKey, ctx);
26433
+ if (stringKey in map)
26434
+ Object.defineProperty(map, stringKey, {
26435
+ value: jsValue,
26436
+ writable: true,
26437
+ enumerable: true,
26438
+ configurable: true
26439
+ });
26440
+ else
26441
+ map[stringKey] = jsValue;
26442
+ }
26443
+ }
26444
+ return map;
26445
+ }
26155
26446
  function stringifyKey(key, jsKey, ctx) {
26156
26447
  if (jsKey === null)
26157
26448
  return '';
26449
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
26158
26450
  if (typeof jsKey !== 'object')
26159
26451
  return String(jsKey);
26160
26452
  if (isNode(key) && ctx?.doc) {
@@ -26307,12 +26599,22 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26307
26599
  if (comment)
26308
26600
  reqNewline = true;
26309
26601
  let str = stringify$2(item, itemCtx, () => (comment = null));
26310
- if (i < items.length - 1)
26602
+ reqNewline || (reqNewline = lines.length > linesAtValue || str.includes('\n'));
26603
+ if (i < items.length - 1) {
26311
26604
  str += ',';
26605
+ }
26606
+ else if (ctx.options.trailingComma) {
26607
+ if (ctx.options.lineWidth > 0) {
26608
+ reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) +
26609
+ (str.length + 2) >
26610
+ ctx.options.lineWidth);
26611
+ }
26612
+ if (reqNewline) {
26613
+ str += ',';
26614
+ }
26615
+ }
26312
26616
  if (comment)
26313
26617
  str += lineComment(str, itemIndent, commentString(comment));
26314
- if (!reqNewline && (lines.length > linesAtValue || str.includes('\n')))
26315
- reqNewline = true;
26316
26618
  lines.push(str);
26317
26619
  linesAtValue = lines.length;
26318
26620
  }
@@ -26657,11 +26959,12 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26657
26959
  const num = typeof value === 'number' ? value : Number(value);
26658
26960
  if (!isFinite(num))
26659
26961
  return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
26660
- let n = JSON.stringify(value);
26962
+ let n = Object.is(value, -0) ? '-0' : JSON.stringify(value);
26661
26963
  if (!format &&
26662
26964
  minFractionDigits &&
26663
26965
  (!tag || tag === 'tag:yaml.org,2002:float') &&
26664
- /^\d/.test(n)) {
26966
+ /^-?\d/.test(n) &&
26967
+ !n.includes('e')) {
26665
26968
  let i = n.indexOf('.');
26666
26969
  if (i < 0) {
26667
26970
  i = n.length;
@@ -26787,7 +27090,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26787
27090
  identify: value => typeof value === 'boolean',
26788
27091
  default: true,
26789
27092
  tag: 'tag:yaml.org,2002:bool',
26790
- test: /^true|false$/,
27093
+ test: /^true$|^false$/,
26791
27094
  resolve: str => str === 'true',
26792
27095
  stringify: stringifyJSON
26793
27096
  },
@@ -26832,10 +27135,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26832
27135
  * document.querySelector('#photo').src = URL.createObjectURL(blob)
26833
27136
  */
26834
27137
  resolve(src, onError) {
26835
- if (typeof Buffer === 'function') {
26836
- return Buffer.from(src, 'base64');
26837
- }
26838
- else if (typeof atob === 'function') {
27138
+ if (typeof atob === 'function') {
26839
27139
  // On IE 11, atob() can't handle newlines
26840
27140
  const str = atob(src.replace(/[\n\r]/g, ''));
26841
27141
  const buffer = new Uint8Array(str.length);
@@ -26849,15 +27149,11 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26849
27149
  }
26850
27150
  },
26851
27151
  stringify({ comment, type, value }, ctx, onComment, onChompKeep) {
27152
+ if (!value)
27153
+ return '';
26852
27154
  const buf = value; // checked earlier by binary.identify()
26853
27155
  let str;
26854
- if (typeof Buffer === 'function') {
26855
- str =
26856
- buf instanceof Buffer
26857
- ? buf.toString('base64')
26858
- : Buffer.from(buf.buffer).toString('base64');
26859
- }
26860
- else if (typeof btoa === 'function') {
27156
+ if (typeof btoa === 'function') {
26861
27157
  let s = '';
26862
27158
  for (let i = 0; i < buf.length; ++i)
26863
27159
  s += String.fromCharCode(buf[i]);
@@ -26866,8 +27162,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
26866
27162
  else {
26867
27163
  throw new Error('This environment does not support writing binary tags; either Buffer or btoa is required');
26868
27164
  }
26869
- if (!type)
26870
- type = Scalar.BLOCK_LITERAL;
27165
+ type ?? (type = Scalar.BLOCK_LITERAL);
26871
27166
  if (type !== Scalar.QUOTE_DOUBLE) {
26872
27167
  const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
26873
27168
  const n = Math.ceil(str.length / lineWidth);
@@ -27336,7 +27631,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27336
27631
  }
27337
27632
  return new Date(date);
27338
27633
  },
27339
- stringify: ({ value }) => value.toISOString().replace(/((T00:00)?:00)?\.000Z$/, '')
27634
+ stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, '') ?? ''
27340
27635
  };
27341
27636
 
27342
27637
  const schema = [
@@ -27354,6 +27649,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27354
27649
  floatExp,
27355
27650
  float,
27356
27651
  binary,
27652
+ merge,
27357
27653
  omap,
27358
27654
  pairs,
27359
27655
  set,
@@ -27381,6 +27677,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27381
27677
  intOct: intOct$1,
27382
27678
  intTime,
27383
27679
  map,
27680
+ merge,
27384
27681
  null: nullTag,
27385
27682
  omap,
27386
27683
  pairs,
@@ -27390,13 +27687,20 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27390
27687
  };
27391
27688
  const coreKnownTags = {
27392
27689
  'tag:yaml.org,2002:binary': binary,
27690
+ 'tag:yaml.org,2002:merge': merge,
27393
27691
  'tag:yaml.org,2002:omap': omap,
27394
27692
  'tag:yaml.org,2002:pairs': pairs,
27395
27693
  'tag:yaml.org,2002:set': set,
27396
27694
  'tag:yaml.org,2002:timestamp': timestamp
27397
27695
  };
27398
- function getTags(customTags, schemaName) {
27399
- let tags = schemas.get(schemaName);
27696
+ function getTags(customTags, schemaName, addMergeTag) {
27697
+ const schemaTags = schemas.get(schemaName);
27698
+ if (schemaTags && !customTags) {
27699
+ return addMergeTag && !schemaTags.includes(merge)
27700
+ ? schemaTags.concat(merge)
27701
+ : schemaTags.slice();
27702
+ }
27703
+ let tags = schemaTags;
27400
27704
  if (!tags) {
27401
27705
  if (Array.isArray(customTags))
27402
27706
  tags = [];
@@ -27415,17 +27719,21 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27415
27719
  else if (typeof customTags === 'function') {
27416
27720
  tags = customTags(tags.slice());
27417
27721
  }
27418
- return tags.map(tag => {
27419
- if (typeof tag !== 'string')
27420
- return tag;
27421
- const tagObj = tagsByName[tag];
27422
- if (tagObj)
27423
- return tagObj;
27424
- const keys = Object.keys(tagsByName)
27425
- .map(key => JSON.stringify(key))
27426
- .join(', ');
27427
- throw new Error(`Unknown custom tag "${tag}"; use one of ${keys}`);
27428
- });
27722
+ if (addMergeTag)
27723
+ tags = tags.concat(merge);
27724
+ return tags.reduce((tags, tag) => {
27725
+ const tagObj = typeof tag === 'string' ? tagsByName[tag] : tag;
27726
+ if (!tagObj) {
27727
+ const tagName = JSON.stringify(tag);
27728
+ const keys = Object.keys(tagsByName)
27729
+ .map(key => JSON.stringify(key))
27730
+ .join(', ');
27731
+ throw new Error(`Unknown custom tag ${tagName}; use one of ${keys}`);
27732
+ }
27733
+ if (!tags.includes(tagObj))
27734
+ tags.push(tagObj);
27735
+ return tags;
27736
+ }, []);
27429
27737
  }
27430
27738
 
27431
27739
  const sortMapEntriesByKey = (a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
@@ -27436,10 +27744,9 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27436
27744
  : compat
27437
27745
  ? getTags(null, compat)
27438
27746
  : null;
27439
- this.merge = !!merge;
27440
27747
  this.name = (typeof schema === 'string' && schema) || 'core';
27441
27748
  this.knownTags = resolveKnownTags ? coreKnownTags : {};
27442
- this.tags = getTags(customTags, this.name);
27749
+ this.tags = getTags(customTags, this.name, merge);
27443
27750
  this.toStringOptions = toStringDefaults ?? null;
27444
27751
  Object.defineProperty(this, MAP, { value: map });
27445
27752
  Object.defineProperty(this, SCALAR$1, { value: string });
@@ -27564,6 +27871,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27564
27871
  logLevel: 'warn',
27565
27872
  prettyErrors: true,
27566
27873
  strict: true,
27874
+ stringKeys: false,
27567
27875
  uniqueKeys: true,
27568
27876
  version: '1.2'
27569
27877
  }, options);
@@ -27787,7 +28095,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27787
28095
  this.directives.yaml.version = '1.1';
27788
28096
  else
27789
28097
  this.directives = new Directives({ version: '1.1' });
27790
- opt = { merge: true, resolveKnownTags: false, schema: 'yaml-1.1' };
28098
+ opt = { resolveKnownTags: false, schema: 'yaml-1.1' };
27791
28099
  break;
27792
28100
  case '1.2':
27793
28101
  case 'next':
@@ -27795,7 +28103,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27795
28103
  this.directives.yaml.version = version;
27796
28104
  else
27797
28105
  this.directives = new Directives({ version });
27798
- opt = { merge: false, resolveKnownTags: true, schema: 'core' };
28106
+ opt = { resolveKnownTags: true, schema: 'core' };
27799
28107
  break;
27800
28108
  case null:
27801
28109
  if (this.directives)
@@ -27908,7 +28216,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27908
28216
  if (/[^ ]/.test(lineStr)) {
27909
28217
  let count = 1;
27910
28218
  const end = error.linePos[1];
27911
- if (end && end.line === line && end.col > col) {
28219
+ if (end?.line === line && end.col > col) {
27912
28220
  count = Math.max(1, Math.min(end.col - col, 80 - ci));
27913
28221
  }
27914
28222
  const pointer = ' '.repeat(ci) + '^'.repeat(count);
@@ -27973,7 +28281,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27973
28281
  if (atNewline) {
27974
28282
  if (comment)
27975
28283
  comment += token.source;
27976
- else
28284
+ else if (!found || indicator !== 'seq-item-ind')
27977
28285
  spaceBefore = true;
27978
28286
  }
27979
28287
  else
@@ -27990,8 +28298,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
27990
28298
  if (token.source.endsWith(':'))
27991
28299
  onError(token.offset + token.source.length - 1, 'BAD_ALIAS', 'Anchor ending in : is ambiguous', true);
27992
28300
  anchor = token;
27993
- if (start === null)
27994
- start = token.offset;
28301
+ start ?? (start = token.offset);
27995
28302
  atNewline = false;
27996
28303
  hasSpace = false;
27997
28304
  reqSpace = true;
@@ -28000,8 +28307,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28000
28307
  if (tag)
28001
28308
  onError(token, 'MULTIPLE_TAGS', 'A node can have at most one tag');
28002
28309
  tag = token;
28003
- if (start === null)
28004
- start = token.offset;
28310
+ start ?? (start = token.offset);
28005
28311
  atNewline = false;
28006
28312
  hasSpace = false;
28007
28313
  reqSpace = true;
@@ -28114,11 +28420,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28114
28420
  return false;
28115
28421
  const isEqual = typeof uniqueKeys === 'function'
28116
28422
  ? uniqueKeys
28117
- : (a, b) => a === b ||
28118
- (isScalar$1(a) &&
28119
- isScalar$1(b) &&
28120
- a.value === b.value &&
28121
- !(a.value === '<<' && ctx.schema.merge));
28423
+ : (a, b) => a === b || (isScalar$1(a) && isScalar$1(b) && a.value === b.value);
28122
28424
  return items.some(pair => isEqual(pair.key, search));
28123
28425
  }
28124
28426
 
@@ -28167,12 +28469,14 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28167
28469
  onError(offset, 'BAD_INDENT', startColMsg);
28168
28470
  }
28169
28471
  // key value
28472
+ ctx.atKey = true;
28170
28473
  const keyStart = keyProps.end;
28171
28474
  const keyNode = key
28172
28475
  ? composeNode(ctx, key, keyProps, onError)
28173
28476
  : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
28174
28477
  if (ctx.schema.compat)
28175
28478
  flowIndentCheck(bm.indent, key, onError);
28479
+ ctx.atKey = false;
28176
28480
  if (mapIncludes(ctx, map.items, keyNode))
28177
28481
  onError(keyStart, 'DUPLICATE_KEY', 'Map keys must be unique');
28178
28482
  // value properties
@@ -28232,6 +28536,8 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28232
28536
  const seq = new NodeClass(ctx.schema);
28233
28537
  if (ctx.atRoot)
28234
28538
  ctx.atRoot = false;
28539
+ if (ctx.atKey)
28540
+ ctx.atKey = false;
28235
28541
  let offset = bs.offset;
28236
28542
  let commentEnd = null;
28237
28543
  for (const { start, value } of bs.items) {
@@ -28245,7 +28551,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28245
28551
  });
28246
28552
  if (!props.found) {
28247
28553
  if (props.anchor || props.tag || value) {
28248
- if (value && value.type === 'block-seq')
28554
+ if (value?.type === 'block-seq')
28249
28555
  onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
28250
28556
  else
28251
28557
  onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
@@ -28316,6 +28622,8 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28316
28622
  const atRoot = ctx.atRoot;
28317
28623
  if (atRoot)
28318
28624
  ctx.atRoot = false;
28625
+ if (ctx.atKey)
28626
+ ctx.atKey = false;
28319
28627
  let offset = fc.offset + fc.start.source.length;
28320
28628
  for (let i = 0; i < fc.items.length; ++i) {
28321
28629
  const collItem = fc.items[i];
@@ -28395,12 +28703,14 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28395
28703
  else {
28396
28704
  // item is a key+value pair
28397
28705
  // key value
28706
+ ctx.atKey = true;
28398
28707
  const keyStart = props.end;
28399
28708
  const keyNode = key
28400
28709
  ? composeNode(ctx, key, props, onError)
28401
28710
  : composeEmptyNode(ctx, keyStart, start, null, props, onError);
28402
28711
  if (isBlock(key))
28403
28712
  onError(keyNode.range, 'BLOCK_IN_FLOW', blockMsg);
28713
+ ctx.atKey = false;
28404
28714
  // value properties
28405
28715
  const valueProps = resolveProps(sep ?? [], {
28406
28716
  flow: fcName,
@@ -28427,7 +28737,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28427
28737
  }
28428
28738
  }
28429
28739
  else if (value) {
28430
- if ('source' in value && value.source && value.source[0] === ':')
28740
+ if ('source' in value && value.source?.[0] === ':')
28431
28741
  onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
28432
28742
  else
28433
28743
  onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
@@ -28471,7 +28781,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28471
28781
  const expectedEnd = isMap ? '}' : ']';
28472
28782
  const [ce, ...ee] = fc.end;
28473
28783
  let cePos = offset;
28474
- if (ce && ce.source === expectedEnd)
28784
+ if (ce?.source === expectedEnd)
28475
28785
  cePos = ce.offset + ce.source.length;
28476
28786
  else {
28477
28787
  const name = fcName[0].toUpperCase() + fcName.substring(1);
@@ -28551,13 +28861,13 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28551
28861
  let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType);
28552
28862
  if (!tag) {
28553
28863
  const kt = ctx.schema.knownTags[tagName];
28554
- if (kt && kt.collection === expType) {
28864
+ if (kt?.collection === expType) {
28555
28865
  ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
28556
28866
  tag = kt;
28557
28867
  }
28558
28868
  else {
28559
- if (kt?.collection) {
28560
- onError(tagToken, 'BAD_COLLECTION_TYPE', `${kt.tag} used for ${expType} collection, but expects ${kt.collection}`, true);
28869
+ if (kt) {
28870
+ onError(tagToken, 'BAD_COLLECTION_TYPE', `${kt.tag} used for ${expType} collection, but expects ${kt.collection ?? 'scalar'}`, true);
28561
28871
  }
28562
28872
  else {
28563
28873
  onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, true);
@@ -28913,7 +29223,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28913
29223
  next = source[++i + 1];
28914
29224
  }
28915
29225
  else if (next === 'x' || next === 'u' || next === 'U') {
28916
- const length = { x: 2, u: 4, U: 8 }[next];
29226
+ const length = next === 'x' ? 2 : next === 'u' ? 4 : 8;
28917
29227
  res += parseCharCode(source, i + 1, length, onError);
28918
29228
  i += length;
28919
29229
  }
@@ -28983,12 +29293,14 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28983
29293
  const cc = source.substr(offset, length);
28984
29294
  const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc);
28985
29295
  const code = ok ? parseInt(cc, 16) : NaN;
28986
- if (isNaN(code)) {
29296
+ try {
29297
+ return String.fromCodePoint(code);
29298
+ }
29299
+ catch {
28987
29300
  const raw = source.substr(offset - 2, length + 2);
28988
29301
  onError(offset - 2, 'BAD_DQ_ESCAPE', `Invalid escape sequence ${raw}`);
28989
29302
  return raw;
28990
29303
  }
28991
- return String.fromCodePoint(code);
28992
29304
  }
28993
29305
 
28994
29306
  function composeScalar(ctx, token, tagToken, onError) {
@@ -28998,11 +29310,16 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
28998
29310
  const tagName = tagToken
28999
29311
  ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
29000
29312
  : null;
29001
- const tag = tagToken && tagName
29002
- ? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError)
29003
- : token.type === 'scalar'
29004
- ? findScalarTagByTest(ctx, value, token, onError)
29005
- : ctx.schema[SCALAR$1];
29313
+ let tag;
29314
+ if (ctx.options.stringKeys && ctx.atKey) {
29315
+ tag = ctx.schema[SCALAR$1];
29316
+ }
29317
+ else if (tagName)
29318
+ tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
29319
+ else if (token.type === 'scalar')
29320
+ tag = findScalarTagByTest(ctx, value, token, onError);
29321
+ else
29322
+ tag = ctx.schema[SCALAR$1];
29006
29323
  let scalar;
29007
29324
  try {
29008
29325
  const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
@@ -29050,8 +29367,9 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29050
29367
  onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
29051
29368
  return schema[SCALAR$1];
29052
29369
  }
29053
- function findScalarTagByTest({ directives, schema }, value, token, onError) {
29054
- const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[SCALAR$1];
29370
+ function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
29371
+ const tag = schema.tags.find(tag => (tag.default === true || (atKey && tag.default === 'key')) &&
29372
+ tag.test?.test(value)) || schema[SCALAR$1];
29055
29373
  if (schema.compat) {
29056
29374
  const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ??
29057
29375
  schema[SCALAR$1];
@@ -29067,8 +29385,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29067
29385
 
29068
29386
  function emptyScalarPosition(offset, before, pos) {
29069
29387
  if (before) {
29070
- if (pos === null)
29071
- pos = before.length;
29388
+ pos ?? (pos = before.length);
29072
29389
  for (let i = pos - 1; i >= 0; --i) {
29073
29390
  let st = before[i];
29074
29391
  switch (st.type) {
@@ -29093,6 +29410,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29093
29410
 
29094
29411
  const CN = { composeNode, composeEmptyNode };
29095
29412
  function composeNode(ctx, token, props, onError) {
29413
+ const atKey = ctx.atKey;
29096
29414
  const { spaceBefore, comment, anchor, tag } = props;
29097
29415
  let node;
29098
29416
  let isSrcToken = true;
@@ -29113,21 +29431,36 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29113
29431
  case 'block-map':
29114
29432
  case 'block-seq':
29115
29433
  case 'flow-collection':
29116
- node = composeCollection(CN, ctx, token, props, onError);
29117
- if (anchor)
29118
- node.anchor = anchor.source.substring(1);
29434
+ try {
29435
+ node = composeCollection(CN, ctx, token, props, onError);
29436
+ if (anchor)
29437
+ node.anchor = anchor.source.substring(1);
29438
+ }
29439
+ catch (error) {
29440
+ // Almost certainly here due to a stack overflow
29441
+ const message = error instanceof Error ? error.message : String(error);
29442
+ onError(token, 'RESOURCE_EXHAUSTION', message);
29443
+ }
29119
29444
  break;
29120
29445
  default: {
29121
29446
  const message = token.type === 'error'
29122
29447
  ? token.message
29123
29448
  : `Unsupported token (type: ${token.type})`;
29124
29449
  onError(token, 'UNEXPECTED_TOKEN', message);
29125
- node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
29126
29450
  isSrcToken = false;
29127
29451
  }
29128
29452
  }
29453
+ node ?? (node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError));
29129
29454
  if (anchor && node.anchor === '')
29130
29455
  onError(anchor, 'BAD_ALIAS', 'Anchor cannot be an empty string');
29456
+ if (atKey &&
29457
+ ctx.options.stringKeys &&
29458
+ (!isScalar$1(node) ||
29459
+ typeof node.value !== 'string' ||
29460
+ (node.tag && node.tag !== 'tag:yaml.org,2002:str'))) {
29461
+ const msg = 'With stringKeys, all keys must be strings';
29462
+ onError(tag ?? token, 'NON_STRING_KEY', msg);
29463
+ }
29131
29464
  if (spaceBefore)
29132
29465
  node.spaceBefore = true;
29133
29466
  if (comment) {
@@ -29180,6 +29513,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29180
29513
  const opts = Object.assign({ _directives: directives }, options);
29181
29514
  const doc = new Document(undefined, opts);
29182
29515
  const ctx = {
29516
+ atKey: false,
29183
29517
  atRoot: true,
29184
29518
  directives: doc.directives,
29185
29519
  options: doc.options,
@@ -29301,8 +29635,10 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
29301
29635
  }
29302
29636
  }
29303
29637
  if (afterDoc) {
29304
- Array.prototype.push.apply(doc.errors, this.errors);
29305
- Array.prototype.push.apply(doc.warnings, this.warnings);
29638
+ for (let i = 0; i < this.errors.length; ++i)
29639
+ doc.errors.push(this.errors[i]);
29640
+ for (let i = 0; i < this.warnings.length; ++i)
29641
+ doc.warnings.push(this.warnings[i]);
29306
29642
  }
29307
29643
  else {
29308
29644
  doc.errors = this.errors;
@@ -30205,7 +30541,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
30205
30541
  const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
30206
30542
  this.indentNext = this.indentValue + 1;
30207
30543
  this.indentValue += n;
30208
- return yield* this.parseBlockStart();
30544
+ return 'block-start';
30209
30545
  }
30210
30546
  return 'doc';
30211
30547
  }
@@ -30526,32 +30862,36 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
30526
30862
  return 0;
30527
30863
  }
30528
30864
  *pushIndicators() {
30529
- switch (this.charAt(0)) {
30530
- case '!':
30531
- return ((yield* this.pushTag()) +
30532
- (yield* this.pushSpaces(true)) +
30533
- (yield* this.pushIndicators()));
30534
- case '&':
30535
- return ((yield* this.pushUntil(isNotAnchorChar)) +
30536
- (yield* this.pushSpaces(true)) +
30537
- (yield* this.pushIndicators()));
30538
- case '-': // this is an error
30539
- case '?': // this is an error outside flow collections
30540
- case ':': {
30541
- const inFlow = this.flowLevel > 0;
30542
- const ch1 = this.charAt(1);
30543
- if (isEmpty(ch1) || (inFlow && flowIndicatorChars.has(ch1))) {
30544
- if (!inFlow)
30545
- this.indentNext = this.indentValue + 1;
30546
- else if (this.flowKey)
30547
- this.flowKey = false;
30548
- return ((yield* this.pushCount(1)) +
30549
- (yield* this.pushSpaces(true)) +
30550
- (yield* this.pushIndicators()));
30865
+ let n = 0;
30866
+ loop: while (true) {
30867
+ switch (this.charAt(0)) {
30868
+ case '!':
30869
+ n += yield* this.pushTag();
30870
+ n += yield* this.pushSpaces(true);
30871
+ continue loop;
30872
+ case '&':
30873
+ n += yield* this.pushUntil(isNotAnchorChar);
30874
+ n += yield* this.pushSpaces(true);
30875
+ continue loop;
30876
+ case '-': // this is an error
30877
+ case '?': // this is an error outside flow collections
30878
+ case ':': {
30879
+ const inFlow = this.flowLevel > 0;
30880
+ const ch1 = this.charAt(1);
30881
+ if (isEmpty(ch1) || (inFlow && flowIndicatorChars.has(ch1))) {
30882
+ if (!inFlow)
30883
+ this.indentNext = this.indentValue + 1;
30884
+ else if (this.flowKey)
30885
+ this.flowKey = false;
30886
+ n += yield* this.pushCount(1);
30887
+ n += yield* this.pushSpaces(true);
30888
+ continue loop;
30889
+ }
30551
30890
  }
30552
30891
  }
30892
+ break loop;
30553
30893
  }
30554
- return 0;
30894
+ return n;
30555
30895
  }
30556
30896
  *pushTag() {
30557
30897
  if (this.charAt(1) === '<') {
@@ -30713,6 +31053,14 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
30713
31053
  }
30714
31054
  return prev.splice(i, prev.length);
30715
31055
  }
31056
+ function arrayPushArray(target, source) {
31057
+ // May exhaust call stack with large `source` array
31058
+ if (source.length < 1e5)
31059
+ Array.prototype.push.apply(target, source);
31060
+ else
31061
+ for (let i = 0; i < source.length; ++i)
31062
+ target.push(source[i]);
31063
+ }
30716
31064
  function fixFlowSeqItems(fc) {
30717
31065
  if (fc.start.type === 'flow-seq-start') {
30718
31066
  for (const it of fc.items) {
@@ -30725,12 +31073,12 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
30725
31073
  delete it.key;
30726
31074
  if (isFlowToken(it.value)) {
30727
31075
  if (it.value.end)
30728
- Array.prototype.push.apply(it.value.end, it.sep);
31076
+ arrayPushArray(it.value.end, it.sep);
30729
31077
  else
30730
31078
  it.value.end = it.sep;
30731
31079
  }
30732
31080
  else
30733
- Array.prototype.push.apply(it.start, it.sep);
31081
+ arrayPushArray(it.start, it.sep);
30734
31082
  delete it.sep;
30735
31083
  }
30736
31084
  }
@@ -30872,7 +31220,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
30872
31220
  }
30873
31221
  *step() {
30874
31222
  const top = this.peek(1);
30875
- if (this.type === 'doc-end' && (!top || top.type !== 'doc-end')) {
31223
+ if (this.type === 'doc-end' && top?.type !== 'doc-end') {
30876
31224
  while (this.stack.length > 0)
30877
31225
  yield* this.pop();
30878
31226
  this.stack.push({
@@ -31148,7 +31496,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
31148
31496
  const prev = map.items[map.items.length - 2];
31149
31497
  const end = prev?.value?.end;
31150
31498
  if (Array.isArray(end)) {
31151
- Array.prototype.push.apply(end, it.start);
31499
+ arrayPushArray(end, it.start);
31152
31500
  end.push(this.sourceToken);
31153
31501
  map.items.pop();
31154
31502
  return;
@@ -31314,7 +31662,20 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
31314
31662
  default: {
31315
31663
  const bv = this.startBlockValue(map);
31316
31664
  if (bv) {
31317
- if (atMapIndent && bv.type !== 'block-seq') {
31665
+ if (bv.type === 'block-seq') {
31666
+ if (!it.explicitKey &&
31667
+ it.sep &&
31668
+ !includesToken(it.sep, 'newline')) {
31669
+ yield* this.pop({
31670
+ type: 'error',
31671
+ offset: this.offset,
31672
+ message: 'Unexpected block-seq-ind on same line with key',
31673
+ source: this.source
31674
+ });
31675
+ return;
31676
+ }
31677
+ }
31678
+ else if (atMapIndent) {
31318
31679
  map.items.push({ start });
31319
31680
  }
31320
31681
  this.stack.push(bv);
@@ -31350,7 +31711,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
31350
31711
  const prev = seq.items[seq.items.length - 2];
31351
31712
  const end = prev?.value?.end;
31352
31713
  if (Array.isArray(end)) {
31353
- Array.prototype.push.apply(end, it.start);
31714
+ arrayPushArray(end, it.start);
31354
31715
  end.push(this.sourceToken);
31355
31716
  seq.items.pop();
31356
31717
  return;
@@ -31391,7 +31752,7 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
31391
31752
  do {
31392
31753
  yield* this.pop();
31393
31754
  top = this.peek(1);
31394
- } while (top && top.type === 'flow-collection');
31755
+ } while (top?.type === 'flow-collection');
31395
31756
  }
31396
31757
  else if (fc.end.length === 0) {
31397
31758
  switch (this.type) {
@@ -31685,6 +32046,8 @@ query SendMessage($params: Input_convassist_SendMessageRequest) {
31685
32046
  if (!keepUndefined)
31686
32047
  return undefined;
31687
32048
  }
32049
+ if (isDocument(value) && !_replacer)
32050
+ return value.toString(options);
31688
32051
  return new Document(value, _replacer, options).toString(options);
31689
32052
  }
31690
32053