neuroread/lib/utils.ts

58 lines
1.7 KiB
TypeScript

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { visit } from "unist-util-visit";
import { VFile } from "vfile";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export async function detectWebGPU() {
try {
const adapter = await navigator.gpu.requestAdapter();
return !!adapter;
} catch (e) {
return false;
}
}
/**
* A custom rehype plugin that wraps the first occurrence of "textToHighlight" in a <mark> tag.
* options: { textToHighlight: string }
*/
export default function rehypeHighlight(options: { textToHighlight: string }) {
return (tree: any, file: VFile) => {
let found = false;
visit(tree, "text", (node: any) => {
if (found) return;
const { value } = node;
const text = options.textToHighlight;
const index = value.toLowerCase().indexOf(text.toLowerCase());
if (index !== -1) {
found = true;
// Split the text into three parts: before, match, and after.
const before = value.slice(0, index);
const match = value.slice(index, index + text.length);
const after = value.slice(index + text.length);
// Replace the current node with three nodes.
node.type = "element";
node.tagName = "span";
node.properties = {};
node.children = [];
if (before) {
node.children.push({ type: "text", value: before });
}
node.children.push({
type: "element",
tagName: "mark",
properties: { style: "background-color: yellow;" },
children: [{ type: "text", value: match }],
});
if (after) {
node.children.push({ type: "text", value: after });
}
}
});
};
}