mirror of
				https://github.com/Warky-Devs/artemis-kit.git
				synced 2025-10-31 16:13:53 +00:00 
			
		
		
		
	Added openFileLink, formatSecondToTime and timeStringToSeconds
This commit is contained in:
		
							parent
							
								
									bf80e32841
								
							
						
					
					
						commit
						9f5b743e15
					
				
							
								
								
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| { | ||||
|   "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/dom/file_utils.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/dom/file_utils.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | ||||
| import { openFileLink } from "./file_utils"; | ||||
| import { describe, it, expect } from "vitest"; | ||||
| 
 | ||||
| describe("openFileLink", () => { | ||||
|   it("stub test", () => { | ||||
|     const link = "https://example.com"; | ||||
|     openFileLink(link); | ||||
| 
 | ||||
|     const a = document.querySelector("a"); | ||||
|     expect(a).toBeDefined(); | ||||
|   }); | ||||
| }); | ||||
| // describe("openFileLink", () => {
 | ||||
| //   beforeEach(() => {
 | ||||
| //     // Mock the window object
 | ||||
| //     global.window = {
 | ||||
| //       document: {
 | ||||
| //         body: {
 | ||||
| //           appendChild: vi.fn(),
 | ||||
| //           removeChild: vi.fn(),
 | ||||
| //         },
 | ||||
| //         createElement: vi.fn(() => ({
 | ||||
| //           href: "",
 | ||||
| //           download: "",
 | ||||
| //           click: vi.fn(),
 | ||||
| //         })),
 | ||||
| //       },
 | ||||
| //     };
 | ||||
| 
 | ||||
| //     // Create a mock for document.createElement
 | ||||
| //     const createElementMock = vi.fn(() => ({
 | ||||
| //       href: "",
 | ||||
| //       download: "",
 | ||||
| //       click: vi.fn(),
 | ||||
| //     }));
 | ||||
| //     Object.defineProperty(global.window.document, "createElement", {
 | ||||
| //       value: createElementMock,
 | ||||
| //     });
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   afterEach(() => {
 | ||||
| //     // Restore the original window object
 | ||||
| //     delete global.window;
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("creates an anchor element when window is defined", () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     expect(global.window.document.createElement).toHaveBeenCalledTimes(1);
 | ||||
| //     expect(global.window.document.createElement).toHaveBeenCalledWith("a");
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("sets the href attribute of the anchor element correctly", () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     const elem = global.window.document.body.appendChild.mock.calls[0][0];
 | ||||
| //     expect(elem.href).toBe(link);
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("sets the download attribute of the anchor element correctly", () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     const elem = global.window.document.body.appendChild.mock.calls[0][0];
 | ||||
| //     expect(elem.download).toBe("");
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("appends the anchor element to the DOM", () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     expect(global.window.document.body.appendChild).toHaveBeenCalledTimes(1);
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("clicks the anchor element", () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     const elem = global.window.document.body.appendChild.mock.calls[0][0];
 | ||||
| //     expect(elem.click).toHaveBeenCalledTimes(1);
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("removes the anchor element from the DOM after a timeout", async () => {
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     openFileLink(link);
 | ||||
| //     const elem = global.window.document.body.appendChild.mock.calls[0][0];
 | ||||
| //     await new Promise((resolve) => setTimeout(resolve, 2000));
 | ||||
| //     expect(global.window.document.body.removeChild).toHaveBeenCalledTimes(1);
 | ||||
| //     expect(global.window.document.body.removeChild).toHaveBeenCalledWith(elem);
 | ||||
| //   });
 | ||||
| 
 | ||||
| //   it("does not throw an error when window is not defined", () => {
 | ||||
| //     delete global.window;
 | ||||
| //     const link = "https://example.com";
 | ||||
| //     expect(() => openFileLink(link)).not.toThrow();
 | ||||
| //   });
 | ||||
| // });
 | ||||
							
								
								
									
										20
									
								
								src/dom/file_utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/dom/file_utils.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| /** | ||||
|  * Creates an anchor element and initiates a download click on it with a given URL. | ||||
|  * This function is only available on the client side. | ||||
|  * @param link - URL to download | ||||
|  */ | ||||
| export const openFileLink = (link: string) => { | ||||
|   if (typeof window !== "undefined") { | ||||
|     const elem = document.createElement("a"); | ||||
|     elem.href = link; | ||||
|     elem.style.display = "none"; // Hide the element
 | ||||
|     elem.download = ""; // Suggest the browser to download instead of navigating
 | ||||
|     document.body.appendChild(elem); // Attach to the DOM for the click to work
 | ||||
|     elem.click(); | ||||
|     setTimeout(() => { | ||||
|       if (document.body && elem) { | ||||
|         document.body.removeChild(elem); // Clean up the element from the DOM
 | ||||
|       } | ||||
|     }, 2000); | ||||
|   } | ||||
| }; | ||||
							
								
								
									
										1
									
								
								src/dom/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/dom/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| export * from "./file_utils"; | ||||
| @ -5,3 +5,4 @@ export * from "./promise"; | ||||
| export * from "./i18n"; | ||||
| export * from "./dataqueue"; | ||||
| //export * from './logger'
 | ||||
| export * from "./dom"; | ||||
|  | ||||
| @ -5,3 +5,4 @@ export * from "./locale"; | ||||
| export * from "./fileSize"; | ||||
| export * from "./legacy"; | ||||
| export * from "./uuid"; | ||||
| export * from "./time"; | ||||
|  | ||||
							
								
								
									
										52
									
								
								src/strings/time.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/strings/time.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| import { describe, it, expect } from "vitest"; | ||||
| import { formatSecondToTime } from "./time"; | ||||
| 
 | ||||
| describe("formatSecondToTime", () => { | ||||
|   it("formats time with hours", () => { | ||||
|     expect(formatSecondToTime(3661)).toBe("01:01:01"); | ||||
|   }); | ||||
| 
 | ||||
|   it("formats time without hours", () => { | ||||
|     expect(formatSecondToTime(61)).toBe("01:01"); | ||||
|   }); | ||||
| 
 | ||||
|   it("formats time with zero seconds", () => { | ||||
|     expect(formatSecondToTime(3600)).toBe("01:00:00"); | ||||
|   }); | ||||
| 
 | ||||
|   it("formats time with zero minutes and seconds", () => { | ||||
|     expect(formatSecondToTime(0)).toBe("00:00"); | ||||
|   }); | ||||
| 
 | ||||
|   it("handles negative input", () => { | ||||
|     expect(formatSecondToTime(-1)).toBe("-00:01"); | ||||
|   }); | ||||
| 
 | ||||
|   it("handles decimal input", () => { | ||||
|     expect(formatSecondToTime(1.5)).toBe("00:01"); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| import { timeStringToSeconds } from "./time"; | ||||
| 
 | ||||
| describe("timeStringToSeconds", () => { | ||||
|   it("converts valid time strings in HH:MM:SS format", () => { | ||||
|     expect(timeStringToSeconds("01:02:03")).toBe(3723); | ||||
|     expect(timeStringToSeconds("12:34:56")).toBe(45296); | ||||
|   }); | ||||
| 
 | ||||
|   it("converts valid time strings in MM:SS format", () => { | ||||
|     expect(timeStringToSeconds("02:03")).toBe(123); | ||||
|     expect(timeStringToSeconds("34:56")).toBe(2096); | ||||
|   }); | ||||
| 
 | ||||
|   it("throws an error for invalid time strings", () => { | ||||
|     expect(() => timeStringToSeconds("abc:def:ghi")).toThrowError(); | ||||
|     expect(() => timeStringToSeconds("12:34:56:78")).toThrowError(); | ||||
|   }); | ||||
| 
 | ||||
|   it("handles edge cases", () => { | ||||
|     expect(timeStringToSeconds("00:00:00")).toBe(0); | ||||
|     expect(timeStringToSeconds("23:59:59")).toBe(86399); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										69
									
								
								src/strings/time.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/strings/time.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | ||||
| /** | ||||
|  * Format a time in seconds to a string. | ||||
|  * | ||||
|  * @param totalSeconds time in seconds | ||||
|  * @returns a string in the format HH:MM:SS or MM:SS if hours are zero | ||||
|  */ | ||||
| export function formatSecondToTime(totalSeconds: number): string { | ||||
|   const prefix = totalSeconds < 0 ? "-" : ""; | ||||
|   totalSeconds = Math.abs(Math.floor(totalSeconds)); | ||||
| 
 | ||||
|   const minutes = Math.floor((totalSeconds % 3600) / 60); | ||||
|   const hours = Math.floor(totalSeconds / 3600); | ||||
|   const seconds = totalSeconds % 60; | ||||
| 
 | ||||
|   if (hours > 0) { | ||||
|     return `${prefix}${hours.toString().padStart(2, "0")}:${minutes | ||||
|       .toString() | ||||
|       .padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
 | ||||
|   } | ||||
| 
 | ||||
|   return `${prefix}${minutes.toString().padStart(2, "0")}:${seconds | ||||
|     .toString() | ||||
|     .padStart(2, "0")}`;
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Converts a time string in the format HH:MM:SS or MM:SS to a total number of seconds. | ||||
|  * | ||||
|  * @param timeStr - a string in the format HH:MM:SS or MM:SS | ||||
|  * @returns the total number of seconds | ||||
|  */ | ||||
| export function timeStringToSeconds(timeStr: string): number { | ||||
|   // Validate input is not empty
 | ||||
|   if (!timeStr || !timeStr.trim()) { | ||||
|     throw new Error("Time string cannot be empty"); | ||||
|   } | ||||
| 
 | ||||
|   const parts = timeStr.split(":"); | ||||
|   if (parts.length < 2 || parts.length > 3) { | ||||
|     throw new Error("Invalid time format. Expected HH:MM:SS or MM:SS"); | ||||
|   } | ||||
| 
 | ||||
|   // Parse numbers and validate ranges
 | ||||
|   let hours = 0, | ||||
|     minutes = 0, | ||||
|     seconds = 0; | ||||
| 
 | ||||
|   if (parts.length === 3) { | ||||
|     // HH:MM:SS format
 | ||||
|     [hours, minutes, seconds] = parts.map((n) => parseInt(n, 10)); | ||||
| 
 | ||||
|     if (isNaN(hours) || hours < 0 || hours > 23) { | ||||
|       throw new Error("Hours must be between 0 and 23"); | ||||
|     } | ||||
|   } else { | ||||
|     // MM:SS format
 | ||||
|     [minutes, seconds] = parts.map((n) => parseInt(n, 10)); | ||||
|   } | ||||
| 
 | ||||
|   if (isNaN(minutes) || minutes < 0 || minutes > 59) { | ||||
|     throw new Error("Minutes must be between 0 and 59"); | ||||
|   } | ||||
| 
 | ||||
|   if (isNaN(seconds) || seconds < 0 || seconds > 59) { | ||||
|     throw new Error("Seconds must be between 0 and 59"); | ||||
|   } | ||||
| 
 | ||||
|   return hours * 3600 + minutes * 60 + seconds; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user