Skip to content

About

An extension to help organize your assignments, quizzes, HW-s, midterms etc.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“… ToCalendar

An automated Chrome extension that extracts course deadlines, quizzes, and exams from Canvas LMS into iCal (.ics) and Google Calendar (.csv) β€” built because freshman-year time management was chaotic.

Manifest V3 JavaScript ES6+ Canvas LMS Exports License MIT


πŸ“– Why This Exists

When I first arrived at college, time management was an uphill battle. With multiple computer science, engineering, and math classes, assignments and exam dates were scattered everywhere: tucked inside syllabi PDFs, nested within Canvas module trees, buried in weekly announcements, or hidden across assignment tabs. Keeping track of what was due and when felt overwhelming without a unified, consolidated calendar view.

The idea behind ToCalendar was simple:

What if an extension could navigate through your enrolled course tabs, heuristically parse out every deadline, quiz, and midterm, and give you a one-click export into Apple Calendar or Google Calendar?

The Plot Twist πŸ’‘

While building the extensionβ€”wrestling with dynamic SPA rendering, complex DOM trees, and professors' wildly inconsistent date formatsβ€”I stumbled across an unexpected discovery: Canvas already had a built-in calendar view and a hidden Webcal/iCal subscription feed URL in the sidebar!

Finding that out was both hilarious and humbling. Between that realization and the edge cases inherent in client-side heuristic web scraping, I paused active development on the extension. However, building it was a great hands-on journey in browser extension architecture, asynchronous BFS crawling, DOM parsing heuristics, and calendar formatting standards.


✨ Key Features

  • πŸ”„ In-Tab Autonomous Crawler: Recursively explores course links on the same host up to a configurable depth to discover deadline information across modules and syllabus pages.
  • 🧠 Heuristic Date & Category Detection:
    • Automatically identifies coursework categories (Homework, Quizzes, Midterms, Exams, Labs, Projects).
    • Extracts course codes (e.g., CSE 2231, ENGR 1181).
    • Robust regex patterns support multiple date formats (ISO, US standard MM/DD/YYYY, and month-day strings).
  • ⚑ Composite Hash Deduplication: Prevents duplicate calendar events when assignments are linked repeatedly across course overview tables and module lists.
  • πŸ“† Dual Calendar Export Engine:
    • iCalendar (.ics): RFC 5545 compliant export with local floating time events for Apple Calendar, Google Calendar, and Microsoft Outlook.
    • Google Calendar CSV (.csv): Formatted with standard Google Calendar import columns (Subject, Start Date, Start Time, End Date, End Time, Description, Location) and directly readable in Excel and Google Sheets.
  • 🎨 Minimal Popup Dashboard: Real-time progress telemetry (pages visited, queue size, items extracted) with responsive light and dark theme support.

πŸ›οΈ Architecture

                       ToCalendar Extension Architecture
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚                                                                        β”‚
 β”‚  Popup Layer (UI)                  Background Service Worker           β”‚
 β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
 β”‚  β”‚ popup.html / style.css  │◀─────▢│ background.js (Service Worker) β”‚  β”‚
 β”‚  β”‚ β€’ Crawl triggers        β”‚       β”‚ β€’ BFS Crawl Queue Manager      β”‚  β”‚
 β”‚  β”‚ β€’ Live status telemetry β”‚       β”‚ β€’ Headless Tab Navigation      β”‚  β”‚
 β”‚  β”‚ β€’ .ics / .csv Exporters β”‚       β”‚ β€’ Script Injection Controller  β”‚  β”‚
 β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
 β”‚                β”‚                                  β”‚                    β”‚
 β”‚                β–Ό                                  β–Ό                    β”‚
 β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
 β”‚  β”‚ chrome.storage.local    │◀──────│ content.js (Injected Scraper)  β”‚  β”‚
 β”‚  β”‚ β€’ Cached deadline rows  β”‚       β”‚ β€’ Text Node Heuristic Filter   β”‚  β”‚
 β”‚  β”‚ β€’ Deduplicated items    β”‚       β”‚ β€’ Date & Category Regex Engine β”‚  β”‚
 β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚ β€’ Link Discovery (Same-Origin) β”‚  β”‚
 β”‚                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                     β–Ό
                                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                        β”‚ Canvas LMS DOM          β”‚
                                        β”‚ (Courses / Syllabi / HW)β”‚
                                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ Data Flow & Scraping Pipeline

User opens extension popup on Canvas course page
  β”‚
  β”œβ”€β”€β–Ά popup.js triggers START_CRAWL with current tab URL
  β”‚      β”‚
  β”‚      β–Ό
  β”œβ”€β”€β–Ά background.js initializes BFS queue (maxPages: 30, maxDepth: 3)
  β”‚      β”‚
  β”‚      β”œβ”€β”€ Spawns background tab on course domain
  β”‚      β”œβ”€β”€ Injects content.js via chrome.scripting.executeScript
  β”‚      β”‚
  β”‚      β–Ό
  β”œβ”€β”€β–Ά content.js scans DOM for deadline indicators & date patterns
  β”‚      β”‚
  β”‚      β”œβ”€β”€ Filters nodes matching DUE_HINT and DATE_REGEXES
  β”‚      β”œβ”€β”€ Guesses item title, course code, and category
  β”‚      β”œβ”€β”€ Collects next-page course links (assignments, quizzes, modules)
  β”‚      β”‚
  β”‚      β–Ό
  β”œβ”€β”€β–Ά background.js receives SCRAPE_PAGE response
  β”‚      β”‚
  β”‚      β”œβ”€β”€ Dispatches CRAWL_PROGRESS events to popup UI
  β”‚      β”œβ”€β”€ Deduplicates items via signature hash
  β”‚      └── Persists aggregated rows to chrome.storage.local
  β”‚
  β–Ό
User exports calendar
  β”œβ”€β”€ "Export iCal (.ics)"  ──▢ Generates RFC 5545 VCALENDAR blob
  └── "Export CSV (.csv)"   ──▢ Generates Google Calendar CSV blob

βš™οΈ Heuristic Extraction Engine

1. Date Pattern Recognition

Pattern Name Regular Expression Example Match
Month Name + Day \b(Jan|Feb|Mar...)\s+\d{1,2}(?:,\s*\d{4})?... Sep 15, 2025 11:59 PM
ISO 8601 \b\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}(?::\d{2})?)?\b 2025-10-24 23:59:00
US Standard \b\d{1,2}\/\d{1,2}\/\d{2,4}(?:\s+\d{1,2}:\d{2}\s*(AM|PM)?)?\b 11/04/2025 5:00 PM
Verbose Syllabus \b(Mon|Tue...),\s*\d{1,2}\s+(Jan|Feb...)\s+\d{4}...\b Mon, 03 Nov 2025 14:00

2. Category Classification

Detected Category Matched Keywords in Context
Homework hw, homework
Quiz quiz
Exam exam, test, midterm
Project project, lab, report, paper
Assignment assignment (or fallback)

3. Deduplication Signature

To ensure identical deadlines posted across multiple module views do not clutter the calendar, items are deduplicated using a unique signature key:

const key = `${item.title}__${parts.year}-${parts.month}-${parts.day}__${parts.hour}:${parts.minute}`;

πŸ”Œ Chrome Extension APIs Used

Chrome API Purpose in ToCalendar
chrome.tabs Queries active tab, spawns off-screen tabs for background crawling, and handles page updates
chrome.scripting Injects content.js dynamically into course pages as the crawler navigates
chrome.storage.local Caches discovered deadlines and maintains state between popup open/close cycles
chrome.runtime Coordinates inter-script message passing (START_CRAWL, CRAWL_PROGRESS, CRAWL_DONE, SCRAPE_PAGE)

πŸ’» Tech Stack

Layer Technology Purpose
Extension Platform Chrome Manifest V3 Extension framework, permissions, and service worker lifecycle
Language Vanilla JavaScript (ES6+) Dependency-free execution, zero build step required
User Interface HTML5 / CSS3 Clean popup interface with automatic dark/light mode
Calendar Standard RFC 5545 (.ics) Standard iCalendar format for Apple Calendar, Outlook, and Google Calendar
Spreadsheet Standard RFC 4180 (.csv) Standard Google Calendar import format and Excel/Sheets data

πŸ“ Project Structure

ToCalendar/
β”œβ”€β”€ manifest.json              # Manifest V3 extension configuration & permissions
β”œβ”€β”€ background.js              # Service worker managing BFS crawl queue & tab navigation
β”œβ”€β”€ content.js                 # Injected scraper for DOM text nodes, heuristics, and links
β”œβ”€β”€ popup.html                 # Extension popup interface
β”œβ”€β”€ popup.js                   # Popup state manager, crawler listener, and export builders
β”œβ”€β”€ style.css                  # Popup styling with responsive dark mode support
β”œβ”€β”€ icons/                     # Extension branding icons
β”‚   └── Screenshot ...png      # Extension icon asset
β”œβ”€β”€ .gitignore                 # Excludes macOS metadata, logs, and backup archives
β”œβ”€β”€ LICENSE                    # MIT License
└── README.md                  # Project documentation & architecture overview

πŸš€ Installation & Usage

Running Locally in Chrome

  1. Clone the repository:

    git clone https://github.com/KadyrovAkram/ToCalendar.git
    cd ToCalendar
  2. Open Chrome Extensions:

    • Navigate to chrome://extensions in Google Chrome.
    • Toggle Developer mode on (top-right corner).
  3. Load the Extension:

    • Click Load unpacked (top-left corner).
    • Select the cloned ToCalendar folder.
  4. Extract Deadlines:

    • Navigate to your Canvas LMS portal (e.g., your course home page).
    • Click the ToCalendar icon in your browser toolbar.
    • The crawler will automatically begin scanning course tabs.
    • Click Export iCal (.ics) or Export CSV (.csv) to download your deadlines.

πŸ” Engineering Lessons & Challenges

  1. SPA Asynchronous Hydration: Single-page applications like Canvas dynamically mount components via client-side JavaScript. Scraping immediately upon page load often resulted in blank or partial reads, necessitating deliberate rendering delay pauses.
  2. Heuristic Specificity vs. Recall: Natural language dates in freeform syllabus pages lack consistent markup. Loose regex matching captured irrelevant dates (such as lecture release dates), while strict regex missed assignments formatted with non-standard abbreviations.
  3. Local Floating Time vs. UTC: Academic deadlines are tied to the local timezone of the institution. Exporting .ics timestamps as "floating local time" (without hardcoded UTC offsets) ensured deadlines did not shift incorrectly across daylight saving time boundaries.
  4. Native Feeds vs. Screen Scraping: This project served as a prime lesson in API designβ€”while scraping was a great exercise, native calendar feeds (webcal://) provide vastly superior reliability and real-time synchronization.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with β˜• by Ekremzhan Kadyrov

About

An extension to help organize your assignments, quizzes, HW-s, midterms etc.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages