Recently Written · git

sbm

dmenu bookmarks. Instantly fuzzy search thousands of bookmarks and plumb them. LOOKING FOR SUCKLESS SOFTWARE EDITION? GO TO sbm-suckless INSTEAD

git clone https://github.com/equwal/sbm

Log | Files | Refs


commit 7512a6704a29547c578bbde96477bc9c2cf9e869
Spenser Truex <truex@equwal.com>
2026-09-24 00:48:19 -0700

bm-html: remove the live preview

Most sites do not let a page of another site show them in a frame: they
send X-Frame-Options or a frame-ancestors policy. YouTube is one of them.
For these sites the frame of the preview stayed empty, so the preview did
not work for most bookmarks.

bm-html is again the page of 0.5: a filter box, and the complete list
without script. The fzf preview of bm in a terminal stays: it shows the
text of the page, which bm-page gets with curl. The test "bm-html shows
no page in a frame" replaces the test of the preview pane.

 README      | 10 +++-------
 bm-html     | 49 +++++--------------------------------------------
 test/run.sh |  7 ++++---
 3 files changed, 12 insertions(+), 54 deletions(-)
diff --git a/README b/README
index 2fb3302..054c19e 100755
--- a/README
+++ b/README
@@ -152,13 +152,9 @@ bookmark file itself stays a plain list.
 
 One self-contained file: no server side, nothing loaded from elsewhere.
 Bookmarks are listed under each of their tags, with the tags linked at the
-top. Inline script adds a filter box and, in a wide window, a live preview:
-the page of the highlighted bookmark shows on the right. The arrow keys and
-the mouse move the highlight, and Enter opens it. The preview loads a page
-only when you type or point, in a sandboxed frame without a referrer; some
-sites do not let other pages show them. Without script the page is still the
-complete list, and Ctrl-F works. page.html?q=words starts out filtered, so
-the page can be a search keyword in your browser, or in bm:
+top. A dozen lines of inline script add a filter box; without script the page
+is still the complete list, and Ctrl-F works. page.html?q=words starts out
+filtered, so the page can be a search keyword in your browser, or in bm:
 
     b | https://example.org/bookmarks.html?q=%s
 
diff --git a/bm-html b/bm-html
index 73887d2..4031c5f 100755
--- a/bm-html
+++ b/bm-html
@@ -8,11 +8,10 @@
 # Without a file the default bookmark file is read; "-" is stdin.
 #
 # The page lists the bookmarks under each of their tags, with links to the
-# tags at the top. A few lines of script add a filter box and, in a wide
-# window, a live preview: the page of the highlighted bookmark. Without
-# script the page is still the complete list. page.html?q=words starts out
-# filtered, so the page can serve as a search engine keyword in a browser, or
-# in bm's own engines file:    b | https://example.org/bookmarks.html?q=%s
+# tags at the top. A few lines of script add a filter box; without script the
+# page is still the complete list. page.html?q=words starts out filtered, so
+# the page can serve as a search engine keyword in a browser, or in bm's own
+# engines file:    b | https://example.org/bookmarks.html?q=%s
 
 usage () {
     printf 'usage: bm-html [-t title] [file | -] ...\n'
@@ -80,18 +79,9 @@ END {
     print "body{max-width:50em;margin:1em auto;padding:0 1em;font:1em/1.5 sans-serif}"
     print "#q{width:100%;box-sizing:border-box;font:inherit;padding:.3em}"
     print "ul{padding-left:1.2em}small,.t{color:#777;font-size:.85em}.t{margin-left:.3em}"
-    print "li.sel{background:#e3eef3;box-shadow:0 0 0 .2em #e3eef3}"
-    print "#preview{display:none}#preview p{margin:0 0 .3em;color:#777;font-size:.85em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}"
-    print "#preview iframe{flex:1;width:100%;box-sizing:border-box;border:1px solid #ccc;background:#fff}"
-    print "@media(min-width:80em){body:has(#preview:not([hidden])){margin-left:1em}"
-    print "#preview:not([hidden]){display:flex;flex-direction:column;position:fixed;top:1em;bottom:1em;left:54em;right:1em}}"
     print "</style>"
     print "<h1>" t "</h1>"
     print "<input id=q type=search placeholder=\"filter " total " bookmarks\" hidden>"
-    # The live preview: the page of the highlighted bookmark, on the right
-    # of a wide window. The script shows it.
-    print "<aside id=preview hidden><p>Type in the filter, or point at a bookmark, to see its page here.</p>"
-    print "<iframe title=\"Preview of the page\" sandbox=\"allow-scripts allow-same-origin\" referrerpolicy=no-referrer></iframe></aside>"
     printf "<p>"
     for (i = 1; i <= count; i++)
         if (names[i] != "")
@@ -110,35 +100,6 @@ END {
     print "var t=(l.textContent+\" \"+l.firstChild.href).toLowerCase();"
     print "var ok=w.every(function(x){return t.indexOf(x)>=0});l.hidden=!ok;if(ok)n++});"
     print "s.hidden=!n})}"
-    # The live preview, as on sbm Sync: the arrow keys and the mouse move the
-    # highlight, Enter opens it, and the page loads when the highlight stays
-    # on it for 300 ms. On an https page an http bookmark loads as https,
-    # because a secure page cannot show an insecure frame. A page in the
-    # frame cannot keep the focus: the typing stays in the filter.
-    print "var pane=document.getElementById(\"preview\"),frame=pane.querySelector(\"iframe\"),cap=pane.querySelector(\"p\");"
-    print "var wide=matchMedia(\"(min-width:80em)\"),sel=0,started=false,timer=0,framed=null,pointer=\"\";"
-    print "function rows(){return Array.prototype.filter.call(document.querySelectorAll(\"li\"),function(l){return !l.hidden})}"
-    print "function address(l){var u;try{u=new URL(l.firstChild.href)}catch(e){return null}"
-    print "if(u.protocol!==\"http:\"&&u.protocol!==\"https:\")return null;"
-    print "if(location.protocol===\"https:\")u.protocol=\"https:\";return u.href}"
-    print "function load(to){if(to===framed)return;framed=to;frame.src=to||\"about:blank\"}"
-    print "function show(l){clearTimeout(timer);if(!wide.matches)return;var to=l?address(l):null;"
-    print "cap.textContent=!l?\"No bookmark to preview.\":to||\"No preview: this bookmark is not a web page.\";"
-    print "if(to)timer=setTimeout(function(){load(to)},300);else load(null)}"
-    print "function light(i){var r=rows();sel=Math.max(0,Math.min(r.length-1,i));"
-    print "document.querySelectorAll(\"li.sel\").forEach(function(l){l.className=\"\"});"
-    print "if(r[sel])r[sel].className=\"sel\";if(started)show(r[sel])}"
-    print "function point(e){var l=e.target.closest&&e.target.closest(\"li\");if(!l)return;started=true;light(rows().indexOf(l))}"
-    print "q.oninput=function(){started=true;f();light(0)};"
-    print "q.onkeydown=function(e){var r=rows();"
-    print "if(e.key===\"ArrowDown\"||e.key===\"ArrowUp\"){e.preventDefault();started=true;"
-    print "light(sel+(e.key===\"ArrowDown\"?1:-1));if(rows()[sel])rows()[sel].scrollIntoView({block:\"nearest\"})}"
-    print "else if(e.key===\"Enter\"&&r[sel]){if(e.ctrlKey||e.metaKey)open(r[sel].firstChild.href,\"_blank\",\"noopener\");"
-    print "else location.assign(r[sel].firstChild.href)}};"
-    print "document.addEventListener(\"mousemove\",function(e){var at=e.screenX+\",\"+e.screenY;if(at===pointer)return;pointer=at;point(e)});"
-    print "document.addEventListener(\"focusin\",point);"
-    print "wide.addEventListener(\"change\",function(){if(wide.matches)light(sel);else load(null)});"
-    print "addEventListener(\"blur\",function(){setTimeout(function(){if(document.activeElement===frame)q.focus({preventScroll:true})})});"
-    print "q.value=new URLSearchParams(location.search).get(\"q\")||\"\";started=q.value!==\"\";f();pane.hidden=false;light(0);"
+    print "q.oninput=f;q.value=new URLSearchParams(location.search).get(\"q\")||\"\";f();"
     print "</script>"
 }'
diff --git a/test/run.sh b/test/run.sh
index 3755398..5a5dd34 100755
--- a/test/run.sh
+++ b/test/run.sh
@@ -1022,9 +1022,10 @@ eq 'bm-html has one inline script, a filter box hidden without it, and ?q=' \
     "$(printf '%s\n' "$page" | grep -c '<script>') $(printf '%s\n' "$page" | grep -c '<input id=q type=search placeholder="filter 3 bookmarks" hidden>') $(printf '%s\n' "$page" | grep -c 'URLSearchParams(location.search).get("q")')" \
     '1 1 1'
 eq 'bm-html loads nothing from elsewhere' "$(printf '%s\n' "$page" | grep -c -e ' src=' -e '<link' -e '@import')" '0'
-eq 'bm-html has a preview pane that only its script shows, with a sandboxed frame and no referrer' \
-    "$(printf '%s\n' "$page" | grep -c '^<aside id=preview hidden>') $(printf '%s\n' "$page" | grep -c '<iframe title="Preview of the page" sandbox="allow-scripts allow-same-origin" referrerpolicy=no-referrer></iframe></aside>') $(printf '%s\n' "$page" | grep -c 'pane.hidden=false')" \
-    '1 1 1'
+# Most sites do not let a page of another site show them in a frame
+# (X-Frame-Options or frame-ancestors), YouTube among them, so a preview in
+# a frame stays empty for them.
+eq 'bm-html shows no page in a frame' "$(printf '%s\n' "$page" | grep -ci 'iframe')" '0'
 eq 'bm-html is a filter' "$($BM -t lib -l | $HTML - | grep -c '^<li>')" '2'
 eq 'bm-html reads the bookmark file by default, whatever stdin is' \
     "$($HTML </dev/null | grep -c '^<li>')" '4'