diff --git a/app/providers.tsx b/app/providers.tsx index 6742e48..db08246 100644 --- a/app/providers.tsx +++ b/app/providers.tsx @@ -1,5 +1,6 @@ "use client"; +import { uwuifyDocument } from "@/lib/uwuify"; import { ThemeProvider, useTheme } from "next-themes"; import { type ReactNode, useEffect } from "react"; @@ -27,10 +28,31 @@ function ThemeWatcher() { return null; } +function UwuWatcher() { + // Uwuify the whole page when ctrl + u is pressed + useEffect(() => { + function onKeyDown(event: KeyboardEvent) { + if (event.key === "u" && (event.metaKey || event.ctrlKey)) { + event.preventDefault(); + uwuifyDocument(); + } + } + + window.addEventListener("keydown", onKeyDown); + + return () => { + window.removeEventListener("keydown", onKeyDown); + }; + }, []); + + return null; +} + export function Providers({ children }: { children: ReactNode }) { return ( + {children} ); diff --git a/bun.lock b/bun.lock index 4b1d5a4..6955f4b 100644 --- a/bun.lock +++ b/bun.lock @@ -39,6 +39,7 @@ "typescript": "^5.8.3", "unist-util-filter": "^5.0.1", "unist-util-visit": "^5.0.0", + "uwuifier": "^4.2.2", "zustand": "^5.0.3", }, "devDependencies": { @@ -835,6 +836,8 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "uwuifier": ["uwuifier@4.2.2", "", {}, "sha512-Fhtj3Yg3rrDTEs+L1fqkgM3VYGJrP4U9GY+4fPdw08T5kzOB8NSosZnZfa5Zhv1Hh7NCpH5G6t1DIZyM1wPK1w=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="], diff --git a/lib/uwuify.ts b/lib/uwuify.ts new file mode 100644 index 0000000..e7fbe16 --- /dev/null +++ b/lib/uwuify.ts @@ -0,0 +1,36 @@ +import Uwuifier from "uwuifier"; + +const uwuifier = new Uwuifier(); + +const getAllDOMTextNodes = (): Node[] => { + const walker = document.createTreeWalker( + document.body, + NodeFilter.SHOW_TEXT, + null, + ); + + const nodes: Node[] = []; + + while (true) { + const newNode = walker.nextNode(); + + if (!newNode) { + break; + } + + nodes.push(newNode); + } + + return nodes; +}; + +export const uwuifyDocument = (): void => { + const textNodes = getAllDOMTextNodes(); + + for (const node of textNodes) { + if (node.nodeValue) { + const newText = uwuifier.uwuifySentence(node.nodeValue); + node.nodeValue = newText; + } + } +}; diff --git a/package.json b/package.json index 15e4046..481b0fa 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "typescript": "^5.8.3", "unist-util-filter": "^5.0.1", "unist-util-visit": "^5.0.0", + "uwuifier": "^4.2.2", "zustand": "^5.0.3" }, "devDependencies": {