@miadi/chronicle-tui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.tsx"],"names":[],"mappings":";;AAcA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,MAAM,KAAK,GAAG;;;;;;;;;;;;;CAab,CAAA;AAED,SAAS,IAAI,CAAC,IAAc;IAC1B,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACzD,IAAI,MAA0B,CAAA;IAC9B,IAAI,MAA0B,CAAA;IAC9B,IAAI,OAA2B,CAAA;IAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAE,CAAA;QACxB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAC3B,OAAO,CAAC,CAAA;QACV,CAAC;QACD,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAA;YAChH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAA;YACxC,OAAO,CAAC,CAAA;QACV,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ;YAAE,IAAI,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;aAC3C,IAAI,GAAG,KAAK,UAAU;YAAE,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;aAC9C,IAAI,GAAG,KAAK,UAAU;YAAE,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;aAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,OAAO,KAAK,EAAE,CAAC,CAAA;YACzD,OAAO,CAAC,CAAA;QACV,CAAC;;YAAM,OAAO,GAAG,GAAG,CAAA;IACtB,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAA;QACtF,OAAO,CAAC,CAAA;IACV,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kFAAkF,CAAC,CAAA;QACxG,OAAO,CAAC,CAAA;IACV,CAAC;IACD,MAAM,CAAC,KAAC,GAAG,IAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAI,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAA;IACvG,OAAO,CAAC,CAAA;AACV,CAAC;AAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACxC,IAAI,IAAI,KAAK,CAAC;IAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAA"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.tsx"],"names":[],"mappings":"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"}
package/dist/data.d.ts CHANGED
@@ -3,9 +3,15 @@
3
3
  * it. The browser holds no chronicle rules of its own:
4
4
  *
5
5
  * - the catalog and the readings: `@miadi/inquiry-weave`
6
- * - a vessel's summary, files, file text and full-text search: `@miadi/episode-vessel`
6
+ * - a vessel's summary, files, file text, full-text search, the room rule and
7
+ * an episode's audience: `@miadi/episode-vessel`
7
8
  * - the doors a reference opens, and OSC 8 links: `@miadi/inquiry-weave`
8
9
  * - the five-stage proof: `@miadi/inquiry-weave` (git and the wheel, so only on demand)
10
+ *
11
+ * It shows a reader what the web room would show them (jgwill/Miadi#712): a
12
+ * visitor sees no `community` episode and nothing under `captures/` or
13
+ * `ceremonies/`; a reader the app lets write sees everything, as the room's
14
+ * file reader allows them.
9
15
  */
10
16
  import { type Destination, type EpisodeStatus, type TextReference } from "@miadi/inquiry-weave";
11
17
  import { type EpisodeFile, type EpisodeSummary, type SearchResult } from "@miadi/episode-vessel";
@@ -14,21 +20,36 @@ export interface Chronicle {
14
20
  root: string;
15
21
  rows: EpisodeRow[];
16
22
  }
23
+ /** What this reader may see: decided by the app, most closed until it answers. */
24
+ export interface Access {
25
+ /** The app named a reader (a person or the writer): community episodes show. */
26
+ signedIn: boolean;
27
+ /** The app would record a write from this reader: the room's private folders show. */
28
+ mayWrite: boolean;
29
+ }
30
+ export declare const VISITOR: Access;
17
31
  export declare function loadChronicle(root: string): Promise<Chronicle>;
32
+ /** The rows this reader sees. */
33
+ export declare function visibleRows(rows: readonly EpisodeRow[], access: Access): EpisodeRow[];
34
+ /** The room rule for this reader: a path it may list, read and search. */
35
+ export declare function inRoom(access: Access): (relativePath: string) => boolean;
18
36
  export interface EpisodeDetail {
19
37
  summary: EpisodeSummary | null;
20
38
  files: EpisodeFile[];
21
39
  error?: string;
22
40
  }
23
- export declare function loadDetail(root: string, name: string): EpisodeDetail;
24
- export declare function loadText(root: string, name: string, file: string): {
41
+ export declare function loadDetail(root: string, name: string, access: Access): EpisodeDetail;
42
+ export declare function loadText(root: string, name: string, file: string, access: Access): {
25
43
  content: string;
26
44
  } | {
27
45
  error: string;
28
46
  };
29
- /** Up to 1000 hits, newest episode first, file and line order kept inside each episode. */
30
- export declare function search(root: string, query: string, rows?: readonly EpisodeRow[]): Promise<SearchResult>;
31
- /** The episode a chronicle reference names, or null when it names none or several. */
47
+ /**
48
+ * Up to 1000 hits over the episodes this reader sees, newest episode first,
49
+ * file and line order kept inside each episode.
50
+ */
51
+ export declare function search(root: string, query: string, rows: readonly EpisodeRow[], access: Access, signal?: AbortSignal): Promise<SearchResult>;
52
+ /** The episode a chronicle reference names among `rows`, or null when it names none or several. */
32
53
  export declare function episodeOfReference(rows: readonly EpisodeRow[], uri: string): string | null;
33
54
  export interface Doors {
34
55
  title: string;
@@ -42,15 +63,30 @@ export interface Doors {
42
63
  */
43
64
  export declare function episodeDoors(chronicle: Chronicle, name: string, file?: string): Promise<Doors>;
44
65
  /**
45
- * The doors of a reference found in a file. A ceremony or circle shows its
46
- * URLs only (D9): the page it opens asks the reader for their seat, and
47
- * nothing the wheel holds about it is read here.
66
+ * The doors of a reference found in a file. A ceremony or circle opens its
67
+ * pages only, which ask for the reader's seat: the wheel's record answers
68
+ * anyone, so it is never offered here (D9; jgwill/Miadi#706 security review, F6).
48
69
  */
49
- export declare function referenceDoors(chronicle: Chronicle, ref: TextReference): Promise<Doors>;
70
+ export declare function referenceDoors(chronicle: Chronicle, ref: TextReference, rows: readonly EpisodeRow[]): Promise<Doors>;
50
71
  /** The door a phone can open: the tailnet room, then the public one, then the first. */
51
72
  export declare function phoneDoor(doors: readonly Destination[]): Destination | undefined;
52
73
  export declare function qrLines(url: string, invert?: boolean): string[];
53
74
  export declare function proof(root: string, name: string): Promise<EpisodeStatus>;
54
- /** Hand a URL to the system opener. Returns the command used, or null when none exists. */
55
- export declare function openUrl(url: string): string | null;
75
+ /**
76
+ * Why a door may not be handed to the system opener, or null when it may: an
77
+ * http(s) page, or a `file:` path inside the chronicle that is a folder or a
78
+ * text, document or media file. Anything else (another scheme, a path outside,
79
+ * a script, a `.desktop` entry) stays text to copy
80
+ * (jgwill/Miadi#706 security review, F4).
81
+ */
82
+ export declare function refuseToOpen(url: string, root: string): string | null;
83
+ /**
84
+ * Hand a door to the system opener. Returns the command used, or the reason it
85
+ * was not opened. The opener never inherits a token.
86
+ */
87
+ export declare function openUrl(url: string, root: string, withheld?: readonly string[]): {
88
+ opened: string;
89
+ } | {
90
+ refused: string;
91
+ };
56
92
  //# sourceMappingURL=data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EASL,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAML,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAE7D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,EAAE,CAAA;CACnB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAIpE;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAMpE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAM1G;AAED,2FAA2F;AAC3F,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,UAAU,EAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CASjH;AAKD,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK1F;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAapG;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAW7F;AAED,wFAAwF;AACxF,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,GAAG,SAAS,CAOhF;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,EAAE,CAE7D;AAED,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAG9E;AAED,2FAA2F;AAC3F,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBlD"}
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
package/dist/data.js CHANGED
@@ -3,30 +3,57 @@
3
3
  * it. The browser holds no chronicle rules of its own:
4
4
  *
5
5
  * - the catalog and the readings: `@miadi/inquiry-weave`
6
- * - a vessel's summary, files, file text and full-text search: `@miadi/episode-vessel`
6
+ * - a vessel's summary, files, file text, full-text search, the room rule and
7
+ * an episode's audience: `@miadi/episode-vessel`
7
8
  * - the doors a reference opens, and OSC 8 links: `@miadi/inquiry-weave`
8
9
  * - the five-stage proof: `@miadi/inquiry-weave` (git and the wheel, so only on demand)
10
+ *
11
+ * It shows a reader what the web room would show them (jgwill/Miadi#712): a
12
+ * visitor sees no `community` episode and nothing under `captures/` or
13
+ * `ceremonies/`; a reader the app lets write sees everything, as the room's
14
+ * file reader allows them.
9
15
  */
10
16
  import { spawn } from "node:child_process";
11
17
  import fs from "node:fs";
18
+ import path from "node:path";
12
19
  import { buildChronicleCatalog, episodeDoorStatus, readWebBases, resolveChronicleRef, resolveDoorContext, resolveForTerminal, resolveWheelRefForTerminal, parseMiadiChronicleUri, } from "@miadi/inquiry-weave";
13
- import { listEpisodeFiles, readEpisodeSummary, readEpisodeText, resolveChronicleRoot, searchVessels, } from "@miadi/episode-vessel";
20
+ import { DOCUMENT_EXTENSIONS, MEDIA_EXTENSIONS, TEXT_EXTENSIONS, isOutsideTheRoom, listEpisodeFiles, listEpisodes, readEpisodeSummary, readEpisodeText, resolveChronicleRoot, searchVessels, } from "@miadi/episode-vessel";
14
21
  import { renderUnicodeCompact } from "uqr";
15
22
  import { sortRows, toRow } from "./model.js";
23
+ export const VISITOR = { signedIn: false, mayWrite: false };
16
24
  export async function loadChronicle(root) {
17
25
  const real = resolveChronicleRoot(root);
18
26
  const catalog = await buildChronicleCatalog(real);
19
- return { root: real, rows: sortRows(catalog.episodes.map(toRow)) };
27
+ const audience = new Map();
28
+ try {
29
+ for (const episode of listEpisodes({ root: real }))
30
+ audience.set(episode.episodePath, episode.audience === "community" ? "community" : "public");
31
+ }
32
+ catch {
33
+ // An unreadable shelf leaves every episode public, as the catalog does.
34
+ }
35
+ return { root: real, rows: sortRows(catalog.episodes.map((entry) => toRow(entry, audience.get(entry.name)))) };
20
36
  }
21
- export function loadDetail(root, name) {
37
+ /** The rows this reader sees. */
38
+ export function visibleRows(rows, access) {
39
+ return access.signedIn ? [...rows] : rows.filter((row) => row.audience !== "community");
40
+ }
41
+ /** The room rule for this reader: a path it may list, read and search. */
42
+ export function inRoom(access) {
43
+ return (relativePath) => access.mayWrite || !isOutsideTheRoom(relativePath);
44
+ }
45
+ export function loadDetail(root, name, access) {
22
46
  try {
23
- return { summary: readEpisodeSummary(name, { root }), files: listEpisodeFiles(name, { root }) };
47
+ const allowed = inRoom(access);
48
+ return { summary: readEpisodeSummary(name, { root }), files: listEpisodeFiles(name, { root, include: (file) => allowed(file) }) };
24
49
  }
25
50
  catch (error) {
26
51
  return { summary: null, files: [], error: error.message };
27
52
  }
28
53
  }
29
- export function loadText(root, name, file) {
54
+ export function loadText(root, name, file, access) {
55
+ if (!inRoom(access)(file))
56
+ return { error: `${file} is outside the room: it opens for a reader the app lets write there.` };
30
57
  try {
31
58
  return { content: readEpisodeText(name, file, { root }).content };
32
59
  }
@@ -34,10 +61,21 @@ export function loadText(root, name, file) {
34
61
  return { error: error.message };
35
62
  }
36
63
  }
37
- /** Up to 1000 hits, newest episode first, file and line order kept inside each episode. */
38
- export async function search(root, query, rows = []) {
39
- const result = await searchVessels(query, { root, limit: 1000 });
40
- const rank = new Map(rows.map((row, index) => [row.name, index]));
64
+ /**
65
+ * Up to 1000 hits over the episodes this reader sees, newest episode first,
66
+ * file and line order kept inside each episode.
67
+ */
68
+ export async function search(root, query, rows, access, signal) {
69
+ const visible = visibleRows(rows, access);
70
+ const result = await searchVessels(query, {
71
+ root,
72
+ limit: 1000,
73
+ order: "newest-first",
74
+ episodes: visible.map((row) => row.name),
75
+ include: inRoom(access),
76
+ signal,
77
+ });
78
+ const rank = new Map(visible.map((row, index) => [row.name, index]));
41
79
  const order = (name) => rank.get(name) ?? Number.MAX_SAFE_INTEGER;
42
80
  const hits = result.hits
43
81
  .map((hit, index) => ({ hit, index }))
@@ -46,7 +84,7 @@ export async function search(root, query, rows = []) {
46
84
  return { ...result, hits };
47
85
  }
48
86
  const resolvable = (rows) => rows.map((row) => ({ name: row.name, number: row.number, slug: row.slug, date: row.date, title: row.title }));
49
- /** The episode a chronicle reference names, or null when it names none or several. */
87
+ /** The episode a chronicle reference names among `rows`, or null when it names none or several. */
50
88
  export function episodeOfReference(rows, uri) {
51
89
  const parsed = parseMiadiChronicleUri(uri);
52
90
  if (!parsed)
@@ -77,20 +115,20 @@ export async function episodeDoors(chronicle, name, file) {
77
115
  return { title: file ? `${label} · ${file}` : `${label} · ${row?.title ?? name}`, doors };
78
116
  }
79
117
  /**
80
- * The doors of a reference found in a file. A ceremony or circle shows its
81
- * URLs only (D9): the page it opens asks the reader for their seat, and
82
- * nothing the wheel holds about it is read here.
118
+ * The doors of a reference found in a file. A ceremony or circle opens its
119
+ * pages only, which ask for the reader's seat: the wheel's record answers
120
+ * anyone, so it is never offered here (D9; jgwill/Miadi#706 security review, F6).
83
121
  */
84
- export async function referenceDoors(chronicle, ref) {
122
+ export async function referenceDoors(chronicle, ref, rows) {
85
123
  if (ref.kind === "chronicle") {
86
- const result = await resolveForTerminal(ref.uri, resolvable(chronicle.rows), chronicle.root, { bases: readWebBases() });
124
+ const result = await resolveForTerminal(ref.uri, resolvable(rows), chronicle.root, { bases: readWebBases() });
87
125
  return { title: ref.uri, doors: result?.destinations ?? [] };
88
126
  }
89
127
  const result = await resolveWheelRefForTerminal(ref.uri, { bases: readWebBases() });
90
128
  return {
91
129
  title: ref.uri,
92
- doors: result?.destinations ?? [],
93
- note: `A ${ref.kind} is private until its page sees your seat. Only its addresses are shown here.`,
130
+ doors: (result?.destinations ?? []).filter((door) => door.kind === "room"),
131
+ note: `A ${ref.kind} is private until its page sees your seat. Only its pages are offered here.`,
94
132
  };
95
133
  }
96
134
  /** The door a phone can open: the tailnet room, then the public one, then the first. */
@@ -107,8 +145,64 @@ export async function proof(root, name) {
107
145
  const context = resolveDoorContext({ chronicleRoot: root });
108
146
  return episodeDoorStatus(context, name);
109
147
  }
110
- /** Hand a URL to the system opener. Returns the command used, or null when none exists. */
111
- export function openUrl(url) {
148
+ /** Keys an opener never inherits: tokens and secrets, and whatever `--env` loaded. */
149
+ const SECRET_NAME = /TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|API_KEY|PRIVATE_KEY/i;
150
+ function openerEnv(withheld) {
151
+ const env = {};
152
+ for (const [key, value] of Object.entries(process.env)) {
153
+ if (SECRET_NAME.test(key) || withheld.includes(key))
154
+ continue;
155
+ env[key] = value;
156
+ }
157
+ return env;
158
+ }
159
+ const OPENABLE_FILE = new Set([...TEXT_EXTENSIONS, ...DOCUMENT_EXTENSIONS, ...MEDIA_EXTENSIONS]);
160
+ /**
161
+ * Why a door may not be handed to the system opener, or null when it may: an
162
+ * http(s) page, or a `file:` path inside the chronicle that is a folder or a
163
+ * text, document or media file. Anything else (another scheme, a path outside,
164
+ * a script, a `.desktop` entry) stays text to copy
165
+ * (jgwill/Miadi#706 security review, F4).
166
+ */
167
+ export function refuseToOpen(url, root) {
168
+ if (/[\u0000- \u007f-\u009f]/.test(url))
169
+ return "the address holds a control character or a space";
170
+ if (/^https?:\/\//i.test(url))
171
+ return null;
172
+ if (!/^file:\/\//i.test(url))
173
+ return "only web pages and files inside the chronicle open from here";
174
+ let file;
175
+ try {
176
+ file = decodeURIComponent(new URL(url).pathname);
177
+ }
178
+ catch {
179
+ return "the file address does not parse";
180
+ }
181
+ let real;
182
+ try {
183
+ real = fs.realpathSync(file);
184
+ }
185
+ catch {
186
+ return "that file is not on this machine";
187
+ }
188
+ const chronicle = fs.realpathSync(root);
189
+ if (real !== chronicle && !real.startsWith(`${chronicle}${path.sep}`))
190
+ return "that file is outside the chronicle";
191
+ const stat = fs.statSync(real);
192
+ if (stat.isDirectory())
193
+ return null;
194
+ if (!stat.isFile() || !OPENABLE_FILE.has(path.extname(real).toLowerCase()))
195
+ return "only text, documents and media open from here";
196
+ return null;
197
+ }
198
+ /**
199
+ * Hand a door to the system opener. Returns the command used, or the reason it
200
+ * was not opened. The opener never inherits a token.
201
+ */
202
+ export function openUrl(url, root, withheld = []) {
203
+ const reason = refuseToOpen(url, root);
204
+ if (reason)
205
+ return { refused: reason };
112
206
  const candidates = process.platform === "darwin"
113
207
  ? [["open", [url]]]
114
208
  : [
@@ -119,11 +213,11 @@ export function openUrl(url) {
119
213
  const onPath = (process.env.PATH ?? "").split(":").some((dir) => dir && fs.existsSync(`${dir}/${command}`));
120
214
  if (!onPath)
121
215
  continue;
122
- const child = spawn(command, args, { detached: true, stdio: "ignore" });
216
+ const child = spawn(command, args, { detached: true, stdio: "ignore", env: openerEnv(withheld) });
123
217
  child.on("error", () => { });
124
218
  child.unref();
125
- return command;
219
+ return { opened: command };
126
220
  }
127
- return null;
221
+ return { refused: "no opener here (xdg-open, termux-open-url or open)" };
128
222
  }
129
223
  //# sourceMappingURL=data.js.map
package/dist/data.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export { App, type AppProps } from "./App.js";
2
- export { DEFAULT_ACTIONS, actionFor, doorsAction, followAction, proofAction, qrAction, type ActionContext, type ChronicleAction, type Overlay, type View, } from "./actions.js";
3
- export { episodeDoors, episodeOfReference, loadChronicle, loadDetail, loadText, openUrl, phoneDoor, proof, qrLines, referenceDoors, search, type Chronicle, type Doors, type EpisodeDetail, } from "./data.js";
4
- export { ageOf, chipText, clamp, formatDate, fileView, filterRows, screenLineOf, sortRows, toRow, windowOf, wrapSegments, type EpisodeRow, type FileView, type ScreenLine, type Segment, type SegmentStyle, } from "./model.js";
2
+ export { ApiError, ENV_FILE_KEYS, MiadiApi, PERSON_TOKEN_ENV, PERSON_TOKEN_HEADER, TOKEN_ENV, addReview, answerAttention, ceremonyCard, circleCard, connectApi, loadEnvFile, mayCarryToken, type CeremonyCard, type CircleCard, type Connection, type Reader, type Tokens, } from "./api.js";
3
+ export { BOARD_LABELS, ROOM_LABELS, answeredMessage, checkAnswer, filterBoard, loadBoard, loadEpisodePanel, panelView, readOnlyLabel, type BoardItem, type EpisodePanel, } from "./attention.js";
4
+ export { DEFAULT_ACTIONS, actionFor, attentionAction, doorsAction, followAction, proofAction, qrAction, reviewAction, type ActionContext, type ChronicleAction, type Overlay, type View, } from "./actions.js";
5
+ export { VISITOR, episodeDoors, episodeOfReference, inRoom, loadChronicle, loadDetail, loadText, openUrl, phoneDoor, proof, qrLines, referenceDoors, refuseToOpen, search, visibleRows, type Access, type Chronicle, type Doors, type EpisodeDetail, } from "./data.js";
6
+ export { ageOf, chipText, clamp, fileView, filterRows, formatDate, screenLineOf, sortRows, toRow, windowOf, wrapSegments, type EpisodeRow, type FileView, type ScreenLine, type Segment, type SegmentStyle, } from "./model.js";
7
+ export { TAB_WIDTH, clean, cleanLine, expandTabs, isSafeUrl, link } from "./text.js";
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EACL,eAAe,EACf,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,IAAI,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EACL,OAAO,EACP,cAAc,EACd,MAAM,EACN,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,aAAa,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,UAAU,EACV,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EACL,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,eAAe,EACf,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,MAAM,GACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,KAAK,SAAS,EACd,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,IAAI,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACN,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EACL,OAAO,EACP,cAAc,EACd,YAAY,EACZ,MAAM,EACN,WAAW,EACX,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,aAAa,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  export { App } from "./App.js";
2
- export { DEFAULT_ACTIONS, actionFor, doorsAction, followAction, proofAction, qrAction, } from "./actions.js";
3
- export { episodeDoors, episodeOfReference, loadChronicle, loadDetail, loadText, openUrl, phoneDoor, proof, qrLines, referenceDoors, search, } from "./data.js";
4
- export { ageOf, chipText, clamp, formatDate, fileView, filterRows, screenLineOf, sortRows, toRow, windowOf, wrapSegments, } from "./model.js";
2
+ export { ApiError, ENV_FILE_KEYS, MiadiApi, PERSON_TOKEN_ENV, PERSON_TOKEN_HEADER, TOKEN_ENV, addReview, answerAttention, ceremonyCard, circleCard, connectApi, loadEnvFile, mayCarryToken, } from "./api.js";
3
+ export { BOARD_LABELS, ROOM_LABELS, answeredMessage, checkAnswer, filterBoard, loadBoard, loadEpisodePanel, panelView, readOnlyLabel, } from "./attention.js";
4
+ export { DEFAULT_ACTIONS, actionFor, attentionAction, doorsAction, followAction, proofAction, qrAction, reviewAction, } from "./actions.js";
5
+ export { VISITOR, episodeDoors, episodeOfReference, inRoom, loadChronicle, loadDetail, loadText, openUrl, phoneDoor, proof, qrLines, referenceDoors, refuseToOpen, search, visibleRows, } from "./data.js";
6
+ export { ageOf, chipText, clamp, fileView, filterRows, formatDate, screenLineOf, sortRows, toRow, windowOf, wrapSegments, } from "./model.js";
7
+ export { TAB_WIDTH, clean, cleanLine, expandTabs, isSafeUrl, link } from "./text.js";
5
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAiB,MAAM,UAAU,CAAA;AAC7C,OAAO,EACL,eAAe,EACf,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,QAAQ,GAKT,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EACL,OAAO,EACP,cAAc,EACd,MAAM,GAIP,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,UAAU,EACV,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,GAMb,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAiB,MAAM,UAAU,CAAA;AAC7C,OAAO,EACL,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,eAAe,EACf,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,GAMd,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,eAAe,EACf,WAAW,EACX,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,aAAa,GAGd,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,eAAe,EACf,SAAS,EACT,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,YAAY,GAKb,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACN,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EACL,OAAO,EACP,cAAc,EACd,YAAY,EACZ,MAAM,EACN,WAAW,GAKZ,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,GAMb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
package/dist/model.d.ts CHANGED
@@ -16,8 +16,10 @@ export interface EpisodeRow {
16
16
  /** An `episode.yaml` was read. Folders without one are listed, not hidden. */
17
17
  structured: boolean;
18
18
  readings: EpisodeReadings;
19
+ /** Who the episode is for (`audience:` in episode.yaml): a visitor never sees a `community` one. */
20
+ audience: "public" | "community";
19
21
  }
20
- export declare function toRow(entry: EpisodeManifestEntry): EpisodeRow;
22
+ export declare function toRow(entry: EpisodeManifestEntry, audience?: "public" | "community"): EpisodeRow;
21
23
  /** Newest first; folders without a number last, by name. */
22
24
  export declare function sortRows(rows: readonly EpisodeRow[]): EpisodeRow[];
23
25
  /**
@@ -57,7 +59,13 @@ export interface FileView {
57
59
  }
58
60
  /** The words a chip shows: the author's label, or what the reference names. */
59
61
  export declare function chipText(ref: TextReference): string;
60
- /** Cut segments into screen lines no wider than `width` columns, breaking at spaces where it can. */
62
+ /**
63
+ * Cut segments into screen lines no wider than `width` columns, breaking at
64
+ * spaces where it can. Each word is measured once and a word longer than a
65
+ * line is cut by grapheme, so the cost is linear in the text and an emoji or
66
+ * a combining mark is never split (0.3.0 measured the whole remaining line for
67
+ * every piece: 13 s for one 500 KB line).
68
+ */
61
69
  export declare function wrapSegments(segments: Segment[], width: number): Segment[][];
62
70
  /** A text file as wrapped screen lines, with every reference found and marked. */
63
71
  export declare function fileView(content: string, width: number): FileView;
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACzE,OAAO,EAAmC,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEhH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,eAAe,CAAA;CAC1B;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,UAAU,CAY7D;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAOlE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAoBnF;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAE,CAIhH;AASD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAS9E;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAI3D;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAMD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;AAExE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,IAAI,EAAE,aAAa,EAAE,CAAA;CACtB;AAID,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAKnD;AAgBD,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EAAE,CA4C5E;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAiBjE;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjE"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACzE,OAAO,EAAmC,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGhH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,eAAe,CAAA;IACzB,oGAAoG;IACpG,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAA;CACjC;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,oBAAoB,EAAE,QAAQ,GAAE,QAAQ,GAAG,WAAsB,GAAG,UAAU,CAa1G;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAOlE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAoBnF;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAE,CAIhH;AASD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAS9E;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAI3D;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAMD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;AAExE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,IAAI,EAAE,aAAa,EAAE,CAAA;CACtB;AAID,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAEnD;AA0BD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EAAE,CA0C5E;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAmBjE;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjE"}
package/dist/model.js CHANGED
@@ -5,17 +5,19 @@
5
5
  */
6
6
  import stringWidth from "string-width";
7
7
  import { findTextReferences, readEpisode } from "@miadi/inquiry-weave";
8
- export function toRow(entry) {
8
+ import { clean, cleanLine } from "./text.js";
9
+ export function toRow(entry, audience = "public") {
9
10
  return {
10
11
  name: entry.name,
11
12
  number: entry.number,
12
13
  date: entry.date,
13
- title: entry.title ?? entry.slug ?? entry.name,
14
- slug: entry.slug,
15
- type: entry.type,
16
- status: entry.status,
14
+ title: cleanLine(entry.title ?? entry.slug ?? entry.name),
15
+ slug: entry.slug === undefined ? undefined : cleanLine(entry.slug),
16
+ type: entry.type === undefined ? undefined : cleanLine(entry.type),
17
+ status: entry.status === undefined ? undefined : cleanLine(entry.status),
17
18
  structured: Boolean(entry.structured),
18
19
  readings: readEpisode(entry),
20
+ audience,
19
21
  };
20
22
  }
21
23
  /** Newest first; folders without a number last, by name. */
@@ -99,9 +101,13 @@ export function clamp(value, count) {
99
101
  const shortId = (id) => (id.length > 22 ? `${id.slice(0, 20)}…` : id);
100
102
  /** The words a chip shows: the author's label, or what the reference names. */
101
103
  export function chipText(ref) {
104
+ return cleanLine(rawChipText(ref));
105
+ }
106
+ function rawChipText(ref) {
102
107
  if (ref.kind === "chronicle")
103
108
  return `↗ ${ref.label ?? ref.uri.replace(/^miadi-chronicle:(\/\/)?/i, "ep ")}`;
104
- const id = ref.uri.replace(/^miadi-(ceremony|circle):/i, "");
109
+ // A circle's id already begins with `circle:`; the chip says it once.
110
+ const id = ref.uri.replace(/^miadi-(ceremony|circle):/i, "").replace(/^(ceremony|circle):/i, "");
105
111
  const mark = ref.kind === "ceremony" ? "◆" : "○";
106
112
  return `${mark} ${ref.label ?? `${ref.kind} ${shortId(id)}`}`;
107
113
  }
@@ -113,27 +119,34 @@ function lineSegments(line, refs, lineStart, style) {
113
119
  return;
114
120
  const from = ref.start - lineStart;
115
121
  if (from > at)
116
- segments.push({ text: line.slice(at, from), style });
122
+ segments.push({ text: clean(line.slice(at, from)), style });
117
123
  segments.push({ text: chipText(ref), style: "ref", ref: index });
118
124
  at = ref.end - lineStart;
119
125
  });
120
126
  if (at < line.length || segments.length === 0)
121
- segments.push({ text: line.slice(at), style });
127
+ segments.push({ text: clean(line.slice(at)), style });
122
128
  return segments;
123
129
  }
124
- /** Cut segments into screen lines no wider than `width` columns, breaking at spaces where it can. */
130
+ const graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
131
+ /**
132
+ * Cut segments into screen lines no wider than `width` columns, breaking at
133
+ * spaces where it can. Each word is measured once and a word longer than a
134
+ * line is cut by grapheme, so the cost is linear in the text and an emoji or
135
+ * a combining mark is never split (0.3.0 measured the whole remaining line for
136
+ * every piece: 13 s for one 500 KB line).
137
+ */
125
138
  export function wrapSegments(segments, width) {
126
139
  const limit = Math.max(8, width);
127
140
  const lines = [[]];
128
141
  let used = 0;
129
- const push = (segment) => {
142
+ const append = (text, segment, w) => {
130
143
  const last = lines[lines.length - 1];
131
144
  const prev = last[last.length - 1];
132
145
  if (prev && prev.style === segment.style && prev.ref === segment.ref)
133
- prev.text += segment.text;
146
+ prev.text += text;
134
147
  else
135
- last.push({ ...segment });
136
- used += stringWidth(segment.text);
148
+ last.push({ ...segment, text });
149
+ used += w;
137
150
  };
138
151
  const newline = () => {
139
152
  lines.push([]);
@@ -142,33 +155,28 @@ export function wrapSegments(segments, width) {
142
155
  for (const segment of segments) {
143
156
  if (segment.style === "ref") {
144
157
  // A chip is never split.
145
- if (used > 0 && used + stringWidth(segment.text) > limit)
158
+ const w = stringWidth(segment.text);
159
+ if (used > 0 && used + w > limit)
146
160
  newline();
147
- push(segment);
161
+ append(segment.text, segment, w);
148
162
  continue;
149
163
  }
150
164
  for (const word of segment.text.split(/(?<= )/)) {
151
- let rest = word;
152
- while (rest) {
153
- const room = limit - used;
154
- const w = stringWidth(rest);
155
- if (w <= room) {
156
- push({ ...segment, text: rest });
157
- rest = "";
158
- }
159
- else if (used > 0 && w <= limit) {
165
+ const w = stringWidth(word);
166
+ if (used + w <= limit) {
167
+ append(word, segment, w);
168
+ continue;
169
+ }
170
+ if (w <= limit) {
171
+ newline();
172
+ append(word, segment, w);
173
+ continue;
174
+ }
175
+ for (const { segment: grapheme } of graphemeSegmenter.segment(word)) {
176
+ const gw = stringWidth(grapheme);
177
+ if (used > 0 && used + gw > limit)
160
178
  newline();
161
- }
162
- else {
163
- // A word longer than a whole line is cut where the line ends.
164
- let cut = 0;
165
- while (cut < rest.length && stringWidth(rest.slice(0, cut + 1)) <= room)
166
- cut++;
167
- push({ ...segment, text: rest.slice(0, Math.max(1, cut)) });
168
- rest = rest.slice(Math.max(1, cut));
169
- if (rest)
170
- newline();
171
- }
179
+ append(grapheme, segment, gw);
172
180
  }
173
181
  }
174
182
  }
@@ -187,7 +195,9 @@ export function fileView(content, width) {
187
195
  if (fenceLine)
188
196
  fence = !fence;
189
197
  for (const segments of wrapSegments(lineSegments(line, refs, offset, style), width)) {
190
- lines.push({ segments, source: index + 1 });
198
+ // An empty line still takes a row, or paragraphs run together.
199
+ const empty = segments.every((segment) => segment.text.length === 0);
200
+ lines.push({ segments: empty ? [{ text: " ", style }] : segments, source: index + 1 });
191
201
  }
192
202
  offset += raw.length + 1;
193
203
  });