Repository navigation
Conversation
… README with installation instructions
Reviewer's GuideAdds and publishes a Google Calendar Multi-Day Grid Viewer userscript that observes Calendar’s DOM, derives multi-day event timing and placement, renders clickable hourly-grid clones, and rebuilds efficiently; the PR also adds its build automation, documentation, and issue templates. Sequence diagram for Google Calendar multi-day event renderingsequenceDiagram
participant Calendar as Google_Calendar_DOM
participant Observer as MutationObserver
participant Processor as processCalendar
participant Grid as Hourly_Grid
Calendar->>Observer: DOM mutation
Observer->>Processor: processCalendar()
Processor->>Processor: buildFingerprint()
alt structural change detected
Processor->>Processor: extractTimes()
Processor->>Grid: append gcal-multiday-clone
Processor->>Grid: copy event delegation attributes
else no structural change
Processor-->>Observer: skip rebuild
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again. |
There was a problem hiding this comment.
Hey - I've found 5 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="google_calendar/core/observer.js" line_range="19" />
<code_context>
+
+export function setupObserver() {
+ log('Setting up MutationObserver...');
+ const observer = new MutationObserver(() => {
+ if (debounceTimer) clearTimeout(debounceTimer);
+ debounceTimer = setTimeout(() => {
+ // Pause observing while we mutate the DOM ourselves
+ observer.disconnect();
+ processCalendar();
+ // Resume observing
+ observer.observe(document.body, { childList: true, subtree: true });
+ }, 500);
+ });
+
+ observer.observe(document.body, { childList: true, subtree: true });
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** setupObserver only registers a MutationObserver and never calls processCalendar initially, so a calendar that is already settled when the userscript runs at document-idle gets no clones until an unrelated DOM mutation occurs.
**Triggers:** When Google Calendar finishes rendering before the userscript installs the observer and performs no subsequent child-list mutation.
**Suggested fix:** Call processCalendar once during setup, then install the observer for later changes.
```suggestion
processCalendar();
observer.observe(document.body, { childList: true, subtree: true });
```
</issue_to_address>
### Comment 2
<location path="google_calendar/core/dom.js" line_range="144" />
<code_context>
+
+ // Only rebuild clones when the calendar actually changed (navigation, event add/remove).
+ // Skip rebuilds caused by clicks, popovers, hover effects, etc.
+ const fingerprint = buildFingerprint(allDayChips, gridColumns);
+ if (fingerprint === lastFingerprint && document.querySelector('.gcal-multiday-clone')) {
+ log('Skipping rebuild — no structural change detected.');
+ return;
+ }
+ lastFingerprint = fingerprint;
</code_context>
<issue_to_address>
**issue (broader_impact):** The fingerprint contains only column date keys and event IDs, so layout changes that preserve the same calendar structure leave existing clones at their old positions, heights, and text offsets. Browser resizing, zoom changes, or Google Calendar layout recalculation therefore displays stale clone geometry.
**Triggers:** When the calendar is resized or its column dimensions change without changing date keys or event IDs.
**Suggested fix:** Include the relevant column/chip geometry in the rebuild trigger or use a ResizeObserver to recalculate clones after layout changes.
```suggestion
const fingerprint = [
buildFingerprint(allDayChips, gridColumns),
Array.from(gridColumns).map(column => {
const rect = column.getBoundingClientRect();
return `${rect.left},${rect.top},${rect.width},${rect.height}`;
}).join(';'),
Array.from(allDayChips)
.filter(chip => !chip.classList.contains('gcal-multiday-clone'))
.map(chip => {
const rect = chip.getBoundingClientRect();
return `${rect.left},${rect.top},${rect.width},${rect.height}`;
})
.join(';')
].join('::');
```
</issue_to_address>
### Comment 3
<location path="google_calendar/core/dom.js" line_range="176-179" />
<code_context>
+ if (!chip.style.width || !chip.style.width.includes('%')) return;
+
+ const widthPct = parseFloat(chip.style.width) || 14.28;
+ const daysSpan = Math.round(widthPct / 14.28);
+ const leftPct = parseFloat(chip.style.left) || 0;
+ const startDayIndex = Math.round(leftPct / 14.28);
+
+ if (daysSpan > 1) {
</code_context>
<issue_to_address>
**issue (bug_risk):** daysSpan and startDayIndex are calculated using a hard-coded 14.28% per day, so non-seven-day views such as Google Calendar's five-day work-week view calculate incorrect spans and column indices. Multi-day events are consequently skipped or rendered in the wrong columns.
**Triggers:** When the user uses a five-day, four-day, or another non-seven-column calendar view.
**Suggested fix:** Derive the per-day width from the actual grid column count or from the chip and column geometry instead of assuming seven equal columns.
```suggestion
const dayWidthPct = 100 / gridColumns.length;
const widthPct = parseFloat(chip.style.width) || dayWidthPct;
const daysSpan = Math.round(widthPct / dayWidthPct);
const leftPct = parseFloat(chip.style.left) || 0;
const startDayIndex = Math.round(leftPct / dayWidthPct);
```
</issue_to_address>
### Comment 4
<location path="google_calendar/core/dom.js" line_range="181-183" />
<code_context>
+ const leftPct = parseFloat(chip.style.left) || 0;
+ const startDayIndex = Math.round(leftPct / 14.28);
+
+ if (daysSpan > 1) {
+ if (config.hideOriginals) {
+ chip.style.opacity = '0.4';
+ }
+
</code_context>
<issue_to_address>
**issue (bug_risk):** The code sets a multi-day chip's opacity to 0.4 when hideOriginals is enabled but never restores the original opacity when the setting is later disabled or the event no longer qualifies as multi-day, leaving the original event permanently dimmed for the rest of the page lifetime.
**Triggers:** When gcal-hide-original is changed from true to false, or an existing event changes from multi-day to a non-multi-day event.
**Suggested fix:** Explicitly restore the chip's original or default opacity when hideOriginals is false and when a chip is no longer converted.
</issue_to_address>
### Comment 5
<location path=".github/workflows/google-calendar.yml" line_range="22" />
<code_context>
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+
+ steps:
</code_context>
<issue_to_address>
**🚨 issue (security):** The pull_request workflow executes repository-controlled installation/build commands while requesting contents: write, so a pull request can modify package lifecycle scripts or the build command and run arbitrary code with a write-capable GITHUB_TOKEN.
**Triggers:** When an untrusted contributor can submit a pull request branch in the repository.
**Suggested fix:** Run pull-request builds with read-only permissions and make the dist commit/push a separate push-only job; do not execute untrusted pull-request code with write access.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 5 findings to address first, and the new pull-request workflow grants contents: write while executing repository-controlled npm and build code, so a malicious or mistaken change could push arbitrary repository modifications or expose the write-capable token; those effects are not fully undone by reverting this PR. The userscript itself is ordinary reversible UI behavior, but this CI trust-boundary change needs human review.
Blocking findings: google_calendar/core/observer.js:19, google_calendar/core/dom.js:144, google_calendar/core/dom.js:179, google_calendar/core/dom.js:183, .github/workflows/google-calendar.yml:22
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const widthPct = parseFloat(chip.style.width) || 14.28; | ||
| const daysSpan = Math.round(widthPct / 14.28); | ||
| const leftPct = parseFloat(chip.style.left) || 0; | ||
| const startDayIndex = Math.round(leftPct / 14.28); |
There was a problem hiding this comment.
issue (bug_risk): daysSpan and startDayIndex are calculated using a hard-coded 14.28% per day, so non-seven-day views such as Google Calendar's five-day work-week view calculate incorrect spans and column indices. Multi-day events are consequently skipped or rendered in the wrong columns.
Triggers: When the user uses a five-day, four-day, or another non-seven-column calendar view.
Suggested fix: Derive the per-day width from the actual grid column count or from the chip and column geometry instead of assuming seven equal columns.
| const widthPct = parseFloat(chip.style.width) || 14.28; | |
| const daysSpan = Math.round(widthPct / 14.28); | |
| const leftPct = parseFloat(chip.style.left) || 0; | |
| const startDayIndex = Math.round(leftPct / 14.28); | |
| const dayWidthPct = 100 / gridColumns.length; | |
| const widthPct = parseFloat(chip.style.width) || dayWidthPct; | |
| const daysSpan = Math.round(widthPct / dayWidthPct); | |
| const leftPct = parseFloat(chip.style.left) || 0; | |
| const startDayIndex = Math.round(leftPct / dayWidthPct); |
| if (daysSpan > 1) { | ||
| if (config.hideOriginals) { | ||
| chip.style.opacity = '0.4'; |
There was a problem hiding this comment.
issue (bug_risk): The code sets a multi-day chip's opacity to 0.4 when hideOriginals is enabled but never restores the original opacity when the setting is later disabled or the event no longer qualifies as multi-day, leaving the original event permanently dimmed for the rest of the page lifetime.
Triggers: When gcal-hide-original is changed from true to false, or an existing event changes from multi-day to a non-multi-day event.
Suggested fix: Explicitly restore the chip's original or default opacity when hideOriginals is false and when a chip is no longer converted.
| build: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write |
There was a problem hiding this comment.
🚨 issue (security): The pull_request workflow executes repository-controlled installation/build commands while requesting contents: write, so a pull request can modify package lifecycle scripts or the build command and run arbitrary code with a write-capable GITHUB_TOKEN.
Triggers: When an untrusted contributor can submit a pull request branch in the repository.
Suggested fix: Run pull-request builds with read-only permissions and make the dist commit/push a separate push-only job; do not execute untrusted pull-request code with write access.
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
|
👋 nihaltp your PR is conflicting and needs to be updated to be merged |
Summary by Sourcery
Add a Google Calendar userscript for rendering multi-day events in the hourly grid and automate its build and support workflow.
New Features:
Enhancements:
Build:
CI:
Documentation: