diff --git a/packages/widgets/src/notebook/component.tsx b/packages/widgets/src/notebook/component.tsx
index e8dc77498..b8ef2191b 100644
--- a/packages/widgets/src/notebook/component.tsx
+++ b/packages/widgets/src/notebook/component.tsx
@@ -1,33 +1,38 @@
"use client";
import dynamic from "next/dynamic";
+import { useEffect, useState } from "react";
import { useScopedI18n } from "@homarr/translation/client";
import { WidgetMobileSummary } from "../common/mobile-summary";
import type { WidgetComponentProps } from "../definition";
+import { extractNotebookExcerpt } from "./mobile-summary";
const Notebook = dynamic(() => import("./notebook").then((module) => module.Notebook), {
ssr: false,
});
+interface NotebookMobileSummaryProps {
+ content: string;
+ label: string;
+}
+
+const NotebookMobileSummary = ({ content, label }: NotebookMobileSummaryProps) => {
+ const [excerpt, setExcerpt] = useState("");
+
+ useEffect(() => {
+ setExcerpt(extractNotebookExcerpt(content));
+ }, [content]);
+
+ return
Still visible
'; + + expect(extractNotebookExcerpt(content)).toBe("Visible Still visible"); + }); + + test("returns an empty excerpt when there is no visible content", () => { + expect(extractNotebookExcerpt("")).toBe(""); + }); +}); diff --git a/packages/widgets/src/notebook/mobile-summary.ts b/packages/widgets/src/notebook/mobile-summary.ts new file mode 100644 index 000000000..dc935d3df --- /dev/null +++ b/packages/widgets/src/notebook/mobile-summary.ts @@ -0,0 +1,15 @@ +export const extractNotebookExcerpt = (content: string) => { + const parsedDocument = new DOMParser().parseFromString(content, "text/html"); + parsedDocument.querySelectorAll("script, style").forEach((element) => { + element.remove(); + }); + + const textWalker = parsedDocument.createTreeWalker(parsedDocument.body, NodeFilter.SHOW_TEXT); + const textParts: string[] = []; + + while (textWalker.nextNode()) { + textParts.push(textWalker.currentNode.textContent ?? ""); + } + + return textParts.join(" ").replace(/\s+/g, " ").trim(); +};