@coveo/quantic 3.39.1 → 3.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/force-app/main/default/classes/HeadlessControllerTest.cls +1 -0
  2. package/force-app/main/default/classes/InsightControllerTest.cls +1 -0
  3. package/force-app/main/default/classes/RecommendationsControllerTest.cls +1 -1
  4. package/force-app/main/default/classes/SampleTokenProvider.cls +1 -0
  5. package/force-app/main/default/classes/SampleTokenProviderTest.cls +1 -0
  6. package/force-app/main/default/labels/CustomLabels.labels-meta.xml +77 -0
  7. package/force-app/main/default/lwc/quanticGeneratedAnswer/__tests__/quanticGeneratedAnswer.test.js +54 -0
  8. package/force-app/main/default/lwc/quanticGeneratedAnswer/quanticGeneratedAnswer.js +26 -3
  9. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.css +5 -0
  10. package/force-app/main/default/lwc/quanticGeneratedAnswer/templates/generatedAnswer.html +3 -1
  11. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/__tests__/quanticGeneratedAnswerBody.test.js +341 -0
  12. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/quanticGeneratedAnswerBody.js +148 -0
  13. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/quanticGeneratedAnswerBody.js-meta.xml +5 -0
  14. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/answer.css +3 -0
  15. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/answer.html +53 -0
  16. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/cannotAnswer.html +7 -0
  17. package/force-app/main/default/lwc/quanticGeneratedAnswerBody/templates/error.html +7 -0
  18. package/force-app/main/default/lwc/quanticGeneratedAnswerContent/__tests__/quanticGeneratedAnswerContent.test.js +269 -0
  19. package/force-app/main/default/lwc/quanticGeneratedAnswerContent/quanticGeneratedAnswerContent.js +136 -0
  20. package/force-app/main/default/lwc/quanticGeneratedAnswerContent/templates/generatedMarkdownContent.css +10 -0
  21. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/__tests__/quanticGeneratedAnswerStreamOfThought.test.js +348 -0
  22. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.css +17 -0
  23. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.js +163 -0
  24. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/quanticGeneratedAnswerStreamOfThought.js-meta.xml +5 -0
  25. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/collapsedSummary.css +1 -0
  26. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/collapsedSummary.html +32 -0
  27. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/streamOfThought.css +1 -0
  28. package/force-app/main/default/lwc/quanticGeneratedAnswerStreamOfThought/templates/streamOfThought.html +65 -0
  29. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/__tests__/quanticGeneratedAnswerThread.test.js +285 -0
  30. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.css +47 -0
  31. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.html +67 -0
  32. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.js +93 -0
  33. package/force-app/main/default/lwc/quanticGeneratedAnswerThread/quanticGeneratedAnswerThread.js-meta.xml +5 -0
  34. package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.css +0 -4
  35. package/force-app/main/default/lwc/quanticThreadItem/quanticThreadItem.html +1 -1
  36. package/force-app/main/default/lwc/quanticUtils/__tests__/markdownUtils.test.js +38 -0
  37. package/force-app/main/default/lwc/quanticUtils/markdownUtils.js +18 -0
  38. package/force-app/main/default/staticresources/coveoheadless/case-assist/headless.js +6 -6
  39. package/force-app/main/default/staticresources/coveoheadless/definitions/api/commerce/common/pagination.d.ts +1 -1
  40. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/core/generated-answer/headless-core-generated-answer.d.ts +1 -0
  41. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/core/generated-answer/headless-core-interactive-citation.d.ts +3 -3
  42. package/force-app/main/default/staticresources/coveoheadless/definitions/controllers/generated-answer/interactive-citation-analytics-client.d.ts +3 -0
  43. package/force-app/main/default/staticresources/coveoheadless/definitions/features/analytics/analytics-utils.d.ts +3 -2
  44. package/force-app/main/default/staticresources/coveoheadless/definitions/features/generated-answer/generated-answer-analytics-actions.d.ts +2 -0
  45. package/force-app/main/default/staticresources/coveoheadless/headless.js +17 -17
  46. package/force-app/main/default/staticresources/coveoheadless/insight/headless.js +7 -7
  47. package/force-app/main/default/staticresources/coveoheadless/recommendation/headless.js +14 -14
  48. package/package.json +2 -2
@@ -0,0 +1,93 @@
1
+ import {LightningElement, api} from 'lwc';
2
+ import showPreviousQuestions_plural from '@salesforce/label/c.quantic_ShowPreviousQuestions_plural';
3
+ import {I18nUtils} from 'c/quanticUtils';
4
+
5
+ /** @typedef {import("coveo").GeneratedAnswerBase} GeneratedAnswer */
6
+
7
+ const MIN_ANSWERS_TO_COLLAPSE = 2;
8
+
9
+ /**
10
+ * The `QuanticGeneratedAnswerThread` component renders a thread of generated answers, including the initial answer and follow-up answers.
11
+ * @category Internal
12
+ * @example
13
+ * <c-quantic-generated-answer-thread engine-id={engineId} generated-answers={generatedAnswers}></c-quantic-generated-answer-thread>
14
+ */
15
+ export default class QuanticGeneratedAnswerThread extends LightningElement {
16
+ /**
17
+ * The ID of the engine instance the component registers to.
18
+ * @api
19
+ * @type {string}
20
+ */
21
+ @api engineId;
22
+
23
+ /**
24
+ * The list of generated answers to render in the thread.
25
+ * @api
26
+ * @type {GeneratedAnswer[]}
27
+ */
28
+ @api
29
+ get generatedAnswers() {
30
+ return this._generatedAnswers;
31
+ }
32
+ set generatedAnswers(value) {
33
+ const previous = this._generatedAnswers;
34
+ this._generatedAnswers = value ?? [];
35
+ if (previous?.length !== this._generatedAnswers.length) {
36
+ this._allAnswersDisplayed = false;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Whether to disable citation anchoring.
42
+ * @api
43
+ * @type {boolean}
44
+ * @defaultValue `false`
45
+ */
46
+ @api disableCitationAnchoring = false;
47
+
48
+ /** @type {boolean} */
49
+ _allAnswersDisplayed = false;
50
+ /** @type {GeneratedAnswer[]} */
51
+ _generatedAnswers = [];
52
+
53
+ labels = {
54
+ showPreviousQuestions_plural,
55
+ };
56
+
57
+ get isSingleAnswer() {
58
+ return this.generatedAnswers.length === 1;
59
+ }
60
+
61
+ get shouldCollapseOlderAnswers() {
62
+ return (
63
+ this.generatedAnswers.length > MIN_ANSWERS_TO_COLLAPSE &&
64
+ !this._allAnswersDisplayed
65
+ );
66
+ }
67
+
68
+ get showPreviousQuestionsLabel() {
69
+ return I18nUtils.format(
70
+ this.labels.showPreviousQuestions_plural,
71
+ this.generatedAnswers.length - 1
72
+ );
73
+ }
74
+
75
+ get previousAnswers() {
76
+ if (this.shouldCollapseOlderAnswers) {
77
+ return [];
78
+ }
79
+ return this.generatedAnswers.slice(0, -1);
80
+ }
81
+
82
+ get headAnswer() {
83
+ return this.generatedAnswers[0];
84
+ }
85
+
86
+ get lastAnswer() {
87
+ return this.generatedAnswers[this.generatedAnswers.length - 1];
88
+ }
89
+
90
+ handleShowAllClick() {
91
+ this._allAnswersDisplayed = true;
92
+ }
93
+ }
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <apiVersion>66.0</apiVersion>
4
+ <isExposed>false</isExposed>
5
+ </LightningComponentBundle>
@@ -7,10 +7,6 @@
7
7
  width: 10px;
8
8
  }
9
9
 
10
- .thread-item__line-column {
11
- align-items: stretch;
12
- }
13
-
14
10
  .thread-item__dot {
15
11
  height: 8px;
16
12
  width: 8px;
@@ -6,7 +6,7 @@
6
6
  >
7
7
  <span class={dotClass} data-testid="thread-item-dot"></span>
8
8
  </div>
9
- <div class="slds-col slds-has-flexi-truncate">
9
+ <div class="slds-has-flexi-truncate">
10
10
  <template lwc:if={disableCollapse}>
11
11
  <span class={titleClass} data-testid="thread-item-title-static"
12
12
  >{title}</span
@@ -67,5 +67,43 @@ describe('c/markdownUtils', () => {
67
67
  const resultCode = transformMarkdownToHtml(textCode, marked);
68
68
  expect(removeLineBreaks(resultCode)).toEqual('<p><code>code</code></p>');
69
69
  });
70
+
71
+ it('should transform markdown link to HTML <a> with data-answer-inline-link attribute', () => {
72
+ const text = '[Google](https://google.com)';
73
+ const result = transformMarkdownToHtml(text, marked);
74
+ expect(removeLineBreaks(result)).toEqual(
75
+ '<p><a href="https://google.com" data-answer-inline-link="true">Google</a></p>'
76
+ );
77
+ });
78
+
79
+ it('should transform markdown link with title to HTML <a> with title attribute', () => {
80
+ const text = '[Google](https://google.com "Search Engine")';
81
+ const result = transformMarkdownToHtml(text, marked);
82
+ expect(removeLineBreaks(result)).toEqual(
83
+ '<p><a href="https://google.com" title="Search Engine" data-answer-inline-link="true">Google</a></p>'
84
+ );
85
+ });
86
+
87
+ it('should escape special characters in link href', () => {
88
+ const text = '[Link](https://example.com?param="value"&other=test)';
89
+ const result = transformMarkdownToHtml(text, marked);
90
+ expect(removeLineBreaks(result)).toEqual(
91
+ '<p><a href="https://example.com?param=&quot;value&quot;&amp;other=test" data-answer-inline-link="true">Link</a></p>'
92
+ );
93
+ });
94
+
95
+ it('should escape special characters in link title', () => {
96
+ const text = '[Link](https://example.com "Title with <script> & quotes")';
97
+ const result = transformMarkdownToHtml(text, marked);
98
+ expect(removeLineBreaks(result)).toEqual(
99
+ '<p><a href="https://example.com" title="Title with &amp;lt;script&amp;gt; &amp;amp; quotes" data-answer-inline-link="true">Link</a></p>'
100
+ );
101
+ });
102
+
103
+ it('should render link text as span when href is missing', () => {
104
+ const text = '[Link]()';
105
+ const result = transformMarkdownToHtml(text, marked);
106
+ expect(removeLineBreaks(result)).toEqual('<p><span>Link</span></p>');
107
+ });
70
108
  });
71
109
  });
@@ -117,6 +117,24 @@ const customRenderer = {
117
117
  text(text) {
118
118
  return completeUnclosedElement(text);
119
119
  },
120
+
121
+ /**
122
+ * Custom Marked renderer for links.
123
+ * @param {string} href The link href.
124
+ * @param {string} title The link title.
125
+ * @param {string} text The link text.
126
+ * @returns {string} The link element to render.
127
+ */
128
+ link(href, title, text) {
129
+ const titleAttribute = title ? ` title="${escapeHtml(title)}"` : '';
130
+ const safeHref = href ? escapeHtml(href) : '';
131
+
132
+ if (!safeHref) {
133
+ return `<span>${text}</span>`;
134
+ }
135
+
136
+ return `<a href="${safeHref}"${titleAttribute} data-answer-inline-link="true">${text}</a>`;
137
+ },
120
138
  };
121
139
 
122
140
  /**