Skip to content
56 changes: 37 additions & 19 deletions src/scripts/scrumHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -1000,20 +1000,16 @@ function allIncluded(outputTarget = 'email') {
log('[DEBUG] Both data processing functions completed, generating scrum body');
if (subjectForEmail) {
// Synchronized subject and body injection for email
let lastWeekUl = '<ul>';
for (let i = 0; i < lastWeekArray.length; i++) lastWeekUl += lastWeekArray[i];
for (let i = 0; i < reviewedPrsArray.length; i++) lastWeekUl += reviewedPrsArray[i];
lastWeekUl += '</ul>';
let nextWeekUl = '<ul>';
for (let i = 0; i < nextWeekArray.length; i++) nextWeekUl += nextWeekArray[i];
nextWeekUl += '</ul>';
const lastWeekUl = buildActivityListHtml();
const nextWeekUl = buildNextWeekListHtml();
const blockerText = buildBlockerTextHtml();
const weekOrDay = yesterdayContribution ? 'yesterday' : 'the period';
const weekOrDay2 = 'today';
let content;
if (yesterdayContribution) {
content = `<b>1. What did I do ${weekOrDay}?</b><br>${lastWeekUl}<br><b>2. What do I plan to do ${weekOrDay2}?</b><br>${nextWeekUl}<br><b>3. What is blocking me from making progress?</b><br>${userReason}`;
content = `<b>1. What did I do ${weekOrDay}?</b><br>${lastWeekUl}<br><b>2. What do I plan to do ${weekOrDay2}?</b><br>${nextWeekUl}<br><b>3. What is blocking me from making progress?</b><br>${blockerText}`;
} else {
content = `<b>1. What did I do from ${formatDate(startingDate)} to ${formatDate(endingDate)}?</b><br>${lastWeekUl}<br><b>2. What do I plan to do ${weekOrDay2}?</b><br>${nextWeekUl}<br><b>3. What is blocking me from making progress?</b><br>${userReason}`;
content = `<b>1. What did I do from ${formatDate(startingDate)} to ${formatDate(endingDate)}?</b><br>${lastWeekUl}<br><b>2. What do I plan to do ${weekOrDay2}?</b><br>${nextWeekUl}<br><b>3. What is blocking me from making progress?</b><br>${blockerText}`;
}
// Wait for both subject and body to be available, then inject both
let injected = false;
Expand Down Expand Up @@ -1041,20 +1037,42 @@ function allIncluded(outputTarget = 'email') {
return date.toLocaleDateString('en-US', options);
}

function buildActivityListHtml() {
if (lastWeekArray.length === 0 && reviewedPrsArray.length === 0) {
return '<span style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;">No activity to report for the selected time period.</span>';
}
Comment on lines +1042 to +1044
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same long inline style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;" string is hard-coded in multiple helpers (activity, next-week, blockers). Consider extracting it into a constant or a shared wrapper helper (or a CSS class) to avoid duplication and keep formatting changes centralized.

Copilot uses AI. Check for mistakes.

let activityList = '<ul>';
for (let i = 0; i < lastWeekArray.length; i++) activityList += lastWeekArray[i];
for (let i = 0; i < reviewedPrsArray.length; i++) activityList += reviewedPrsArray[i];
activityList += '</ul>';
return activityList;
}
Comment on lines +1041 to +1051
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding similar no-activity handling for the "next week" section. Currently, if nextWeekArray is empty, the code will render <ul></ul> (lines 1004-1006 and 1061-1063) which provides no user feedback. While the "next week" section represents plans rather than completed activities, an empty state might still benefit from a helpful message like "No plans added yet" or similar to maintain consistency with the improved UX for the activity section.

Copilot uses AI. Check for mistakes.

function buildNextWeekListHtml() {
if (nextWeekArray.length === 0) {
return '<span style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;">No plans added yet.</span>';
}

let nextWeekList = '<ul>';
for (let i = 0; i < nextWeekArray.length; i++) nextWeekList += nextWeekArray[i];
nextWeekList += '</ul>';
return nextWeekList;
}

function buildBlockerTextHtml() {
return `<span style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;">${userReason}</span>`;
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userReason is interpolated directly into an HTML string that later gets injected via innerHTML/email adapter. If userReason can contain user-provided text, this enables HTML/script injection. Escape/encode userReason before inserting it into markup (or inject it as text rather than HTML).

Suggested change
function buildBlockerTextHtml() {
return `<span style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;">${userReason}</span>`;
function escapeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function buildBlockerTextHtml() {
return `<span style="display: inline-block; padding: 0 8px; margin: 0; line-height: 1.2;">${escapeHtml(userReason)}</span>`;

Copilot uses AI. Check for mistakes.
}

function writeScrumBody() {
if (!enableToggle) {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enableToggle is referenced here but it is not defined anywhere in scrumHelper.js (and a repo-wide search only finds it being removed from storage in popup.js). This will throw a ReferenceError when writeScrumBody() runs in the non-email path. Remove this guard or replace it with a locally-defined flag (e.g., read from storage) and a safe check that won’t crash when undefined.

Suggested change
if (!enableToggle) {
let isEnabled = true;
if (typeof enableToggle !== 'undefined' && !enableToggle) {
isEnabled = false;
}
if (!isEnabled) {

Copilot uses AI. Check for mistakes.
scrumGenerationInProgress = false;
return;
}

let lastWeekUl = '<ul>';
for (let i = 0; i < lastWeekArray.length; i++) lastWeekUl += lastWeekArray[i];
for (let i = 0; i < reviewedPrsArray.length; i++) lastWeekUl += reviewedPrsArray[i];
lastWeekUl += '</ul>';

let nextWeekUl = '<ul>';
for (let i = 0; i < nextWeekArray.length; i++) nextWeekUl += nextWeekArray[i];
nextWeekUl += '</ul>';
const lastWeekUl = buildActivityListHtml();
const nextWeekUl = buildNextWeekListHtml();
const blockerText = buildBlockerTextHtml();

const weekOrDay = yesterdayContribution ? 'yesterday' : 'the period';
const weekOrDay2 = 'today';
Expand All @@ -1066,14 +1084,14 @@ ${lastWeekUl}<br>
<b>2. What do I plan to do ${weekOrDay2}?</b><br>
${nextWeekUl}<br>
<b>3. What is blocking me from making progress?</b><br>
${userReason}`;
${blockerText}`;
} else {
content = `<b>1. What did I do from ${formatDate(startingDate)} to ${formatDate(endingDate)}?</b><br>
${lastWeekUl}<br>
<b>2. What do I plan to do ${weekOrDay2}?</b><br>
${nextWeekUl}<br>
<b>3. What is blocking me from making progress?</b><br>
${userReason}`;
${blockerText}`;
}

if (outputTarget === 'popup') {
Expand Down
Loading