@ 261101.7

261029.4 · 00011b6688dc6372821c09b0a62727dbb8effcb3

A search's recent pages come only from the page's own tree

Recent pages crossed trees, so on the web address a search in one repo listed pages from repos read before. Each page's search box now names its tree, and each stored entry keeps the tree it was opened in. A version counts as its tree. Entries stored before this have no tree and are dropped.

reading declarations

Changes to assets/. All files

assets/layout.html

@@ -13,7 +13,7 @@ <nav>{{range $i, $c := .Crumbs}}{{if $i}}&nbsp;/ {{end}}{{if $c.Href}}<a href="{{$c.Href}}"{{with $c.Title}} title="{{.}}"{{end}}>{{$c.Label}}</a>{{else if $c.Title}}<span title="{{$c.Title}}">{{$c.Label}}</span>{{else}}<span>{{$c.Label}}</span>{{end}}{{end}}</nav> {{if not .Stopped}}<span>{{with .Status}}<span class="age">{{.}}</span>{{end}}{{if .Raw}}<a href="?raw">raw</a>{{end}}{{if not (or .Shared .NoStop)}}<form method="post" action="{{ownPath}}stop">{{if .Tree}}<input type="hidden" name="tree" value="{{.Tree}}"><button>Delete lock</button>{{else}}<button class="kill">Kill server</button>{{end}}</form>{{end}}</span>{{end}} </header>-{{if not .Stopped}}{{with .Search}}<div class="search"><input type="search" class="search" data-search="{{.}}" placeholder="search" aria-label="Search this directory" autocomplete="off"><span class="tools"><button class="copy" title="copy the page's text" aria-label="copy the page's text">⧉</button>{{if $.Forge}}<button class="share" data-forge="{{$.Forge}}" data-lines="{{$.ForgeLines}}" title="copy the forge's link to what is selected, or to the page" aria-label="copy the forge's link to what is selected, or to the page">⤴</button>{{else}}<button class="share" title="copy a link to what is selected, or to the page" aria-label="copy a link to what is selected, or to the page">⤴</button>{{end}}</span></div>+{{if not .Stopped}}{{with .Search}}<div class="search"><input type="search" class="search" data-search="{{.}}" data-recents="{{$.Recents}}" placeholder="search" aria-label="Search this directory" autocomplete="off"><span class="tools"><button class="copy" title="copy the page's text" aria-label="copy the page's text">⧉</button>{{if $.Forge}}<button class="share" data-forge="{{$.Forge}}" data-lines="{{$.ForgeLines}}" title="copy the forge's link to what is selected, or to the page" aria-label="copy the forge's link to what is selected, or to the page">⤴</button>{{else}}<button class="share" title="copy a link to what is selected, or to the page" aria-label="copy a link to what is selected, or to the page">⤴</button>{{end}}</span></div> {{end}}{{end}}<main> {{.Body}} </main>

assets/live.js

@@ -578,12 +578,19 @@ 	// origin, never on the server, so each viewer of a share sees only 	// what that viewer opened. Each entry counts its visits and keeps the 	// last; the score weighs both, as zoxide does. A reload is no visit.+	// Each entry names its tree, and a search lists only the page's own+	// tree, so one repo's reading never shows in another's. An entry+	// without a tree predates that and is dropped. 	const recentKey = "recent"; 	const maxRecent = 300;+	const recentTree = () => {+		const b = box();+		return b ? b.dataset.recents : undefined;+	}; 	const readRecent = () => { 		try { 			const list = JSON.parse(localStorage.getItem(recentKey));-			return Array.isArray(list) ? list : [];+			return Array.isArray(list) ? list.filter((e) => typeof e.r === "string") : []; 		} catch { 			return []; 		}@@ -594,7 +601,9 @@ 	}; 	const recentPaths = () => { 		const now = Date.now();+		const tree = recentTree(); 		return readRecent()+			.filter((e) => e.r === tree) 			.sort((a, b) => score(b, now) - score(a, now)) 			.map((e) => e.p); 	};@@ -617,13 +626,16 @@ 		if (!["doc", "code", "dir"].includes(document.body.className)) return; 		const nav = performance.getEntriesByType("navigation")[0]; 		if (nav && nav.type === "reload") return;+		const tree = recentTree();+		if (tree === undefined) return; 		const now = Date.now(); 		const list = readRecent(); 		const e = list.find((e) => e.p === location.pathname); 		if (e) { 			e.n++; 			e.t = now;-		} else list.push({ p: location.pathname, n: 1, t: now });+			e.r = tree;+		} else list.push({ p: location.pathname, r: tree, n: 1, t: now }); 		list.sort((a, b) => score(b, now) - score(a, now)); 		try { 			localStorage.setItem(recentKey, JSON.stringify(list.slice(0, maxRecent)));