mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-04 00:47:01 +01:00
search: a file is found by what it says
The text of every file in the tree that is text, by its type or by its first 8 KiB reading as UTF-8 without a NUL, now goes into `file_text` and a second FTS5 index beside the documents', up to its first 256 KiB, the same part the viewer shows. A search asks both, lists a node found in both once, and marks a file found by its text with `in_text`; the list shows the words around the match under its name. There is one way in, `file_text::catch_up`, which reads every unsealed file that has no row yet. An upload, an import, an SFTP save and a decrypt call it once their own transaction is done, and the server runs it at start for anything that slipped past. A file that is not text gets an empty row, so it is read once and not again. The triggers keep it honest the other way. New bytes drop the old text, so an SFTP save is read again, and `:encrypt` writes a file under a new media id, so its plaintext is gone in the same statement that seals it. The text of a sealed file is refused outright, whatever path tries to store it; otherwise it would sit in `diary.db` and its mirror beside the sealed bytes. PDFs and office documents are not read: their text needs a parser this binary does not carry.
This commit is contained in:
1 parent
6673298cb2
commit
909abf5fcb
13 files changed
+476
-14
No files matched your search
@@ -130,6 +130,7 @@
|
||||
<span class="title">
|
||||
{label(node)}{#if isContainer(node)}<span class="slash">/</span>{/if}
|
||||
{#if workspace.query && node.location}<span class="where">{node.location}</span>{/if}
|
||||
{#if workspace.query && node.in_text}<span class="hit" title="found in the file's text">{node.excerpt}</span>{/if}
|
||||
</span>
|
||||
{#if workspace.isMarked(node.id)}<span class="badge" title="marked — p drops what is marked in a folder">m</span>{/if}
|
||||
{#if node.shared}<span class="shared" title="shared"></span>{/if}
|
||||
@@ -259,6 +260,16 @@
|
||||
/* Where a search match sits, so two of the same name can be told apart. */
|
||||
.where { margin-left: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
|
||||
.row.active .where { color: var(--ink); }
|
||||
/* A file found by its text, not its name: the words it was found by, below. */
|
||||
.hit {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.row.active .hit { color: var(--ink); }
|
||||
.aside { flex: none; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
||||
.badge { flex: none; font-size: 11px; font-weight: 700; color: var(--light-dim); }
|
||||
.shared {
|
||||
|
||||
Reference in new issue
Block a user