diff --git a/package.json b/package.json index 052c5a6..0317d72 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.3.0", "@types/node": "^24.0.10", + "@types/pako": "^2.0.3", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^4.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 223bb6e..141b824 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,6 +99,9 @@ importers: '@types/node': specifier: ^24.0.10 version: 24.0.13 + '@types/pako': + specifier: ^2.0.3 + version: 2.0.3 '@types/react': specifier: ^19.1.8 version: 19.1.8 @@ -1059,6 +1062,9 @@ packages: '@types/node@24.0.13': resolution: {integrity: sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==} + '@types/pako@2.0.3': + resolution: {integrity: sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==} + '@types/react-dom@19.1.6': resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: @@ -3791,6 +3797,8 @@ snapshots: dependencies: undici-types: 7.8.0 + '@types/pako@2.0.3': {} + '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: '@types/react': 19.1.8 diff --git a/src/app/course/[courseName]/calendar/CourseCalendar.tsx b/src/app/course/[courseName]/calendar/CourseCalendar.tsx index 5a230b1..282aee5 100644 --- a/src/app/course/[courseName]/calendar/CourseCalendar.tsx +++ b/src/app/course/[courseName]/calendar/CourseCalendar.tsx @@ -45,10 +45,10 @@ export default function CourseCalendar() { className=" min-h-0 flex-grow - border-4 + border-2 border-gray-900 rounded-lg - bg-slate-950 + bg-slate-950/70 sm:p-1 " > diff --git a/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/AssignmentPreview.tsx b/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/AssignmentPreview.tsx index 1168183..b3bc407 100644 --- a/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/AssignmentPreview.tsx +++ b/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/AssignmentPreview.tsx @@ -2,6 +2,7 @@ import MarkdownDisplay from "@/components/MarkdownDisplay"; import { LocalAssignment } from "@/models/local/assignment/localAssignment"; import { rubricItemIsExtraCredit } from "@/models/local/assignment/rubricItem"; import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPointsUtils"; +import { formatHumanReadableDate } from "@/services/utils/dateFormat"; import React, { Fragment } from "react"; export default function AssignmentPreview({ @@ -19,11 +20,15 @@ export default function AssignmentPreview({
Due Date
-
{assignment.dueAt}
+
+ {formatHumanReadableDate(assignment.dueAt)} +
Lock Date
-
{assignment.lockAt}
+
+ {assignment.lockAt && formatHumanReadableDate(assignment.lockAt)} +
Assignment Group Name
diff --git a/src/app/course/[courseName]/modules/[moduleName]/page/[pageName]/EditPageHeader.tsx b/src/app/course/[courseName]/modules/[moduleName]/page/[pageName]/EditPageHeader.tsx index 352c534..3b765d4 100644 --- a/src/app/course/[courseName]/modules/[moduleName]/page/[pageName]/EditPageHeader.tsx +++ b/src/app/course/[courseName]/modules/[moduleName]/page/[pageName]/EditPageHeader.tsx @@ -14,14 +14,14 @@ export default function EditPageHeader({ return (
{courseName} -
{pageName}
+
{pageName}
); } diff --git a/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuizHeader.tsx b/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuizHeader.tsx index 7244f8e..0b0857e 100644 --- a/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuizHeader.tsx +++ b/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuizHeader.tsx @@ -14,7 +14,7 @@ export default function EditQuizHeader({ return (
diff --git a/src/services/htmlMarkdownUtils.ts b/src/services/htmlMarkdownUtils.ts index ed3209c..d737f21 100644 --- a/src/services/htmlMarkdownUtils.ts +++ b/src/services/htmlMarkdownUtils.ts @@ -1,9 +1,34 @@ "use client"; -import { marked } from "marked"; +import { marked, MarkedExtension } from "marked"; import DOMPurify from "isomorphic-dompurify"; import { LocalCourseSettings } from "@/models/local/localCourseSettings"; import markedKatex from "marked-katex-extension"; +const mermaidExtension = { + name: "mermaid", + level: "block" as const, + start(src: string) { + return src.indexOf("```mermaid"); + }, + tokenizer(src: string) { + const rule = /^```mermaid\n([\s\S]+?)```(?:\n|$)/; + const match = rule.exec(src); + if (match) { + return { + type: "mermaid", + raw: match[0], + text: match[1].trim(), + }; + } + }, + renderer(token: { text: string }) { + const base64 = btoa(token.text); + const url = `https://mermaid.ink/img/${base64}?type=png` + console.log(token.text, url); + return `Mermaid diagram`; + }, +}; + marked.use( markedKatex({ throwOnError: false, @@ -11,6 +36,8 @@ marked.use( }) ); +marked.use({ extensions: [mermaidExtension] }); + export function extractImageSources(htmlString: string) { const srcUrls = []; const regex = /]+src=["']?([^"'>]+)["']?/g; @@ -22,6 +49,7 @@ export function extractImageSources(htmlString: string) { return srcUrls; } + export function convertImagesToCanvasImages( html: string, settings: LocalCourseSettings @@ -37,7 +65,9 @@ export function convertImagesToCanvasImages( for (const imageSrc of imageSources) { const destinationUrl = imageLookup[imageSrc]; if (typeof destinationUrl === "undefined") { - console.log(`No image in settings for ${imageSrc}, do you have NEXT_PUBLIC_ENABLE_FILE_SYNC=true in your settings?`) + console.log( + `No image in settings for ${imageSrc}, do you have NEXT_PUBLIC_ENABLE_FILE_SYNC=true in your settings?` + ); } // could error check here, but better to just not display an image... // if (typeof destinationUrl === "undefined") { diff --git a/src/services/utils/dateFormat.ts b/src/services/utils/dateFormat.ts new file mode 100644 index 0000000..e63476c --- /dev/null +++ b/src/services/utils/dateFormat.ts @@ -0,0 +1,15 @@ +export function formatHumanReadableDate(date: Date | string): string { + const d = typeof date === "string" ? new Date(date) : date; + if (isNaN(d.getTime())) return "Invalid date"; + + const options: Intl.DateTimeFormatOptions = { + weekday: "short", + // year: "numeric", + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + }; + + return d.toLocaleString(undefined, options); +}