Skip to content

Commit 6da439b

Browse files
authored
Address CodeQL warnings (#351)
1 parent aa86707 commit 6da439b

File tree

8 files changed

+63
-19
lines changed

8 files changed

+63
-19
lines changed

.github/codeql/codeql-config.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: "CodeQL Config for CrestApps.OrchardCore"
22

3-
# This configuration file is automatically used by GitHub's default CodeQL
4-
# setup. It does NOT require a separate workflow file.
3+
# This configuration file is referenced by .github/workflows/codeql.yml.
4+
# It is NOT automatically used by GitHub's default CodeQL setup.
55

66
# Paths to ignore during analysis.
77
paths-ignore:
@@ -12,6 +12,8 @@ paths-ignore:
1212
- "docs/**"
1313
- "BenchmarkDotNet.Artifacts/**"
1414
- "TestResults/**"
15+
# Third-party / generated files that should not be analysed.
16+
- "**/Assets/js/flatpickr-culture.js"
1517

1618
query-filters:
1719
# Exclude CSRF (missing antiforgery token) alerts.

.github/workflows/codeql.yml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ permissions:
1414
contents: read
1515

1616
jobs:
17-
analyze:
17+
analyze-csharp:
1818
name: Analyze C#
1919
runs-on: ubuntu-latest
2020
timeout-minutes: 60
@@ -41,3 +41,23 @@ jobs:
4141
uses: github/codeql-action/analyze@v3
4242
with:
4343
category: "/language:csharp"
44+
45+
analyze-javascript:
46+
name: Analyze JavaScript
47+
runs-on: ubuntu-latest
48+
timeout-minutes: 30
49+
50+
steps:
51+
- name: Checkout repository
52+
uses: actions/checkout@v4
53+
54+
- name: Initialize CodeQL
55+
uses: github/codeql-action/init@v3
56+
with:
57+
languages: javascript-typescript
58+
config-file: ./.github/codeql/codeql-config.yml
59+
60+
- name: Perform CodeQL Analysis
61+
uses: github/codeql-action/analyze@v3
62+
with:
63+
category: "/language:javascript-typescript"

src/Modules/CrestApps.OrchardCore.AI.Chat.Interactions/Assets/js/chat-interaction.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ window.chatInteractionManager = function () {
2121
</div>
2222
<div class="lh-base">
2323
<h4 v-if="message.title">{{ message.title }}</h4>
24-
<div v-html="message.htmlContent || message.content"></div>
24+
<div v-html="message.htmlContent"></div>
2525
<span class="message-buttons-container" v-if="!isIndicator(message)">
2626
<button class="btn btn-sm btn-link text-secondary p-0 button-message-toolbox" @click="copyResponse(message.content)" title="Click here to copy response to clipboard.">
2727
<i class="fa-solid fa-copy"></i>
@@ -415,6 +415,9 @@ window.chatInteractionManager = function () {
415415
}
416416
},
417417
addMessageInternal(message) {
418+
if (message.content && !message.htmlContent) {
419+
message.htmlContent = parseMarkdownContent(message.content, message);
420+
}
418421
this.fireEvent(new CustomEvent("addingChatInteractionMessage", { detail: { message: message } }));
419422
this.messages.push(message);
420423

@@ -688,14 +691,14 @@ window.chatInteractionManager = function () {
688691
var stopIcon = this.buttonElement.getAttribute('data-stop-icon');
689692

690693
if (stopIcon) {
691-
this.buttonElement.innerHTML = DOMPurify.sanitize(stopIcon);
694+
this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));
692695
}
693696
},
694697
streamingFinished() {
695698
var startIcon = this.buttonElement.getAttribute('data-start-icon');
696699

697700
if (startIcon) {
698-
this.buttonElement.innerHTML = DOMPurify.sanitize(startIcon);
701+
this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));
699702
}
700703

701704
// Directly manipulate the DOM to stop all streaming animations.

src/Modules/CrestApps.OrchardCore.AI.Chat.Interactions/wwwroot/scripts/chat-interaction.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ window.chatInteractionManager = function () {
2929
downloadImageTitle: 'Download image',
3030
downloadChartTitle: 'Download chart as image',
3131
downloadChartButtonText: 'Download',
32-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i :class=\"'fa fa-robot' + (message.isStreaming ? ' ai-streaming-icon' : ' ai-bot-icon')\"></i>\n Assistant\n </div>\n <div class=\"lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent || message.content\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n ",
32+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i :class=\"'fa fa-robot' + (message.isStreaming ? ' ai-streaming-icon' : ' ai-bot-icon')\"></i>\n Assistant\n </div>\n <div class=\"lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n ",
3333
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i class=\"fa fa-robot ai-streaming-icon\" style=\"display: inline-block;\"></i>\n Assistant\n </div>\n ",
3434
// Localizable strings
3535
untitledText: 'Untitled',
@@ -386,6 +386,9 @@ window.chatInteractionManager = function () {
386386
},
387387
addMessageInternal: function addMessageInternal(message) {
388388
var _this2 = this;
389+
if (message.content && !message.htmlContent) {
390+
message.htmlContent = parseMarkdownContent(message.content, message);
391+
}
389392
this.fireEvent(new CustomEvent("addingChatInteractionMessage", {
390393
detail: {
391394
message: message
@@ -724,13 +727,17 @@ window.chatInteractionManager = function () {
724727
streamingStarted: function streamingStarted() {
725728
var stopIcon = this.buttonElement.getAttribute('data-stop-icon');
726729
if (stopIcon) {
727-
this.buttonElement.innerHTML = DOMPurify.sanitize(stopIcon);
730+
this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, {
731+
RETURN_DOM_FRAGMENT: true
732+
}));
728733
}
729734
},
730735
streamingFinished: function streamingFinished() {
731736
var startIcon = this.buttonElement.getAttribute('data-start-icon');
732737
if (startIcon) {
733-
this.buttonElement.innerHTML = DOMPurify.sanitize(startIcon);
738+
this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, {
739+
RETURN_DOM_FRAGMENT: true
740+
}));
734741
}
735742

736743
// Directly manipulate the DOM to stop all streaming animations.

src/Modules/CrestApps.OrchardCore.AI.Chat.Interactions/wwwroot/scripts/chat-interaction.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Modules/CrestApps.OrchardCore.AI.Chat/Assets/js/ai-chat.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ window.openAIChatManager = function () {
2525
</div>
2626
<div class="lh-base">
2727
<h4 v-if="message.title">{{ message.title }}</h4>
28-
<div v-html="message.htmlContent || message.content"></div>
28+
<div v-html="message.htmlContent"></div>
2929
<span class="message-buttons-container" v-if="!isIndicator(message)">
3030
<template v-if="metricsEnabled && message.role === 'assistant'">
3131
<span class="ai-chat-message-assistant-feedback" :data-message-id="message.id">
@@ -517,7 +517,7 @@ window.openAIChatManager = function () {
517517

518518
html += '</div>';
519519

520-
this.documentBar.innerHTML = DOMPurify.sanitize(html);
520+
this.documentBar.replaceChildren(DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));
521521

522522
// Bind remove handlers
523523
var self = this;
@@ -613,6 +613,9 @@ window.openAIChatManager = function () {
613613
}
614614
},
615615
addMessageInternal(message) {
616+
if (message.content && !message.htmlContent) {
617+
message.htmlContent = parseMarkdownContent(message.content, message);
618+
}
616619
this.fireEvent(new CustomEvent("addingOpenAIPromotMessage", { detail: { message: message } }));
617620
this.messages.push(message);
618621

@@ -915,7 +918,7 @@ window.openAIChatManager = function () {
915918
var stopIcon = this.buttonElement.getAttribute('data-stop-icon');
916919

917920
if (stopIcon) {
918-
this.buttonElement.innerHTML = DOMPurify.sanitize(stopIcon);
921+
this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, { RETURN_DOM_FRAGMENT: true }));
919922
}
920923

921924
if (this.inputElement) {
@@ -926,7 +929,7 @@ window.openAIChatManager = function () {
926929
var startIcon = this.buttonElement.getAttribute('data-start-icon');
927930

928931
if (startIcon) {
929-
this.buttonElement.innerHTML = DOMPurify.sanitize(startIcon);
932+
this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, { RETURN_DOM_FRAGMENT: true }));
930933
}
931934

932935
if (this.inputElement) {

src/Modules/CrestApps.OrchardCore.AI.Chat/wwwroot/scripts/ai-chat.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ window.openAIChatManager = function () {
3434
thumbsUpTitle: 'Thumbs up',
3535
thumbsDownTitle: 'Thumbs down',
3636
copyTitle: 'Click here to copy response to clipboard.',
37-
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i :class=\"'fa fa-robot' + (message.isStreaming ? ' ai-streaming-icon' : ' ai-bot-icon')\"></i>\n {{ assistantLabel }}\n </div>\n <div class=\"lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent || message.content\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n ",
37+
messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">{{ userLabel }}</div>\n <div v-else-if=\"message.role !== 'indicator'\" class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i :class=\"'fa fa-robot' + (message.isStreaming ? ' ai-streaming-icon' : ' ai-bot-icon')\"></i>\n {{ assistantLabel }}\n </div>\n <div class=\"lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <template v-if=\"metricsEnabled && message.role === 'assistant'\">\n <span class=\"ai-chat-message-assistant-feedback\" :data-message-id=\"message.id\">\n <button class=\"btn btn-sm btn-link text-success p-0 me-2 button-message-toolbox rate-up-btn\" @click=\"rateMessage(message, true, $event)\" :title=\"thumbsUpTitle\">\n <i class=\"fa-regular fa-thumbs-up\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-danger p-0 me-2 button-message-toolbox rate-down-btn\" @click=\"rateMessage(message, false, $event)\" :title=\"thumbsDownTitle\">\n <i class=\"fa-regular fa-thumbs-down\"></i>\n </button>\n </span>\n </template>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" :title=\"copyTitle\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n ",
3838
indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <i class=\"fa fa-robot ai-streaming-icon\" style=\"display: inline-block;\"></i>\n Assistant\n </div>\n "
3939
};
4040

@@ -528,7 +528,9 @@ window.openAIChatManager = function () {
528528
}
529529
html += '</button>';
530530
html += '</div>';
531-
this.documentBar.innerHTML = DOMPurify.sanitize(html);
531+
this.documentBar.replaceChildren(DOMPurify.sanitize(html, {
532+
RETURN_DOM_FRAGMENT: true
533+
}));
532534

533535
// Bind remove handlers
534536
var self = this;
@@ -631,6 +633,9 @@ window.openAIChatManager = function () {
631633
},
632634
addMessageInternal: function addMessageInternal(message) {
633635
var _this4 = this;
636+
if (message.content && !message.htmlContent) {
637+
message.htmlContent = parseMarkdownContent(message.content, message);
638+
}
634639
this.fireEvent(new CustomEvent("addingOpenAIPromotMessage", {
635640
detail: {
636641
message: message
@@ -977,7 +982,9 @@ window.openAIChatManager = function () {
977982
streamingStarted: function streamingStarted() {
978983
var stopIcon = this.buttonElement.getAttribute('data-stop-icon');
979984
if (stopIcon) {
980-
this.buttonElement.innerHTML = DOMPurify.sanitize(stopIcon);
985+
this.buttonElement.replaceChildren(DOMPurify.sanitize(stopIcon, {
986+
RETURN_DOM_FRAGMENT: true
987+
}));
981988
}
982989
if (this.inputElement) {
983990
this.inputElement.setAttribute('disabled', 'disabled');
@@ -986,7 +993,9 @@ window.openAIChatManager = function () {
986993
streamingFinished: function streamingFinished() {
987994
var startIcon = this.buttonElement.getAttribute('data-start-icon');
988995
if (startIcon) {
989-
this.buttonElement.innerHTML = DOMPurify.sanitize(startIcon);
996+
this.buttonElement.replaceChildren(DOMPurify.sanitize(startIcon, {
997+
RETURN_DOM_FRAGMENT: true
998+
}));
990999
}
9911000
if (this.inputElement) {
9921001
this.inputElement.removeAttribute('disabled');

src/Modules/CrestApps.OrchardCore.AI.Chat/wwwroot/scripts/ai-chat.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)