From 47be00355d6315590af69e810dbd91f7922412da Mon Sep 17 00:00:00 2001 From: 01zulfi <85733202+01zulfi@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:14:05 +0500 Subject: [PATCH 1/3] webclipper: add bookmark option Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> --- apps/web/src/utils/web-extension-server.ts | 22 ++- ...ng-your-first-web-page-with-web-clipper.md | 4 + extensions/web-clipper/src/common/bridge.ts | 2 +- .../web-clipper/src/components/icons/index.ts | 1 + extensions/web-clipper/src/views/main.tsx | 130 ++++++++++-------- 5 files changed, 98 insertions(+), 61 deletions(-) diff --git a/apps/web/src/utils/web-extension-server.ts b/apps/web/src/utils/web-extension-server.ts index e88460f83..b337c531e 100644 --- a/apps/web/src/utils/web-extension-server.ts +++ b/apps/web/src/utils/web-extension-server.ts @@ -73,7 +73,11 @@ export class WebExtensionServer implements Server { async saveClip(clip: Clip) { let clipContent = ""; - if (clip.mode === "simplified" || clip.mode === "screenshot") { + if ( + clip.mode === "simplified" || + clip.mode === "screenshot" || + clip.mode === "bookmark" + ) { clipContent += clip.data; } else { const clippedFile = new File( @@ -105,11 +109,17 @@ export class WebExtensionServer implements Server { if (isCipher(content)) return; content += clipContent; - content += h("div", [ - h("hr"), - h("p", ["Clipped from ", h("a", [clip.title], { href: clip.url })]), - h("p", [`Date clipped: ${getFormattedDate(Date.now())}`]) - ]).innerHTML; + content += + clip.mode === "bookmark" + ? h("div", [ + h("hr"), + h("p", [`Date bookmarked: ${getFormattedDate(Date.now())}`]) + ]).innerHTML + : h("div", [ + h("hr"), + h("p", ["Clipped from ", h("a", [clip.title], { href: clip.url })]), + h("p", [`Date clipped: ${getFormattedDate(Date.now())}`]) + ]).innerHTML; const id = await db.notes.add({ id: note?.id, diff --git a/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md b/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md index 9e83b332c..4ae5f967f 100644 --- a/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md +++ b/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md @@ -73,6 +73,10 @@ The `Selected nodes` mode allows you to select exactly which nodes you want to c The clipping mode controls how the final clip should look. +### Bookmark + +`Bookmark` mode saves only the URL of the page along with the title. It is best suited to save pages for later reading/reference. + ### Simplified `Simplified` mode doesn't include any styles. It is best suited for long-form content such as articles & blogs. All clips in `Simplified` mode are saved directly as is i.e. they do not appear as web clip embeds in the Notesnook editor. diff --git a/extensions/web-clipper/src/common/bridge.ts b/extensions/web-clipper/src/common/bridge.ts index 3e081fb62..894c76fae 100644 --- a/extensions/web-clipper/src/common/bridge.ts +++ b/extensions/web-clipper/src/common/bridge.ts @@ -21,7 +21,7 @@ import { ThemeDefinition } from "@notesnook/theme"; export type ClipArea = "full-page" | "visible" | "selection" | "article"; -export type ClipMode = "simplified" | "screenshot" | "complete"; +export type ClipMode = "bookmark" | "simplified" | "screenshot" | "complete"; export type User = { email?: string; diff --git a/extensions/web-clipper/src/components/icons/index.ts b/extensions/web-clipper/src/components/icons/index.ts index ee1f97e76..bba876573 100644 --- a/extensions/web-clipper/src/components/icons/index.ts +++ b/extensions/web-clipper/src/components/icons/index.ts @@ -57,6 +57,7 @@ export const Icons = { visible: mdiViewDayOutline, selection: mdiCursorDefaultClickOutline, + bookmark: mdiBookmarkOutline, simplified: mdiTextBoxOutline, screenshot: mdiFitToScreenOutline, complete: mdiViewDashboardOutline, diff --git a/extensions/web-clipper/src/views/main.tsx b/extensions/web-clipper/src/views/main.tsx index 80b0de2a3..3aed3a7ab 100644 --- a/extensions/web-clipper/src/views/main.tsx +++ b/extensions/web-clipper/src/views/main.tsx @@ -68,6 +68,11 @@ const clipAreas: { name: string; id: ClipArea; icon: string }[] = [ const clipModes: { name: string; id: ClipMode; icon: string; pro?: boolean }[] = [ + { + name: "Bookmark", + id: "bookmark", + icon: Icons.bookmark + }, { name: "Simplified", id: "simplified", @@ -166,7 +171,7 @@ export function Main() { }, [settings]); async function startClip() { - if (!clipArea || !clipMode) return; + if (!clipArea || !clipMode || clipMode === "bookmark") return; try { setError(undefined); @@ -268,7 +273,11 @@ export function Main() { setClipperState(ClipperState.Idle); setClipArea(item.id); }} - disabled={isClipping || clipperState === ClipperState.Clipped} + disabled={ + isClipping || + clipperState === ClipperState.Clipped || + clipMode === "bookmark" + } sx={{ display: "flex", borderRadius: "default", @@ -342,55 +351,58 @@ export function Main() { ))} - {clipData && clipData.data && !isClipping && ( - - { - const winUrl = URL.createObjectURL( - new Blob(["\ufeff", clipData.data], { type: "text/html" }) - ); - await browser.windows.create({ - url: winUrl - }); - }} - > - Clip done. Click here to preview. - - { - setClipData(undefined); - setClipperState(ClipperState.Idle); - }} - > - Discard - - - )} + {clipMode !== "bookmark" && + clipData && + clipData.data && + !isClipping && ( + + { + const winUrl = URL.createObjectURL( + new Blob(["\ufeff", clipData.data], { type: "text/html" }) + ); + await browser.windows.create({ + url: winUrl + }); + }} + > + Clip done. Click here to preview. + + { + setClipData(undefined); + setClipperState(ClipperState.Idle); + }} + > + Discard + + + )} {error && ( ${title}` + } + : clipData; + + if (!data || !clipData || !title || !clipArea || !clipMode || !url) + return; const notesnook = await connectApi(false); if (!notesnook) { @@ -476,7 +496,7 @@ export function Main() { note, refs, pageTitle: pageTitle.current, - ...clipData + ...data }); setClipData(undefined); @@ -492,7 +512,9 @@ export function Main() { window.close(); }} > - {clipperButtonLabelMap[clipperState]} + {clipMode === "bookmark" + ? "Save bookmark" + : clipperButtonLabelMap[clipperState]} Date: Mon, 27 Oct 2025 15:18:00 +0500 Subject: [PATCH 2/3] webclipper: fix bookmark not working in web clipper --- extensions/web-clipper/src/views/main.tsx | 30 +++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/extensions/web-clipper/src/views/main.tsx b/extensions/web-clipper/src/views/main.tsx index 3aed3a7ab..8f99a1d32 100644 --- a/extensions/web-clipper/src/views/main.tsx +++ b/extensions/web-clipper/src/views/main.tsx @@ -466,22 +466,24 @@ export function Main() { disabled={isClipping} onClick={async () => { if ( - clipperState === ClipperState.Idle || - clipperState === ClipperState.Error + clipMode !== "bookmark" && + (clipperState === ClipperState.Idle || + clipperState === ClipperState.Error) ) { await startClip(); return; } - const isBookmark = clipMode === "bookmark"; - const data = isBookmark - ? { - data: `${title}` - } - : clipData; + if (!title || !clipArea || !clipMode || !url) return; - if (!data || !clipData || !title || !clipArea || !clipMode || !url) - return; + const data = + clipMode === "bookmark" + ? { + data: createBookmark(url, title) + } + : clipData; + + if (!data) return; const notesnook = await connectApi(false); if (!notesnook) { @@ -589,3 +591,11 @@ export async function clip( settings }); } + +function createBookmark(url: string, title: string) { + const a = document.createElement("a"); + a.setAttribute("href", url); + a.setAttribute("title", title); + a.innerText = title; + return a.outerHTML; +} From dea91c48a2bda74d39b8fbc31ce446976d108159 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Mon, 27 Oct 2025 15:18:16 +0500 Subject: [PATCH 3/3] web: add hr after bookmark link --- apps/web/src/utils/web-extension-server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/utils/web-extension-server.ts b/apps/web/src/utils/web-extension-server.ts index b337c531e..d5cd96fc4 100644 --- a/apps/web/src/utils/web-extension-server.ts +++ b/apps/web/src/utils/web-extension-server.ts @@ -112,8 +112,8 @@ export class WebExtensionServer implements Server { content += clip.mode === "bookmark" ? h("div", [ - h("hr"), - h("p", [`Date bookmarked: ${getFormattedDate(Date.now())}`]) + h("p", [`Date bookmarked: ${getFormattedDate(Date.now())}`]), + h("hr") ]).innerHTML : h("div", [ h("hr"),