bible-note 0.4.4 → 0.5.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/README.md +45 -5
- package/knowledge/development.md +1927 -0
- package/knowledge/ui-rag.md +2130 -0
- package/package.json +14 -2
- package/types/BibleNote.d.ts +62 -0
- package/types/LookupManager.d.ts +71 -0
- package/types/bibleNoteHelpers.d.ts +105 -0
- package/types/editorStateStorage.d.ts +5 -0
- package/types/footerActionButtons.d.ts +19 -0
- package/types/lookupTypes.d.ts +74 -0
- package/types/params/BibleNoteSettings.d.ts +10 -0
- package/types/params/colorScheme.d.ts +8 -0
- package/types/storageManager.d.ts +20 -0
- package/types/utils/filePathResolver.d.ts +7 -0
- package/types/utils/fontFamilyOptions.d.ts +6 -0
|
@@ -0,0 +1,1927 @@
|
|
|
1
|
+
# BibleNote — development guide
|
|
2
|
+
|
|
3
|
+
> Generated by `npm run pack` for **bible-note@0.5.0** from the hand-written topics in `knowledge/development/` and the package's own type declarations. Do not edit this file — edit the sources and re-run the pack. End-user help for the editor UI lives in `ui-rag.md` next to it.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
1. [Overview](#dev-overview) — What the package is, what it bundles, and what the host supplies.
|
|
8
|
+
2. [Installation and stylesheets](#dev-installation-and-stylesheets) — Peer dependencies and the stylesheet order the editor needs.
|
|
9
|
+
3. [Quick start](#dev-quick-start) — A complete minimal host, plus the optional hooks.
|
|
10
|
+
4. [Datasets and lookup managers](#dev-datasets-and-lookup-managers) — Feeding name and location data, translated datasets, per-dataset styling, building your own lookup UI.
|
|
11
|
+
5. [Persistence and storage](#dev-persistence-and-storage) — Where the note and the editor's own state are stored, and when.
|
|
12
|
+
6. [Host integration](#dev-host-integration) — Fonts, media files, Excalidraw libraries, the settings panel, footer modes and the Electron file bridge.
|
|
13
|
+
7. [Working on the editor UI](#dev-working-on-the-editor-ui) — For contributors — repository layout, the plugin tree, the dev loop, verifying changes in the browser.
|
|
14
|
+
8. [Building and releasing the package](#dev-building-and-releasing-the-package) — What npm run pack does, the hand-maintained files, versioning and publishing.
|
|
15
|
+
9. [API reference](#dev-api-reference) — Every export of the package, generated from its type declarations.
|
|
16
|
+
|
|
17
|
+
<a id="dev-overview"></a>
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
`bible-note` is a Bible-study note editor packaged as a drop-in component. It
|
|
22
|
+
extends the [Lexical playground](https://playground.lexical.dev/) editor with
|
|
23
|
+
Bible-specific features:
|
|
24
|
+
|
|
25
|
+
- person (`@`) and place (`#`) mentions backed by the host's datasets, with
|
|
26
|
+
hover cards and a draggable advanced panel;
|
|
27
|
+
- Bible verse mentions created by pasting verse text after `^`;
|
|
28
|
+
- a lookup panel for browsing both datasets;
|
|
29
|
+
- sticky notes, comments, Excalidraw drawings, equations, tables, column
|
|
30
|
+
layouts, collapsibles, media and embeds;
|
|
31
|
+
- a footer with Word (`.docx`) import and export, a lossless JSON backup, print
|
|
32
|
+
with page-size preview, read-only mode, and buttons the host adds itself.
|
|
33
|
+
|
|
34
|
+
The MIT license and Meta's copyright carry over from upstream Lexical.
|
|
35
|
+
|
|
36
|
+
### The pieces
|
|
37
|
+
|
|
38
|
+
| Piece | What it is |
|
|
39
|
+
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
40
|
+
| `BibleNote` | The editor. `new BibleNote(props)` then `render(element)`. It mounts its own React root, so the host does not have to be a React app. |
|
|
41
|
+
| `NamesLookupManager`, `LocationsLookupManager` | The datasets behind every mention, hover card, panel and the lookup panel. They have no editor dependency — a host can use them on their own. |
|
|
42
|
+
| `BibleNoteSettings` | The optional settings panel (gear button), passed to `render`. |
|
|
43
|
+
| `bible-note/styles.css` | The one stylesheet: editor, KaTeX and Excalidraw rules. |
|
|
44
|
+
| `bible-note/knowledge/development.md` | This guide. |
|
|
45
|
+
| `bible-note/knowledge/ui-rag.md` | End-user help for the editor UI, chunked for a retrieval pipeline. |
|
|
46
|
+
|
|
47
|
+
### Bundled vs. supplied by the host
|
|
48
|
+
|
|
49
|
+
React, React DOM, Bootstrap and bootstrap-icons are **peer dependencies**:
|
|
50
|
+
|
|
51
|
+
- React must be the host's copy so there is a single instance — a second copy
|
|
52
|
+
breaks hooks.
|
|
53
|
+
- Bootstrap and bootstrap-icons are global stylesheets. Shipping them inside the
|
|
54
|
+
package would fix their place in the host's cascade and pin a version the host
|
|
55
|
+
could not theme, so the host installs and imports them itself.
|
|
56
|
+
|
|
57
|
+
Everything else — Lexical, Excalidraw, KaTeX, Shiki, the Word converters — is
|
|
58
|
+
bundled. Lexical and Excalidraw are bundled on purpose: the editor is coupled to
|
|
59
|
+
their module instances, and a separately resolved copy could be a different
|
|
60
|
+
instance than the one the bundle talks to. `use-sync-external-store` is the one
|
|
61
|
+
runtime dependency, left external only so the consumer's bundler converts it
|
|
62
|
+
correctly.
|
|
63
|
+
|
|
64
|
+
The package ships **no datasets**. The host fetches the name and location maps
|
|
65
|
+
(and, optionally, verse text) and hands them to the editor.
|
|
66
|
+
|
|
67
|
+
### Lifecycle in one paragraph
|
|
68
|
+
|
|
69
|
+
Construct `BibleNote` with the datasets, the storage callbacks and any optional
|
|
70
|
+
host hooks; call `render(container)`. Before the first render the editor reads
|
|
71
|
+
its own state (settings, comments, read-only mode, zoom) from `storageManager`
|
|
72
|
+
and the note itself from `loadData`. From then on every document change goes to
|
|
73
|
+
`saveData`, and every other state change to `storageManager`. Methods such as
|
|
74
|
+
`content`, `addText` and `searchText` may be called before `render`; writes are
|
|
75
|
+
queued until the editor mounts. `unmount()` tears the React root down; the
|
|
76
|
+
instance can be rendered again.
|
|
77
|
+
|
|
78
|
+
<a id="dev-installation-and-stylesheets"></a>
|
|
79
|
+
|
|
80
|
+
## Installation and stylesheets
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install bible-note react react-dom bootstrap bootstrap-icons
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The peer ranges are those in the package's `package.json`: React and React DOM
|
|
87
|
+
`^19.2.8`, Bootstrap `^5.3.8`, bootstrap-icons `^1.13.1`.
|
|
88
|
+
|
|
89
|
+
### Stylesheet order
|
|
90
|
+
|
|
91
|
+
Import three stylesheets, in this order — Bootstrap first, then the icon font,
|
|
92
|
+
then the editor's own stylesheet last so its overrides win:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
96
|
+
import 'bootstrap-icons/font/bootstrap-icons.css';
|
|
97
|
+
import 'bible-note/styles.css';
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Skipping the first two does not throw — it renders a broken editor: the toolbar
|
|
101
|
+
and footer lose their layout, and with no `@font-face` for the icon font every
|
|
102
|
+
`bi bi-*` glyph renders as tofu. `bible-note/styles.css` needs no configuration.
|
|
103
|
+
|
|
104
|
+
The package's `sideEffects` lists `**/*.css`, so bundlers keep the
|
|
105
|
+
`bible-note/styles.css` import; if a custom build strips CSS side effects, the
|
|
106
|
+
editor renders unstyled.
|
|
107
|
+
|
|
108
|
+
### Module formats and entry points
|
|
109
|
+
|
|
110
|
+
| Import | Resolves to |
|
|
111
|
+
| ----------------------------------------------------------------------- | ---------------------------------------------- |
|
|
112
|
+
| `import … from 'bible-note'` | ES module bundle, with TypeScript declarations |
|
|
113
|
+
| `require('bible-note')` | CommonJS bundle |
|
|
114
|
+
| `bible-note/styles.css` | the stylesheet |
|
|
115
|
+
| `bible-note/knowledge/development.md`, `bible-note/knowledge/ui-rag.md` | the knowledge files |
|
|
116
|
+
|
|
117
|
+
Shiki grammars, Excalidraw and KaTeX load lazily as separate chunks, so the
|
|
118
|
+
initial bundle stays small and those parts load the first time they are used.
|
|
119
|
+
|
|
120
|
+
### Colour scheme
|
|
121
|
+
|
|
122
|
+
The editor themes itself through classes on `document.body`
|
|
123
|
+
(`playground-theme-light` / `playground-theme-dark`) and Bootstrap's
|
|
124
|
+
`data-bs-theme` attribute. Call `bibleNote.setColorScheme('dark')`, or let the
|
|
125
|
+
settings panel's Dark Mode switch do it. `applyBibleNoteColorScheme` and
|
|
126
|
+
`clearBibleNoteColorScheme` are the bare DOM steps for a host that manages the
|
|
127
|
+
body classes itself.
|
|
128
|
+
|
|
129
|
+
<a id="dev-quick-start"></a>
|
|
130
|
+
|
|
131
|
+
## Quick start
|
|
132
|
+
|
|
133
|
+
A minimal host: the stylesheets, two datasets, browser storage, and a render.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
137
|
+
import 'bootstrap-icons/font/bootstrap-icons.css';
|
|
138
|
+
import 'bible-note/styles.css';
|
|
139
|
+
|
|
140
|
+
import {
|
|
141
|
+
BibleNote,
|
|
142
|
+
BibleNoteSettings,
|
|
143
|
+
createBrowserStorageManager,
|
|
144
|
+
EDITOR_STATE_LOCAL_STORAGE_KEY,
|
|
145
|
+
LocationsLookupManager,
|
|
146
|
+
NamesLookupManager,
|
|
147
|
+
} from 'bible-note';
|
|
148
|
+
|
|
149
|
+
const [namesMap, locationsMap] = await Promise.all([
|
|
150
|
+
fetch('data/KJV/namesMap.json').then((res) => res.json()),
|
|
151
|
+
fetch('data/KJV/locationsMap.json').then((res) => res.json()),
|
|
152
|
+
]);
|
|
153
|
+
|
|
154
|
+
const storageManager = createBrowserStorageManager();
|
|
155
|
+
|
|
156
|
+
const bibleNote = new BibleNote({
|
|
157
|
+
namesLookupManager: NamesLookupManager.fromRawDataset({ en: namesMap }, 'en'),
|
|
158
|
+
locationsLookupManager: LocationsLookupManager.fromRawDataset(
|
|
159
|
+
{ en: locationsMap },
|
|
160
|
+
'en',
|
|
161
|
+
),
|
|
162
|
+
getLangCode: (text) => (/[ក-]/u.test(text) ? 'km' : 'en'),
|
|
163
|
+
editorExtraFontFamilies: [],
|
|
164
|
+
stickyNoteExtraFontFamilies: [],
|
|
165
|
+
storageManager,
|
|
166
|
+
// The note itself: keep it wherever the host keeps documents.
|
|
167
|
+
loadData: async () =>
|
|
168
|
+
(await storageManager.getSetting<string>(EDITOR_STATE_LOCAL_STORAGE_KEY)) ??
|
|
169
|
+
'',
|
|
170
|
+
saveData: async (data) => {
|
|
171
|
+
if (data === '') {
|
|
172
|
+
await storageManager.deleteSetting(EDITOR_STATE_LOCAL_STORAGE_KEY);
|
|
173
|
+
} else {
|
|
174
|
+
await storageManager.setSetting(EDITOR_STATE_LOCAL_STORAGE_KEY, data);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
bibleNote.render(document.getElementById('root')!, {
|
|
180
|
+
settings: (
|
|
181
|
+
<BibleNoteSettings
|
|
182
|
+
setColorScheme={(mode) => bibleNote.setColorScheme(mode)}
|
|
183
|
+
/>
|
|
184
|
+
),
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The `settings` option takes a React element, so a `.tsx` file is the natural
|
|
189
|
+
host. A host without JSX can pass
|
|
190
|
+
`React.createElement(BibleNoteSettings, { setColorScheme })` or leave `settings`
|
|
191
|
+
out — the editor then simply has no settings panel.
|
|
192
|
+
|
|
193
|
+
The required props are the two managers, `getLangCode`,
|
|
194
|
+
`editorExtraFontFamilies`, `stickyNoteExtraFontFamilies`, `storageManager`,
|
|
195
|
+
`loadData` and `saveData`. Everything else is optional and switches a feature
|
|
196
|
+
on; the API reference lists each prop.
|
|
197
|
+
|
|
198
|
+
### Working with a mounted editor
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
bibleNote.content; // serialized editor state (JSON string)
|
|
202
|
+
bibleNote.content = savedState; // replace the document; '' clears it
|
|
203
|
+
bibleNote.addText('^'); // insert as if pasted at the caret
|
|
204
|
+
bibleNote.addText('(KJV) Genesis 1:1\n(1): In the beginning God created…');
|
|
205
|
+
bibleNote.isReadOnly = true; // lock — the user cannot unlock it
|
|
206
|
+
bibleNote.searchText('Moses'); // open the find bar on a query; null closes it
|
|
207
|
+
bibleNote.getIsFocusing(); // is the caret in the editor right now?
|
|
208
|
+
BibleNote.getAllShortVersesFromText(bibleNote.content); // ['GEN 1:1', …]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The two `addText` calls above create a Bible verse mention: verse text pasted
|
|
212
|
+
right after a `^` becomes a verse mention instead of a collapsible block.
|
|
213
|
+
|
|
214
|
+
### Host footer buttons
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
bibleNote.prependFooterActionButton({
|
|
218
|
+
id: 'open-in-app',
|
|
219
|
+
description: 'Open in my app',
|
|
220
|
+
shortcutKey: 'Ctrl+Shift+K',
|
|
221
|
+
children: (
|
|
222
|
+
<button className="action-button" onClick={openInApp}>
|
|
223
|
+
<i className="bi bi-box-arrow-up-right" />
|
|
224
|
+
</button>
|
|
225
|
+
),
|
|
226
|
+
});
|
|
227
|
+
bibleNote.removeFooterActionButton('open-in-app');
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`prepend…` places a button before the built-in footer buttons, `append…` after
|
|
231
|
+
them. Re-adding an `id` replaces that button in place. `description` becomes the
|
|
232
|
+
tooltip when the element has no `title`; `shortcutKey` clicks the button from
|
|
233
|
+
anywhere in the page and is shown in the tooltip. Give the button the
|
|
234
|
+
`action-button` class to match the built-in ones.
|
|
235
|
+
|
|
236
|
+
### Mounting without auto-mount
|
|
237
|
+
|
|
238
|
+
`render` can be called any time after construction and again later — each call
|
|
239
|
+
unmounts the previous root first. Call `unmount()` when the host view goes away;
|
|
240
|
+
the instance keeps its props and footer buttons for the next `render`.
|
|
241
|
+
|
|
242
|
+
<a id="dev-datasets-and-lookup-managers"></a>
|
|
243
|
+
|
|
244
|
+
## Datasets and lookup managers
|
|
245
|
+
|
|
246
|
+
The editor ships no data. Every person and place it can mention comes from two
|
|
247
|
+
managers the host builds:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const names = NamesLookupManager.fromRawDataset({ en: namesMap }, 'en');
|
|
251
|
+
const locations = LocationsLookupManager.fromRawDataset(
|
|
252
|
+
{ en: locationsMap },
|
|
253
|
+
'en',
|
|
254
|
+
);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`fromRawDataset` takes the generated dataset files exactly as fetched —
|
|
258
|
+
`namesMap.json` (`{ version, namesMap, childrenTree, versePersonsMap }`) and
|
|
259
|
+
`locationsMap.json` — keyed by a language code, and normalizes them. Records
|
|
260
|
+
can be an id-keyed object or an array; anything unrecognised is dropped rather
|
|
261
|
+
than trusted. Use the plain constructors only when you already hold normalized
|
|
262
|
+
`MentionNameMatch` / `MentionLocationMatch` records.
|
|
263
|
+
|
|
264
|
+
A manager may hold several languages (`{ en: …, km: … }`); `defaultLang` picks
|
|
265
|
+
the one the editor uses, and every query method takes an optional `lang`. The
|
|
266
|
+
constructor throws when the default language is missing from the map.
|
|
267
|
+
|
|
268
|
+
### Records
|
|
269
|
+
|
|
270
|
+
A name record (`MentionNameMatch`) carries the name, a one-line `title`, a
|
|
271
|
+
`description`, family links (`parents`, `children`, `spouses`, `siblings`,
|
|
272
|
+
`cousin` — record ids), `locations` (location ids), `verses`, `links`,
|
|
273
|
+
`wikipedia`, `gender`, `age`, `years` and a `type` (`person`, `group`, `deity`,
|
|
274
|
+
`place`, `concept`, `month`, `supernatural`, `life`, `unknown`). A location
|
|
275
|
+
record (`MentionLocationMatch`) carries `type` (`city`, `region`, `mountain`, …),
|
|
276
|
+
`coordinates`, `modernIdentification`, `relatedLocations`, `uncertainty` and the
|
|
277
|
+
same text, verse and link fields.
|
|
278
|
+
|
|
279
|
+
`title` and `description` may contain inline reference links the UI renders as
|
|
280
|
+
clickable references:
|
|
281
|
+
|
|
282
|
+
| Link | Points to |
|
|
283
|
+
| ------------------------------------ | ----------------- |
|
|
284
|
+
| `[Amram](name-id://<id>)` | a name record |
|
|
285
|
+
| `[Egypt](location-id://<id>)` | a location record |
|
|
286
|
+
| `[Genesis 1:1](verse-key://GEN 1:1)` | a verse |
|
|
287
|
+
| `[Genesis](book-key://GEN)` | a book |
|
|
288
|
+
| `[Genesis 14](chapter-key://GEN 14)` | a chapter |
|
|
289
|
+
|
|
290
|
+
Verse keys are short keys — a book code plus chapter and verse (`GEN 1:1`,
|
|
291
|
+
`1SA 17:1-4`). Ranges are stored collapsed, so the length of `verses` is not a
|
|
292
|
+
verse count.
|
|
293
|
+
|
|
294
|
+
`matterRange` ranks importance: `0` is the most important record and larger is
|
|
295
|
+
less important; records without a rank sort last. Every listing and every tie in
|
|
296
|
+
a search is ordered by it, then alphabetically.
|
|
297
|
+
|
|
298
|
+
### Searching
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
names.searchNames('Mos', { limit: 20 }); // ranked MentionNameMatch[]
|
|
302
|
+
names.searchNames('', { type: 'deity' }); // filter applies before limit
|
|
303
|
+
names.searchNamesPagination({ query: 'Mos', page: 2, pageSize: 20 });
|
|
304
|
+
names.getRecordById(id);
|
|
305
|
+
names.getRecordsByIds(record.children);
|
|
306
|
+
names.getRecordsByName('Zechariah'); // names are not unique
|
|
307
|
+
names.searchByShortVerse('EXO 6:23'); // the names that verse prints
|
|
308
|
+
names.nameTypes; // types present, most common first
|
|
309
|
+
locations.searchLocations('Jer', { limit: 10 });
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Search is a case-insensitive substring match on the name, the KJV English name
|
|
313
|
+
and the former name (`oldName`), ranked exact, then prefix, then substring, then
|
|
314
|
+
by importance. An empty query lists everything in importance order. Indexes are
|
|
315
|
+
built lazily per language on first use and recent queries are cached.
|
|
316
|
+
|
|
317
|
+
`searchByShortVerse` needs the dataset's verse map (`versePersonsMap` /
|
|
318
|
+
`verseLocationsMap`, both included in the generated files).
|
|
319
|
+
|
|
320
|
+
### Translated datasets
|
|
321
|
+
|
|
322
|
+
A record in a translated dataset (the Khmer and French mirrors of the KJV data)
|
|
323
|
+
carries its translated `name` plus the KJV English name in `kjvName`. The
|
|
324
|
+
managers index both, so the same manager answers a query in either language and
|
|
325
|
+
ranks an English hit exactly like a native one:
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
const names = NamesLookupManager.fromRawDataset({ km: khmerNamesMap }, 'km');
|
|
329
|
+
names.searchNames('Genesis'); // finds the record named "លោកុប្បត្តិ"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The built-in UI shows the English name beside the translated one in the lookup
|
|
333
|
+
panel, the mention typeahead, the hover card and the advanced panel.
|
|
334
|
+
`getMentionKjvName(record)` is the rule it uses: the English name, or `null`
|
|
335
|
+
when there is nothing to add. An untranslated dataset carries no `kjvName`, and
|
|
336
|
+
all of this is a no-op for it.
|
|
337
|
+
|
|
338
|
+
### Styling a dataset
|
|
339
|
+
|
|
340
|
+
Both managers take an optional third argument: a React-style CSS object merged
|
|
341
|
+
into every surface that renders that dataset — the typeahead popup, the hover
|
|
342
|
+
card, the advanced panel and the lookup panel's list and search box. Use it to
|
|
343
|
+
give a dataset in another script its own font:
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
const locations = LocationsLookupManager.fromRawDataset(
|
|
347
|
+
{ km: khmerLocationsMap },
|
|
348
|
+
'km',
|
|
349
|
+
{ fontFamily: 'Battambang, serif' },
|
|
350
|
+
);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The two managers are styled independently. `manager.style` can be read and
|
|
354
|
+
reassigned, but plugins read it as they render, so a change only shows up on the
|
|
355
|
+
next render. A hover card's own positioning always wins over the style.
|
|
356
|
+
|
|
357
|
+
### Verse text
|
|
358
|
+
|
|
359
|
+
The package bundles no Bible text. Three optional props let the host supply it:
|
|
360
|
+
|
|
361
|
+
- `shortToVerseData(shortKey)` → `{ title, fullText, style? }` — labels verse
|
|
362
|
+
lists in the mention panels and fills the Word export's References appendix.
|
|
363
|
+
- `verseFullTextToListShorts(fullText)` → short keys — lets a verse's advanced
|
|
364
|
+
panel show the people and places that verse mentions.
|
|
365
|
+
- `changeBibleKey(event, fullText)` — makes the version label in a verse panel a
|
|
366
|
+
button that opens the same verse in another version.
|
|
367
|
+
|
|
368
|
+
`fullText` is the shape the editor accepts when Bible text is pasted after `^`:
|
|
369
|
+
a title line such as `(KJV) Genesis 1:1`, then one line per verse such as
|
|
370
|
+
`(1): In the beginning…`.
|
|
371
|
+
|
|
372
|
+
`BibleNote.getAllShortVersesFromText(text)` goes the other way: it lists every
|
|
373
|
+
verse a note refers to — verse mentions and references typed in the prose — as
|
|
374
|
+
short keys, in document order without duplicates. Ranges inside one chapter are
|
|
375
|
+
expanded verse by verse; a range crossing chapters keeps only its endpoints.
|
|
376
|
+
|
|
377
|
+
### Your own lookup UI
|
|
378
|
+
|
|
379
|
+
The managers carry no editor dependency. To build a custom mention picker or a
|
|
380
|
+
search page, construct them and call their methods — no `BibleNote` import is
|
|
381
|
+
needed, and the results are exactly what the built-in UI shows.
|
|
382
|
+
|
|
383
|
+
<a id="dev-persistence-and-storage"></a>
|
|
384
|
+
|
|
385
|
+
## Persistence and storage
|
|
386
|
+
|
|
387
|
+
The editor splits what it stores into two channels.
|
|
388
|
+
|
|
389
|
+
| Channel | Carries | Host hook |
|
|
390
|
+
| ------------ | ----------------------------------------------------- | ----------------------- |
|
|
391
|
+
| The note | the serialized Lexical editor state of the document | `loadData` / `saveData` |
|
|
392
|
+
| Editor state | settings, comments, read-only mode, zoom, panel state | `storageManager` |
|
|
393
|
+
|
|
394
|
+
### The note: `loadData` and `saveData`
|
|
395
|
+
|
|
396
|
+
`saveData(data)` is called on every change to the document with the serialized
|
|
397
|
+
editor state — a JSON string, the same one `bibleNote.content` returns. It is
|
|
398
|
+
called with `''` when a stored note turns out to be unreadable and is discarded.
|
|
399
|
+
`loadData()` returns that string (or `null` / `''` for an empty editor) and may
|
|
400
|
+
be async. Store it wherever the host keeps documents: a file, a database row, a
|
|
401
|
+
server.
|
|
402
|
+
|
|
403
|
+
Because `saveData` runs on every change, debounce it on the host side if the
|
|
404
|
+
store is expensive. The string is also the lossless format: the footer's Export
|
|
405
|
+
button downloads it, Import reads it back, and assigning `bibleNote.content`
|
|
406
|
+
replaces the document with it.
|
|
407
|
+
|
|
408
|
+
### Editor state: `storageManager`
|
|
409
|
+
|
|
410
|
+
A `BibleNoteStorageManager` is three async methods — `getSetting`, `setSetting`,
|
|
411
|
+
`deleteSetting` — over string values. `createBrowserStorageManager()` is the
|
|
412
|
+
`localStorage` implementation; an Electron or server-backed host can implement
|
|
413
|
+
the same three methods over its own store.
|
|
414
|
+
|
|
415
|
+
Before the editor first renders it reads every key in
|
|
416
|
+
`BIBLE_NOTE_STORAGE_MANAGER_KEYS` from the storage manager, then serves reads
|
|
417
|
+
from memory; every write goes straight through to `setSetting`, fire-and-forget.
|
|
418
|
+
The keys:
|
|
419
|
+
|
|
420
|
+
| Key | Holds |
|
|
421
|
+
| -------------------------------------------- | -------------------------------------------------------------------------- |
|
|
422
|
+
| `lexical-playground-settings` | the settings panel's switches |
|
|
423
|
+
| `lexical-playground-editor-state` | the note — routed to `loadData` / `saveData`, never to the storage manager |
|
|
424
|
+
| `lexical-playground-comments` | comment threads |
|
|
425
|
+
| `lexical-playground-comments-panel-open` | whether the comments panel is open |
|
|
426
|
+
| `lexical-playground-block-text-links` | the "link block text" connections |
|
|
427
|
+
| `lexical-playground-read-only-mode` | whether the user locked the note |
|
|
428
|
+
| `lexical-playground-insert-character-picker` | the Emoji & HTML Character picker's state |
|
|
429
|
+
| `lexical-playground-editor-zoom-percent` | the zoom level |
|
|
430
|
+
|
|
431
|
+
The `lexical-playground-` prefix is inherited from the upstream playground; keep
|
|
432
|
+
it when migrating stored data.
|
|
433
|
+
|
|
434
|
+
The editor-state key is exported as `EDITOR_STATE_LOCAL_STORAGE_KEY`. The quick
|
|
435
|
+
start reuses it to keep the note in the same store as everything else, which is
|
|
436
|
+
fine for a single-note host; a multi-note host keeps each note under its own key
|
|
437
|
+
or file and returns the right one from `loadData`.
|
|
438
|
+
|
|
439
|
+
### Read-only mode
|
|
440
|
+
|
|
441
|
+
The user can lock a note from the footer, and that choice persists under
|
|
442
|
+
`lexical-playground-read-only-mode`. A host can force it: `bibleNote.isReadOnly
|
|
443
|
+
= true` locks the note, turns the footer button into **Read-Only Mode Locked**,
|
|
444
|
+
and the user cannot unlock it until the host assigns `false`.
|
|
445
|
+
|
|
446
|
+
### Share links
|
|
447
|
+
|
|
448
|
+
Outside an app (`isOnApp` false), the footer's **Share as Link** button encodes
|
|
449
|
+
the note into the page URL's `editor-state` query parameter, optionally
|
|
450
|
+
password-protected; opening such a URL loads that note. Hosts that embed the
|
|
451
|
+
editor in an app set `isOnApp: true`, which hides the button.
|
|
452
|
+
|
|
453
|
+
<a id="dev-host-integration"></a>
|
|
454
|
+
|
|
455
|
+
## Host integration
|
|
456
|
+
|
|
457
|
+
Every optional prop switches on one integration. This topic groups them by
|
|
458
|
+
feature; the API reference has the exact signatures.
|
|
459
|
+
|
|
460
|
+
### Fonts and languages
|
|
461
|
+
|
|
462
|
+
- `editorExtraFontFamilies: [['Battambang', 'km'], …]` adds fonts to the
|
|
463
|
+
toolbar's font menu and to Excalidraw, each tagged with a language code. The
|
|
464
|
+
host loads the font faces itself (a `@font-face` or a webfont link).
|
|
465
|
+
- `getLangCode(text)` returns a language code for a piece of text. When it
|
|
466
|
+
returns something other than `'en'`, pasted Bible text and Excalidraw text
|
|
467
|
+
switch to the first extra font registered for that language — so Khmer verse
|
|
468
|
+
text renders in a Khmer font automatically.
|
|
469
|
+
- `stickyNoteExtraFontFamilies: ['"Fasthand"', …]` adds CSS font-family values
|
|
470
|
+
to the sticky-note font picker.
|
|
471
|
+
- A lookup manager's style object (`{ fontFamily }`) styles one dataset across
|
|
472
|
+
the mention UI; see the datasets topic.
|
|
473
|
+
|
|
474
|
+
### Media files
|
|
475
|
+
|
|
476
|
+
By default a picked or dropped image, video, audio or PDF is embedded in the
|
|
477
|
+
note as a data URL. Two hooks change that:
|
|
478
|
+
|
|
479
|
+
- `resolveFilePath(file, { source })` returns a path or URL to store instead —
|
|
480
|
+
for example the file's location on disk in Electron, or an upload URL. `source`
|
|
481
|
+
is `'drop'` (dropped or pasted) or `'file-input'` (picked in the media dialog).
|
|
482
|
+
Return `null` to fall back to embedding.
|
|
483
|
+
- `revealFile(path)` shows a local file to the user (Electron:
|
|
484
|
+
`shell.showItemInFolder`). With it, a selected media item whose source is a
|
|
485
|
+
local path gets a reveal button.
|
|
486
|
+
|
|
487
|
+
### Excalidraw libraries
|
|
488
|
+
|
|
489
|
+
The editor bundles a Christian-themed Excalidraw library. `excalidrawLibraryItems`
|
|
490
|
+
adds library items of the host's own. To persist libraries the user imports
|
|
491
|
+
inside Excalidraw, implement the trio:
|
|
492
|
+
|
|
493
|
+
- `excalidrawSaveLibrariesFile(json)` — store one serialized library;
|
|
494
|
+
- `excalidrawLoadLibrariesFileList()` — return the stored libraries, read when
|
|
495
|
+
the Excalidraw editor opens;
|
|
496
|
+
- `excalidrawClearLibrariesFileList()` — forget them all.
|
|
497
|
+
|
|
498
|
+
The demo host keeps the list as a JSON array in `localStorage`.
|
|
499
|
+
|
|
500
|
+
### Settings panel
|
|
501
|
+
|
|
502
|
+
`render(el, { settings: <BibleNoteSettings setColorScheme={…} /> })` adds the
|
|
503
|
+
gear button and its switches. Without `settings` there is no settings panel and
|
|
504
|
+
every setting keeps its default. `settingsContainerElement` portals the panel
|
|
505
|
+
elsewhere in the page (the demo puts it in a fixed container of its own).
|
|
506
|
+
Settings persist through the storage manager. The switches, their keys and
|
|
507
|
+
defaults:
|
|
508
|
+
|
|
509
|
+
| Switch | Setting | Default |
|
|
510
|
+
| --- | --- | --- |
|
|
511
|
+
| Measure Perf | `measureTypingPerf` | Off |
|
|
512
|
+
| Debug View | `showTreeView` | Off |
|
|
513
|
+
| Dark Mode | `isDarkMode` | Off |
|
|
514
|
+
| Show invisible characters | `showInvisibleCharacters` | Off |
|
|
515
|
+
| Nested Editors Debug View | `showNestedEditorTreeView` | Off |
|
|
516
|
+
| Rich Text | `isRichText` | On |
|
|
517
|
+
| Nested Tables | `hasNestedTables` | Off |
|
|
518
|
+
| Char Limit | `isCharLimit` | Off |
|
|
519
|
+
| Char Limit (UTF-8) | `isCharLimitUtf8` | Off |
|
|
520
|
+
| Link Attributes | `hasLinkAttributes` | Off |
|
|
521
|
+
| Max Length | `isMaxLength` | Off |
|
|
522
|
+
| Autocomplete | `isAutocomplete` | On |
|
|
523
|
+
| Table Of Contents | `showTableOfContents` | Off |
|
|
524
|
+
| Use Lexical Context Menu | `shouldUseLexicalContextMenu` | Off |
|
|
525
|
+
| Preserve newlines in Markdown | `shouldPreserveNewLinesInMarkdown` | Off |
|
|
526
|
+
| Use Brackets for Highlighting | `shouldAllowHighlightingWithBrackets` | Off |
|
|
527
|
+
| Retain selection | `selectionAlwaysOnDisplay` | Off |
|
|
528
|
+
| Enable Code Highlighting | `isCodeHighlighted` | On |
|
|
529
|
+
| Use Shiki for Code Highlighting | `isCodeShiki` | Off |
|
|
530
|
+
|
|
531
|
+
Pass `setColorScheme={(mode) => bibleNote.setColorScheme(mode)}` so the
|
|
532
|
+
instance's `colorScheme` follows the Dark Mode switch.
|
|
533
|
+
|
|
534
|
+
### Footer modes
|
|
535
|
+
|
|
536
|
+
- `isOnApp: true` — the editor runs inside an app, not a web page: hides
|
|
537
|
+
**Share as Link** and **Convert From Markdown**.
|
|
538
|
+
- `isMinimize: true` — compact footer: Import, Export and Editor Information
|
|
539
|
+
move into a **More actions** menu.
|
|
540
|
+
- `print()` — replaces the built-in printing (which lays the note out at the
|
|
541
|
+
selected page size and opens the print dialog).
|
|
542
|
+
|
|
543
|
+
Host buttons go before or after the built-in ones with
|
|
544
|
+
`prependFooterActionButton` / `appendFooterActionButton`.
|
|
545
|
+
|
|
546
|
+
### Electron: native file dialogs
|
|
547
|
+
|
|
548
|
+
When the page exposes `window.bibleNoteDesktop`, the footer's Word import/export
|
|
549
|
+
and JSON Import/Export use native Open and Save dialogs instead of a browser
|
|
550
|
+
file picker and download. The contract (this repository's
|
|
551
|
+
`scripts/electron-preload.cjs` implements it with `contextBridge` and two
|
|
552
|
+
`ipcMain` handlers):
|
|
553
|
+
|
|
554
|
+
```ts
|
|
555
|
+
window.bibleNoteDesktop = {
|
|
556
|
+
isElectron: true,
|
|
557
|
+
openFile(options: { filters: { name: string; extensions: string[] }[] }):
|
|
558
|
+
Promise<{ canceled: true } | { canceled: false; data: Uint8Array; fileName: string }>,
|
|
559
|
+
saveFile(options: {
|
|
560
|
+
data: Uint8Array | string;
|
|
561
|
+
defaultFileName: string;
|
|
562
|
+
filters: { name: string; extensions: string[] }[];
|
|
563
|
+
}): Promise<{ canceled: true } | { canceled: false; fileName: string }>,
|
|
564
|
+
};
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
The bridge is detected by `isElectron === true`. It is independent of
|
|
568
|
+
`isOnApp` — the demo host sets `isOnApp` from whether the bridge exists, which
|
|
569
|
+
is a reasonable default.
|
|
570
|
+
|
|
571
|
+
### Word round trips
|
|
572
|
+
|
|
573
|
+
The footer's Word buttons export a standard `.docx` that also embeds a private
|
|
574
|
+
BibleNote copy of the editor state; importing that file restores the full
|
|
575
|
+
editable document. A `.docx` from elsewhere (or one Word has stripped) is
|
|
576
|
+
converted from its Word content: text, headings, emphasis, lists, tables, links
|
|
577
|
+
and images survive, Word-only layout may be simplified.
|
|
578
|
+
|
|
579
|
+
Because a Word document has no hover cards, the export adds a **References**
|
|
580
|
+
appendix: every person, place and verse mention links to an entry with the
|
|
581
|
+
record's details and the verse text. Verse references are resolved through
|
|
582
|
+
`shortToVerseData` and related people and places through
|
|
583
|
+
`verseFullTextToListShorts`, so supply both for a complete appendix. Equations
|
|
584
|
+
become editable Word equations; sticky notes, drawings and embed thumbnails
|
|
585
|
+
become pictures.
|
|
586
|
+
|
|
587
|
+
<a id="dev-working-on-the-editor-ui"></a>
|
|
588
|
+
|
|
589
|
+
## Working on the editor UI
|
|
590
|
+
|
|
591
|
+
This topic is for changing the editor itself, in its source repository.
|
|
592
|
+
|
|
593
|
+
### Layout
|
|
594
|
+
|
|
595
|
+
| Path | What lives there |
|
|
596
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
597
|
+
| `src/lib.ts` | the package's public entry — only re-exports; everything it reaches is library code |
|
|
598
|
+
| `src/index.tsx` | the demo host (fetches datasets, wires every prop, mounts) — not part of the package |
|
|
599
|
+
| `src/BibleNote.ts` | the `BibleNote` class: queued editor actions, footer buttons, colour scheme |
|
|
600
|
+
| `src/bibleNoteHelpers.tsx` | `BibleNoteProps`, the storage split, `renderEditor` |
|
|
601
|
+
| `src/AppComp.tsx` | providers, storage hydration, the editor controller behind `BibleNote`'s methods |
|
|
602
|
+
| `src/Editor.tsx` | the plugin tree, zoom and the full-view layout |
|
|
603
|
+
| `src/plugins/<Name>Plugin/` | one Lexical plugin per folder |
|
|
604
|
+
| `src/nodes/` | custom Lexical nodes (`PlaygroundNodes.ts` registers them) |
|
|
605
|
+
| `src/ui/` | shared UI: modals, dropdowns, colour picker, Excalidraw modal, equation editor |
|
|
606
|
+
| `src/context/` | React contexts: settings, toolbar state, lookup managers, verse actions, media actions |
|
|
607
|
+
| `src/themes/` | the Lexical editor themes and their SCSS |
|
|
608
|
+
| `src/LookupManager.ts`, `src/lookupTypes.ts` | the dataset managers and record types |
|
|
609
|
+
| `test-packages/` | a consumer app that installs the built package from `../packages/bible-note` |
|
|
610
|
+
|
|
611
|
+
### The plugin tree
|
|
612
|
+
|
|
613
|
+
`src/Editor.tsx` renders every plugin. The table below is generated from it;
|
|
614
|
+
"mounted when" is the condition wrapping the element, usually a setting from the
|
|
615
|
+
settings panel.
|
|
616
|
+
|
|
617
|
+
| Plugin | Source | Mounted when |
|
|
618
|
+
| --- | --- | --- |
|
|
619
|
+
| `ToolbarPlugin` | `src/plugins/ToolbarPlugin` | `isRichText` |
|
|
620
|
+
| `ShortcutsPlugin` | `src/plugins/ShortcutsPlugin` | `isRichText` |
|
|
621
|
+
| `MaxLengthPlugin` | `src/plugins/MaxLengthPlugin` | `isMaxLength` |
|
|
622
|
+
| `DragDropPaste` | `src/plugins/DragDropPastePlugin` | always |
|
|
623
|
+
| `AutoFocusPlugin` | `@lexical/react/LexicalAutoFocusPlugin` | always |
|
|
624
|
+
| `EditorStatePersistencePlugin` | `src/plugins/EditorStatePersistencePlugin` | always |
|
|
625
|
+
| `SelectionAlwaysOnDisplay` | `@lexical/react/LexicalSelectionAlwaysOnDisplay` | `selectionAlwaysOnDisplay` |
|
|
626
|
+
| `ClearEditorPlugin` | `@lexical/react/LexicalClearEditorPlugin` | always |
|
|
627
|
+
| `FindPlugin` | `src/plugins/FindPlugin` | always |
|
|
628
|
+
| `ComponentPickerPlugin` | `src/plugins/ComponentPickerPlugin` | always |
|
|
629
|
+
| `EmojiPickerPlugin` | `src/plugins/EmojiPickerPlugin` | always |
|
|
630
|
+
| `AutoEmbedPlugin` | `src/plugins/AutoEmbedPlugin` | always |
|
|
631
|
+
| `MentionNamePlugin` | `src/plugins/MentionNamePlugin` | always |
|
|
632
|
+
| `MentionLocationsPlugin` | `src/plugins/MentionLocationsPlugin` | always |
|
|
633
|
+
| `MentionBibleVersesPlugin` | `src/plugins/MentionBibleVersesPlugin` | always |
|
|
634
|
+
| `EmojisPlugin` | `src/plugins/EmojisPlugin` | always |
|
|
635
|
+
| `KeywordsPlugin` | `src/plugins/KeywordsPlugin` | always |
|
|
636
|
+
| `AutoLinkPlugin` | `src/plugins/AutoLinkPlugin` | always |
|
|
637
|
+
| `DateTimePlugin` | `src/plugins/DateTimePlugin` | always |
|
|
638
|
+
| `CommentPlugin` | `src/plugins/CommentPlugin` | always |
|
|
639
|
+
| `LookupPlugin` | `src/plugins/LookupPlugin` | always |
|
|
640
|
+
| `HistoryPlugin` | `@lexical/react/LexicalHistoryPlugin` | `isRichText` |
|
|
641
|
+
| `RichTextPlugin` | `@lexical/react/LexicalRichTextPlugin` | `isRichText` |
|
|
642
|
+
| `StickyPlugin` | `src/plugins/StickyPlugin` | `isRichText` |
|
|
643
|
+
| `MarkdownShortcutPlugin` | `src/plugins/MarkdownShortcutPlugin` | `isRichText` |
|
|
644
|
+
| `CodeHighlightShikiPlugin` | `src/plugins/CodeHighlightShikiPlugin` | `isRichText` and `isCodeHighlighted` and `isCodeShiki` |
|
|
645
|
+
| `CodeHighlightPrismPlugin` | `src/plugins/CodeHighlightPrismPlugin` | `isRichText` and `isCodeHighlighted` and `!(isCodeShiki)` |
|
|
646
|
+
| `ListPlugin` | `@lexical/react/LexicalListPlugin` | `isRichText` |
|
|
647
|
+
| `CheckListPlugin` | `@lexical/react/LexicalCheckListPlugin` | `isRichText` |
|
|
648
|
+
| `TablePlugin` | `@lexical/react/LexicalTablePlugin` | `isRichText` |
|
|
649
|
+
| `TableCellResizer` | `src/plugins/TableCellResizer` | `isRichText` |
|
|
650
|
+
| `TableScrollShadowPlugin` | `src/plugins/TableScrollShadowPlugin` | `isRichText` |
|
|
651
|
+
| `MediaPlugin` | `src/plugins/MediaPlugin` | `isRichText` |
|
|
652
|
+
| `LinkPlugin` | `src/plugins/LinkPlugin` | `isRichText` |
|
|
653
|
+
| `PollPlugin` | `src/plugins/PollPlugin` | `isRichText` |
|
|
654
|
+
| `YouTubePlugin` | `src/plugins/YouTubePlugin` | `isRichText` |
|
|
655
|
+
| `WebsitePlugin` | `src/plugins/WebsitePlugin` | `isRichText` |
|
|
656
|
+
| `ClickableLinkPlugin` | `@lexical/react/LexicalClickableLinkPlugin` | `isRichText` |
|
|
657
|
+
| `HorizontalRulePlugin` | `@lexical/react/LexicalHorizontalRulePlugin` | `isRichText` |
|
|
658
|
+
| `EquationsPlugin` | `src/plugins/EquationsPlugin` | `isRichText` |
|
|
659
|
+
| `ExcalidrawPlugin` | `src/plugins/ExcalidrawPlugin` | `isRichText` |
|
|
660
|
+
| `TabFocusPlugin` | `src/plugins/TabFocusPlugin` | `isRichText` |
|
|
661
|
+
| `TabIndentationPlugin` | `@lexical/react/LexicalTabIndentationPlugin` | `isRichText` |
|
|
662
|
+
| `CollapsiblePlugin` | `src/plugins/CollapsiblePlugin` | `isRichText` |
|
|
663
|
+
| `PageBreakPlugin` | `src/plugins/PageBreakPlugin` | `isRichText` |
|
|
664
|
+
| `LayoutPlugin` | `src/plugins/LayoutPlugin/LayoutPlugin` | `isRichText` |
|
|
665
|
+
| `FloatingLinkEditorPlugin` | `src/plugins/FloatingLinkEditorPlugin` | `isRichText` and `floatingAnchorElem` |
|
|
666
|
+
| `BlockTextLinkPlugin` | `src/plugins/BlockTextLinkPlugin` | `isRichText` and `floatingAnchorElem` |
|
|
667
|
+
| `TableCellActionMenuPlugin` | `src/plugins/TableActionMenuPlugin` | `isRichText` and `floatingAnchorElem` |
|
|
668
|
+
| `FloatingTextFormatToolbarPlugin` | `src/plugins/FloatingTextFormatToolbarPlugin` | `isRichText` and `floatingAnchorElem` |
|
|
669
|
+
| `DraggableBlockPlugin` | `src/plugins/DraggableBlockPlugin` | `isRichText` and `floatingAnchorElem && hasPointerAffordances` |
|
|
670
|
+
| `CodeActionMenuPlugin` | `src/plugins/CodeActionMenuPlugin` | `isRichText` and `floatingAnchorElem && hasPointerAffordances` |
|
|
671
|
+
| `TableHoverActionsV2Plugin` | `src/plugins/TableHoverActionsV2Plugin` | `isRichText` and `floatingAnchorElem && hasPointerAffordances` |
|
|
672
|
+
| `PlainTextPlugin` | `@lexical/react/LexicalPlainTextPlugin` | `!(isRichText)` |
|
|
673
|
+
| `HistoryPlugin` | `@lexical/react/LexicalHistoryPlugin` | `!(isRichText)` |
|
|
674
|
+
| `InvisibleCharactersPlugin` | `src/plugins/InvisibleCharactersPlugin` | always |
|
|
675
|
+
| `CharacterLimitPlugin` | `@lexical/react/LexicalCharacterLimitPlugin` | `(isCharLimit \|\| isCharLimitUtf8)` |
|
|
676
|
+
| `AutocompletePlugin` | `src/plugins/AutocompletePlugin` | `isAutocomplete` |
|
|
677
|
+
| `PageSizePreviewPlugin` | `src/plugins/PageSizePreviewPlugin` | always |
|
|
678
|
+
| `PaperPageNavigationPlugin` | `src/plugins/PaperPageNavigationPlugin` | always |
|
|
679
|
+
| `TableOfContentsPlugin` | `src/plugins/TableOfContentsPlugin` | `showTableOfContents` |
|
|
680
|
+
| `ContextMenuPlugin` | `src/plugins/ContextMenuPlugin` | `shouldUseLexicalContextMenu` |
|
|
681
|
+
| `SpecialTextPlugin` | `src/plugins/SpecialTextPlugin` | `shouldAllowHighlightingWithBrackets` |
|
|
682
|
+
| `ActionsPlugin` | `src/plugins/ActionsPlugin` | always |
|
|
683
|
+
| `TreeViewPlugin` | `src/plugins/TreeViewPlugin` | `showTreeView` |
|
|
684
|
+
|
|
685
|
+
`isRichText` is on by default; `floatingAnchorElem` is the editor's scroll
|
|
686
|
+
container once it has mounted; `hasPointerAffordances` is true on a device with a
|
|
687
|
+
fine, hovering pointer (mouse or trackpad), so drag handles and hover menus never
|
|
688
|
+
appear on touch screens.
|
|
689
|
+
|
|
690
|
+
### Adding a feature
|
|
691
|
+
|
|
692
|
+
A typical new block or inline feature touches:
|
|
693
|
+
|
|
694
|
+
1. a node in `src/nodes/`, registered in `src/nodes/PlaygroundNodes.ts`;
|
|
695
|
+
2. a plugin folder in `src/plugins/`, mounted in `src/Editor.tsx` (behind a
|
|
696
|
+
setting if it is optional — add the key to `DEFAULT_SETTINGS` in
|
|
697
|
+
`src/appSettings.ts` and a `<Switch>` in `src/Settings.tsx`);
|
|
698
|
+
3. a slash-menu option in `getBaseOptions()` in
|
|
699
|
+
`src/plugins/ComponentPickerPlugin/index.tsx` and/or an item in the toolbar's
|
|
700
|
+
Insert dropdown;
|
|
701
|
+
4. a shortcut in `SHORTCUTS` (`src/plugins/ShortcutsPlugin/shortcuts.ts`) and its
|
|
702
|
+
handler in the shortcuts plugin, if it has one;
|
|
703
|
+
5. theme classes in `src/themes/PlaygroundEditorTheme.ts` and SCSS;
|
|
704
|
+
6. any persisted state through `getBibleNoteStorage()` (`src/storageManager.ts`),
|
|
705
|
+
with the key added to `BIBLE_NOTE_STORAGE_MANAGER_KEYS` so it is hydrated
|
|
706
|
+
before the first render;
|
|
707
|
+
7. Word export/import handling in `src/utils/docx*` if the node needs a Word form;
|
|
708
|
+
8. the user-facing description in `knowledge/ui/` (see "The knowledge files"
|
|
709
|
+
below).
|
|
710
|
+
|
|
711
|
+
UI follows the existing conventions: Bootstrap utility classes, `bi bi-*` icons
|
|
712
|
+
from bootstrap-icons (a peer dependency — never import its CSS from library
|
|
713
|
+
code), and colours that work under both `playground-theme-light` and
|
|
714
|
+
`playground-theme-dark`.
|
|
715
|
+
|
|
716
|
+
### Running it
|
|
717
|
+
|
|
718
|
+
- `npm run dev` — Vite on `http://localhost:3005` plus the Electron shell, with
|
|
719
|
+
remote debugging on `127.0.0.1:9225`.
|
|
720
|
+
- `npm run vite` — the web app alone on port 3005.
|
|
721
|
+
- If Electron dies at startup with a `BrowserWindow` export error, the shell
|
|
722
|
+
inherited `ELECTRON_RUN_AS_NODE=1` (VS Code's integrated terminal sets it);
|
|
723
|
+
clear it and run again.
|
|
724
|
+
- `npm run test:unit` — Vitest + jsdom over `src/**/*.test.ts(x)`.
|
|
725
|
+
- `npm run test:e2e` — Playwright.
|
|
726
|
+
- `npm run lint:ts`, `npm run lint:es`, `npm run lint:pre` — types, ESLint,
|
|
727
|
+
Prettier.
|
|
728
|
+
|
|
729
|
+
### Verifying UI changes in the browser
|
|
730
|
+
|
|
731
|
+
Do not call a UI change done until it has been exercised in the running app.
|
|
732
|
+
The repository's Chrome DevTools MCP server attaches to the Electron debug port
|
|
733
|
+
(`9225`): select the `http://localhost:3005/` page, snapshot it, drive the flow
|
|
734
|
+
with clicks and key presses, watch the console, and screenshot the result. The
|
|
735
|
+
`bn-robot-test` skill runs a full regression battery this way — mentions, slash
|
|
736
|
+
menu, toolbar, markdown shortcuts, tables, undo, persistence — and backs up and
|
|
737
|
+
restores the open note around it.
|
|
738
|
+
|
|
739
|
+
### The knowledge files
|
|
740
|
+
|
|
741
|
+
`knowledge/development/*.md` and `knowledge/ui/*.md` are the hand-written
|
|
742
|
+
sources of the two knowledge files; `npm run pack` builds them into
|
|
743
|
+
`packages/bible-note/knowledge/` (`npm run build:knowledge` rebuilds just them).
|
|
744
|
+
When a user-visible behaviour changes, update the matching `knowledge/ui/` topic;
|
|
745
|
+
when the public API changes, update its JSDoc — the API reference is generated
|
|
746
|
+
from the declarations. Catalogues such as the slash menu, shortcuts and the table
|
|
747
|
+
above are extracted from source; if `pack` fails in an extractor, the source moved
|
|
748
|
+
and `scripts/knowledge/extractUi.mjs` needs to follow it. `knowledge/README.md`
|
|
749
|
+
has the authoring rules.
|
|
750
|
+
|
|
751
|
+
<a id="dev-building-and-releasing-the-package"></a>
|
|
752
|
+
|
|
753
|
+
## Building and releasing the package
|
|
754
|
+
|
|
755
|
+
### `npm run pack`
|
|
756
|
+
|
|
757
|
+
`scripts/pack.mjs` builds `packages/bible-note/`:
|
|
758
|
+
|
|
759
|
+
1. wipes the generated directories — `dist/`, `types/`, `knowledge/`;
|
|
760
|
+
2. bundles `src/lib.ts` twice with `vite.lib.config.ts`, once as ESM (`.mjs`)
|
|
761
|
+
and once as CommonJS (`.cjs`), plus the single `dist/bible-note.css`;
|
|
762
|
+
3. emits declarations with `tsc -p tsconfig.lib.json` and prunes them to what
|
|
763
|
+
`types/lib.d.ts` actually reaches;
|
|
764
|
+
4. builds `knowledge/development.md` and `knowledge/ui-rag.md`;
|
|
765
|
+
5. checks the static `package.json` against the build and the root manifest —
|
|
766
|
+
every advertised path exists, `files` and `sideEffects` are right, peer
|
|
767
|
+
ranges match the root `package.json`, external packages are declared;
|
|
768
|
+
6. checks the entry surface (required exports present, no peer CSS bundled, no
|
|
769
|
+
throwing `require()` polyfill in the ES build) and type-checks the packaged
|
|
770
|
+
declarations from outside the repository, as a consumer would see them.
|
|
771
|
+
|
|
772
|
+
Any failure stops the run with the exact mismatch.
|
|
773
|
+
|
|
774
|
+
### Hand-maintained files
|
|
775
|
+
|
|
776
|
+
`packages/bible-note/package.json`, `README.md` and `LICENSE` are the only files
|
|
777
|
+
in `packages/` that git tracks, and no script writes them:
|
|
778
|
+
|
|
779
|
+
- bump `version` whenever library code changes — patch for fixes and internal
|
|
780
|
+
changes, minor for new exports, options or published files, major for a
|
|
781
|
+
breaking change to the public surface;
|
|
782
|
+
- update the README when a change is visible to a consumer (a new export goes
|
|
783
|
+
in its Exports table);
|
|
784
|
+
- edit `package.json` by hand when peer ranges change in the root manifest or
|
|
785
|
+
entry points move — `pack` reports the exact drift.
|
|
786
|
+
|
|
787
|
+
### Testing the built package
|
|
788
|
+
|
|
789
|
+
`test-packages/` installs `bible-note` from `../packages/bible-note`. After
|
|
790
|
+
`npm run pack`, run `npm i` and `npm run vite` (port 3007) there to use the
|
|
791
|
+
tarball contents exactly as a consumer would. `npm run copy-packages` mirrors
|
|
792
|
+
the publishable files into the sibling `../bible-note-dist` checkout
|
|
793
|
+
(`npm run pack:copy` does both).
|
|
794
|
+
|
|
795
|
+
### Publishing
|
|
796
|
+
|
|
797
|
+
From a clean `main`, with the package built:
|
|
798
|
+
|
|
799
|
+
```bash
|
|
800
|
+
npm pack --dry-run # check the file list
|
|
801
|
+
npm whoami # npm login if this fails
|
|
802
|
+
npm version patch --tag-version-prefix="" # or minor / major
|
|
803
|
+
npm publish
|
|
804
|
+
git push origin main --follow-tags
|
|
805
|
+
npm view bible-note version
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
<a id="dev-api-reference"></a>
|
|
809
|
+
|
|
810
|
+
## API reference
|
|
811
|
+
|
|
812
|
+
Generated from the package's own declarations (`types/lib.d.ts`), so it lists
|
|
813
|
+
exactly what `import … from 'bible-note'` provides. Descriptions are the JSDoc
|
|
814
|
+
on the source; a member without one shows its signature only.
|
|
815
|
+
|
|
816
|
+
The package's default export is [`BibleNote`](#api-biblenote); every name below is also a named export of `bible-note`.
|
|
817
|
+
|
|
818
|
+
### Classes
|
|
819
|
+
|
|
820
|
+
<a id="api-biblenote"></a>
|
|
821
|
+
|
|
822
|
+
#### `BibleNote`
|
|
823
|
+
|
|
824
|
+
The BibleNote editor. Construct it with the host's datasets and storage
|
|
825
|
+
callbacks, then [`render`](#api-biblenote) it into an element.
|
|
826
|
+
|
|
827
|
+
Every editor-backed method (`content`, `addText`, `searchText`, …) can be
|
|
828
|
+
called before `render`: writes are queued and applied once the editor has
|
|
829
|
+
mounted, and reads return an empty value until then.
|
|
830
|
+
|
|
831
|
+
```ts
|
|
832
|
+
new BibleNote(...)
|
|
833
|
+
constructor(props: BibleNoteProps);
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
##### `BibleNote.VERSION`
|
|
837
|
+
|
|
838
|
+
```ts
|
|
839
|
+
static VERSION: string;
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
The package version this bundle was built from.
|
|
843
|
+
|
|
844
|
+
##### `BibleNote.getAllShortVersesFromText()`
|
|
845
|
+
|
|
846
|
+
```ts
|
|
847
|
+
static getAllShortVersesFromText(lexicalText: string): Array<string>;
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
Every short verse reference (`GEN 1:1`) the given note content mentions, in
|
|
851
|
+
document order and without duplicates. Takes what `content` returns — a
|
|
852
|
+
serialized editor state — or plain text, and reads both the Bible verse
|
|
853
|
+
mentions and any reference written in the prose. Ranges inside one chapter
|
|
854
|
+
are expanded verse by verse; a range crossing a chapter boundary keeps only
|
|
855
|
+
its endpoints, because per-chapter verse counts are not bundled here.
|
|
856
|
+
|
|
857
|
+
##### `props`
|
|
858
|
+
|
|
859
|
+
```ts
|
|
860
|
+
props: Readonly<BibleNoteProps>;
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
The props the instance was constructed with.
|
|
864
|
+
|
|
865
|
+
##### `colorScheme`
|
|
866
|
+
|
|
867
|
+
```ts
|
|
868
|
+
colorScheme: BibleNoteColorScheme;
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
The colour scheme last applied — by [`BibleNote.setColorScheme`](#api-biblenote) or the
|
|
872
|
+
settings panel's Dark Mode switch. Read it; change it with `setColorScheme`.
|
|
873
|
+
|
|
874
|
+
##### `content`
|
|
875
|
+
|
|
876
|
+
```ts
|
|
877
|
+
get content(): string;
|
|
878
|
+
set content(value: string);
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
The note as a serialized Lexical editor state (a JSON string) — the same
|
|
882
|
+
string `saveData` receives. Reads `''` until the editor has mounted.
|
|
883
|
+
Assigning replaces the whole document; assigning `''` clears it.
|
|
884
|
+
|
|
885
|
+
##### `isReadOnly`
|
|
886
|
+
|
|
887
|
+
```ts
|
|
888
|
+
get isReadOnly(): boolean;
|
|
889
|
+
set isReadOnly(value: boolean);
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
Whether the note is locked against editing. Assigning `true` forces
|
|
893
|
+
read-only mode: the footer's lock turns into **Read-Only Mode Locked** and
|
|
894
|
+
the user cannot unlock it. Assigning `false` releases that lock and makes
|
|
895
|
+
the note editable.
|
|
896
|
+
|
|
897
|
+
##### `getIsFocusing()`
|
|
898
|
+
|
|
899
|
+
```ts
|
|
900
|
+
getIsFocusing(): boolean;
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
Whether the caret is in the editor right now: the window has focus, the
|
|
904
|
+
editor is the active element, and the selection is a collapsed caret inside
|
|
905
|
+
it. A host can use this to decide whether to send text to `addText`.
|
|
906
|
+
|
|
907
|
+
##### `setColorScheme()`
|
|
908
|
+
|
|
909
|
+
```ts
|
|
910
|
+
setColorScheme(mode: BibleNoteColorScheme): void;
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
Switches the editor between light and dark. Applies the body classes at
|
|
914
|
+
once (see `applyBibleNoteColorScheme`) and keeps the settings panel's Dark
|
|
915
|
+
Mode switch in step.
|
|
916
|
+
|
|
917
|
+
##### `addText()`
|
|
918
|
+
|
|
919
|
+
```ts
|
|
920
|
+
addText(text: string): void;
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
Inserts text at the caret, or at the end of the note when there is no
|
|
924
|
+
selection, exactly as if the user had pasted it as plain text — so the
|
|
925
|
+
paste rules apply: Bible text pasted right after a `^` becomes a verse
|
|
926
|
+
mention. Ignored while the note is read-only or when `text` is empty.
|
|
927
|
+
|
|
928
|
+
##### `appendFooterActionButton()`
|
|
929
|
+
|
|
930
|
+
```ts
|
|
931
|
+
appendFooterActionButton(actionButton: BibleNoteFooterActionButton): void;
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
Adds a host button after the footer's built-in buttons. A button whose `id`
|
|
935
|
+
is already present is replaced in place, keeping its position.
|
|
936
|
+
|
|
937
|
+
##### `prependFooterActionButton()`
|
|
938
|
+
|
|
939
|
+
```ts
|
|
940
|
+
prependFooterActionButton(actionButton: BibleNoteFooterActionButton): void;
|
|
941
|
+
```
|
|
942
|
+
|
|
943
|
+
Adds a host button before the footer's built-in buttons, ahead of any
|
|
944
|
+
prepended earlier. A button whose `id` is already present is replaced in
|
|
945
|
+
place, keeping its position.
|
|
946
|
+
|
|
947
|
+
##### `getFooterActionButton()`
|
|
948
|
+
|
|
949
|
+
```ts
|
|
950
|
+
getFooterActionButton(id: string): BibleNoteFooterActionButton | null;
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
The host footer button with this `id`, or `null`.
|
|
954
|
+
|
|
955
|
+
##### `removeFooterActionButton()`
|
|
956
|
+
|
|
957
|
+
```ts
|
|
958
|
+
removeFooterActionButton(id: string): boolean;
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
Removes the host footer button with this `id`; `false` when there was none.
|
|
962
|
+
|
|
963
|
+
##### `searchText()`
|
|
964
|
+
|
|
965
|
+
```ts
|
|
966
|
+
searchText(query: string | null): void;
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
Drives the editor's find bar. A string opens the bar (or updates the query
|
|
970
|
+
if it is already open); `null` closes it. Queued until the editor mounts,
|
|
971
|
+
like the other editor-backed methods.
|
|
972
|
+
|
|
973
|
+
##### `render()`
|
|
974
|
+
|
|
975
|
+
```ts
|
|
976
|
+
render(containerElement: HTMLElement, options?: BibleNoteRenderOptions): void;
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
Mounts the editor into `containerElement` with its own React root.
|
|
980
|
+
Rendering again unmounts the previous root first, so an instance is only
|
|
981
|
+
ever mounted once.
|
|
982
|
+
|
|
983
|
+
##### `unmount()`
|
|
984
|
+
|
|
985
|
+
```ts
|
|
986
|
+
unmount(): void;
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
Unmounts the editor. The instance keeps its props and footer buttons and
|
|
990
|
+
can be rendered again.
|
|
991
|
+
|
|
992
|
+
<a id="api-locationslookupmanager"></a>
|
|
993
|
+
|
|
994
|
+
#### `LocationsLookupManager`
|
|
995
|
+
|
|
996
|
+
Owns the place/location dataset(s): ranked search, id and name lookup,
|
|
997
|
+
pagination and verse → locations lookup. Has no editor dependency, so a host
|
|
998
|
+
can use it to build its own UI. Indexes are built lazily per language on
|
|
999
|
+
first use.
|
|
1000
|
+
|
|
1001
|
+
```ts
|
|
1002
|
+
new LocationsLookupManager(...)
|
|
1003
|
+
constructor(dataMap: LocationsLookupManagerDataMap, defaultLang: string, style?: LookupManagerStyle);
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
##### `LocationsLookupManager.fromRawDataset()`
|
|
1007
|
+
|
|
1008
|
+
```ts
|
|
1009
|
+
static fromRawDataset(rawDataMap: {
|
|
1010
|
+
[langCode: string]: unknown;
|
|
1011
|
+
}, defaultLang: string, style?: LookupManagerStyle): LocationsLookupManager;
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
Builds a manager straight from the generated dataset files, i.e. whatever
|
|
1015
|
+
`fetch('data/KJV/locationsMap.json')` resolved to, keyed by language code.
|
|
1016
|
+
Older generated files stored the records under `namesMap`, so both keys are
|
|
1017
|
+
accepted.
|
|
1018
|
+
|
|
1019
|
+
##### `LocationsLookupManager.createEmpty()`
|
|
1020
|
+
|
|
1021
|
+
```ts
|
|
1022
|
+
static createEmpty(): LocationsLookupManager;
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
An empty manager, used wherever a host has not supplied a dataset yet.
|
|
1026
|
+
|
|
1027
|
+
##### `searchLocations()`
|
|
1028
|
+
|
|
1029
|
+
```ts
|
|
1030
|
+
searchLocations(query: string, options?: LookupSearchOptions): Array<MentionLocationMatch>;
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
Locations matching `query`. Case-insensitive substring match against the name, the KJV English
|
|
1034
|
+
name (translated datasets) and the former name. Ranked exact, then prefix,
|
|
1035
|
+
then substring — the better of the two names counts — and by importance
|
|
1036
|
+
(`matterRange`, then alphabetical) within a tier. An empty query returns
|
|
1037
|
+
every record in importance order.
|
|
1038
|
+
|
|
1039
|
+
##### `searchLocationsPagination()`
|
|
1040
|
+
|
|
1041
|
+
```ts
|
|
1042
|
+
searchLocationsPagination(options?: LookupPaginationOptions): LookupPaginationResult<MentionLocationMatch>;
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
`searchLocations`, one page at a time (20 records per page by default).
|
|
1046
|
+
|
|
1047
|
+
##### `searchByShortVerse()`
|
|
1048
|
+
|
|
1049
|
+
```ts
|
|
1050
|
+
searchByShortVerse(shortVerse: string, lang?: string): Array<MentionLocationMatch>;
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
The locations a short verse key (e.g. `"EXO 6:23"`) mentions.
|
|
1054
|
+
|
|
1055
|
+
##### `style`
|
|
1056
|
+
|
|
1057
|
+
```ts
|
|
1058
|
+
get style(): LookupManagerStyle | undefined;
|
|
1059
|
+
set style(style: LookupManagerStyle | undefined);
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
The host-supplied style for this dataset, or `undefined` when it gave none.
|
|
1063
|
+
The UI merges it into the containers that render these records; like
|
|
1064
|
+
`defaultLang` it is read at render time, so a host that changes it after
|
|
1065
|
+
mounting must also make the editor re-render.
|
|
1066
|
+
|
|
1067
|
+
##### `defaultLang`
|
|
1068
|
+
|
|
1069
|
+
```ts
|
|
1070
|
+
get defaultLang(): string;
|
|
1071
|
+
set defaultLang(lang: string);
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
The language used when a call names none (or names one this manager does
|
|
1075
|
+
not hold). Assigning a language the data map lacks throws.
|
|
1076
|
+
|
|
1077
|
+
##### `langs`
|
|
1078
|
+
|
|
1079
|
+
```ts
|
|
1080
|
+
get langs(): ReadonlyArray<string>;
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
The language codes this manager holds data for.
|
|
1084
|
+
|
|
1085
|
+
##### `getRecordCount()`
|
|
1086
|
+
|
|
1087
|
+
```ts
|
|
1088
|
+
getRecordCount(lang?: string): number;
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
Total number of records in a language, ignoring any query.
|
|
1092
|
+
|
|
1093
|
+
##### `getAllRecords()`
|
|
1094
|
+
|
|
1095
|
+
```ts
|
|
1096
|
+
getAllRecords(lang?: string): Array<TRecord>;
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
Every record in a language, in importance order.
|
|
1100
|
+
|
|
1101
|
+
##### `getRecordById()`
|
|
1102
|
+
|
|
1103
|
+
```ts
|
|
1104
|
+
getRecordById(id: string, lang?: string): TRecord | null;
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
The record with this id (whitespace-trimmed), or `null`.
|
|
1108
|
+
|
|
1109
|
+
##### `getRecordsByIds()`
|
|
1110
|
+
|
|
1111
|
+
```ts
|
|
1112
|
+
getRecordsByIds(ids: ReadonlyArray<string>, lang?: string): Array<TRecord>;
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
The records for these ids, in the order given; unknown and repeated ids
|
|
1116
|
+
are skipped.
|
|
1117
|
+
|
|
1118
|
+
##### `getRecordsByName()`
|
|
1119
|
+
|
|
1120
|
+
```ts
|
|
1121
|
+
getRecordsByName(name: string, lang?: string): Array<TRecord>;
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
Every record carrying exactly this name. Names are not unique in the
|
|
1125
|
+
datasets, so callers that need certainty check for a single result.
|
|
1126
|
+
|
|
1127
|
+
<a id="api-nameslookupmanager"></a>
|
|
1128
|
+
|
|
1129
|
+
#### `NamesLookupManager`
|
|
1130
|
+
|
|
1131
|
+
Owns the person/name dataset(s): ranked search, id and name lookup,
|
|
1132
|
+
pagination, name-type counts and verse → names lookup. Has no editor
|
|
1133
|
+
dependency, so a host can use it to build its own UI. Indexes are built
|
|
1134
|
+
lazily per language on first use.
|
|
1135
|
+
|
|
1136
|
+
```ts
|
|
1137
|
+
new NamesLookupManager(...)
|
|
1138
|
+
constructor(dataMap: NamesLookupManagerDataMap, defaultLang: string, style?: LookupManagerStyle);
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
##### `NamesLookupManager.fromRawDataset()`
|
|
1142
|
+
|
|
1143
|
+
```ts
|
|
1144
|
+
static fromRawDataset(rawDataMap: {
|
|
1145
|
+
[langCode: string]: unknown;
|
|
1146
|
+
}, defaultLang: string, style?: LookupManagerStyle): NamesLookupManager;
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
Builds a manager straight from the generated dataset files, i.e. whatever
|
|
1150
|
+
`fetch('data/KJV/namesMap.json')` resolved to, keyed by language code. Use this
|
|
1151
|
+
unless you already hold normalized [`MentionNameMatch`](#api-mentionnamematch) records.
|
|
1152
|
+
|
|
1153
|
+
##### `NamesLookupManager.createEmpty()`
|
|
1154
|
+
|
|
1155
|
+
```ts
|
|
1156
|
+
static createEmpty(): NamesLookupManager;
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
An empty manager, used wherever a host has not supplied a dataset yet.
|
|
1160
|
+
|
|
1161
|
+
##### `getNameTypes()`
|
|
1162
|
+
|
|
1163
|
+
```ts
|
|
1164
|
+
getNameTypes(lang?: string): ReadonlyArray<NameTypeCount>;
|
|
1165
|
+
```
|
|
1166
|
+
|
|
1167
|
+
The name types actually present in the data, most common first, so a type
|
|
1168
|
+
filter only ever offers choices that would return results.
|
|
1169
|
+
|
|
1170
|
+
##### `nameTypes`
|
|
1171
|
+
|
|
1172
|
+
```ts
|
|
1173
|
+
get nameTypes(): ReadonlyArray<NameTypeCount>;
|
|
1174
|
+
```
|
|
1175
|
+
|
|
1176
|
+
The name types present in the default language.
|
|
1177
|
+
|
|
1178
|
+
##### `searchNames()`
|
|
1179
|
+
|
|
1180
|
+
```ts
|
|
1181
|
+
searchNames(query: string, options?: NamesLookupSearchOptions): Array<MentionNameMatch>;
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
Names matching `query`. Case-insensitive substring match against the name, the KJV English
|
|
1185
|
+
name (translated datasets) and the former name. Ranked exact, then prefix,
|
|
1186
|
+
then substring — the better of the two names counts — and by importance
|
|
1187
|
+
(`matterRange`, then alphabetical) within a tier. An empty query returns
|
|
1188
|
+
every record in importance order.
|
|
1189
|
+
|
|
1190
|
+
##### `searchNamesPagination()`
|
|
1191
|
+
|
|
1192
|
+
```ts
|
|
1193
|
+
searchNamesPagination(options?: NamesLookupPaginationOptions): LookupPaginationResult<MentionNameMatch>;
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
`searchNames`, one page at a time (20 records per page by default).
|
|
1197
|
+
|
|
1198
|
+
##### `searchByShortVerse()`
|
|
1199
|
+
|
|
1200
|
+
```ts
|
|
1201
|
+
searchByShortVerse(shortVerse: string, lang?: string): Array<MentionNameMatch>;
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
The names a short verse key (e.g. `"EXO 6:23"`) mentions.
|
|
1205
|
+
|
|
1206
|
+
##### `style`
|
|
1207
|
+
|
|
1208
|
+
```ts
|
|
1209
|
+
get style(): LookupManagerStyle | undefined;
|
|
1210
|
+
set style(style: LookupManagerStyle | undefined);
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
The host-supplied style for this dataset, or `undefined` when it gave none.
|
|
1214
|
+
The UI merges it into the containers that render these records; like
|
|
1215
|
+
`defaultLang` it is read at render time, so a host that changes it after
|
|
1216
|
+
mounting must also make the editor re-render.
|
|
1217
|
+
|
|
1218
|
+
##### `defaultLang`
|
|
1219
|
+
|
|
1220
|
+
```ts
|
|
1221
|
+
get defaultLang(): string;
|
|
1222
|
+
set defaultLang(lang: string);
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
The language used when a call names none (or names one this manager does
|
|
1226
|
+
not hold). Assigning a language the data map lacks throws.
|
|
1227
|
+
|
|
1228
|
+
##### `langs`
|
|
1229
|
+
|
|
1230
|
+
```ts
|
|
1231
|
+
get langs(): ReadonlyArray<string>;
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
The language codes this manager holds data for.
|
|
1235
|
+
|
|
1236
|
+
##### `getRecordCount()`
|
|
1237
|
+
|
|
1238
|
+
```ts
|
|
1239
|
+
getRecordCount(lang?: string): number;
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
Total number of records in a language, ignoring any query.
|
|
1243
|
+
|
|
1244
|
+
##### `getAllRecords()`
|
|
1245
|
+
|
|
1246
|
+
```ts
|
|
1247
|
+
getAllRecords(lang?: string): Array<TRecord>;
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
Every record in a language, in importance order.
|
|
1251
|
+
|
|
1252
|
+
##### `getRecordById()`
|
|
1253
|
+
|
|
1254
|
+
```ts
|
|
1255
|
+
getRecordById(id: string, lang?: string): TRecord | null;
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
The record with this id (whitespace-trimmed), or `null`.
|
|
1259
|
+
|
|
1260
|
+
##### `getRecordsByIds()`
|
|
1261
|
+
|
|
1262
|
+
```ts
|
|
1263
|
+
getRecordsByIds(ids: ReadonlyArray<string>, lang?: string): Array<TRecord>;
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
The records for these ids, in the order given; unknown and repeated ids
|
|
1267
|
+
are skipped.
|
|
1268
|
+
|
|
1269
|
+
##### `getRecordsByName()`
|
|
1270
|
+
|
|
1271
|
+
```ts
|
|
1272
|
+
getRecordsByName(name: string, lang?: string): Array<TRecord>;
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
Every record carrying exactly this name. Names are not unique in the
|
|
1276
|
+
datasets, so callers that need certainty check for a single result.
|
|
1277
|
+
|
|
1278
|
+
### Functions and components
|
|
1279
|
+
|
|
1280
|
+
<a id="api-applybiblenotecolorscheme"></a>
|
|
1281
|
+
|
|
1282
|
+
#### `applyBibleNoteColorScheme()`
|
|
1283
|
+
|
|
1284
|
+
Applies a colour scheme to `body` (default `document.body`): toggles the
|
|
1285
|
+
`playground-theme-dark` / `playground-theme-light` classes and sets
|
|
1286
|
+
`data-bs-theme`, so Bootstrap's own components follow. Prefer
|
|
1287
|
+
`BibleNote#setColorScheme` on a mounted editor; this is the bare DOM step.
|
|
1288
|
+
|
|
1289
|
+
```ts
|
|
1290
|
+
function applyBibleNoteColorScheme(mode: BibleNoteColorScheme, body?: HTMLElement): void;
|
|
1291
|
+
```
|
|
1292
|
+
|
|
1293
|
+
<a id="api-biblenotesettings"></a>
|
|
1294
|
+
|
|
1295
|
+
#### `BibleNoteSettings()`
|
|
1296
|
+
|
|
1297
|
+
The editor's settings panel — a gear button that opens the switches (Dark
|
|
1298
|
+
Mode, Table Of Contents, …). Pass it to `render` as `options.settings`;
|
|
1299
|
+
settings persist through the storage manager.
|
|
1300
|
+
|
|
1301
|
+
```ts
|
|
1302
|
+
default function BibleNoteSettings({ setColorScheme, }: BibleNoteSettingsProps): JSX.Element;
|
|
1303
|
+
```
|
|
1304
|
+
|
|
1305
|
+
<a id="api-clearbiblenotecolorscheme"></a>
|
|
1306
|
+
|
|
1307
|
+
#### `clearBibleNoteColorScheme()`
|
|
1308
|
+
|
|
1309
|
+
Removes the theme classes `applyBibleNoteColorScheme` added (leaves `data-bs-theme`).
|
|
1310
|
+
|
|
1311
|
+
```ts
|
|
1312
|
+
function clearBibleNoteColorScheme(body?: HTMLElement): void;
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
<a id="api-createbrowserstoragemanager"></a>
|
|
1316
|
+
|
|
1317
|
+
#### `createBrowserStorageManager()`
|
|
1318
|
+
|
|
1319
|
+
A `BibleNoteStorageManager` backed by `window.localStorage`. Non-string
|
|
1320
|
+
values are stored as JSON; when `localStorage` is unavailable every call is
|
|
1321
|
+
a no-op.
|
|
1322
|
+
|
|
1323
|
+
```ts
|
|
1324
|
+
function createBrowserStorageManager(): BibleNoteStorageManager;
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
<a id="api-getlookuprecordvalues"></a>
|
|
1328
|
+
|
|
1329
|
+
#### `getLookupRecordValues()`
|
|
1330
|
+
|
|
1331
|
+
The records of a raw dataset collection, whether it is an id-keyed object or
|
|
1332
|
+
a plain array; `[]` for anything else.
|
|
1333
|
+
|
|
1334
|
+
```ts
|
|
1335
|
+
function getLookupRecordValues(value: unknown): Array<unknown>;
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
<a id="api-getmentionkjvname"></a>
|
|
1339
|
+
|
|
1340
|
+
#### `getMentionKjvName()`
|
|
1341
|
+
|
|
1342
|
+
The English name worth showing beside a record's own name, or `null` when
|
|
1343
|
+
there is nothing to add — an untranslated (KJV) dataset, or a record whose
|
|
1344
|
+
translated name is the English one anyway. Display it the way a Bible book
|
|
1345
|
+
reads in a translated UI: `លោកុប្បត្តិ (Genesis)`.
|
|
1346
|
+
|
|
1347
|
+
```ts
|
|
1348
|
+
function getMentionKjvName(record: {
|
|
1349
|
+
name: string;
|
|
1350
|
+
kjvName: string | null;
|
|
1351
|
+
}): string | null;
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
<a id="api-normalizementionnametype"></a>
|
|
1355
|
+
|
|
1356
|
+
#### `normalizeMentionNameType()`
|
|
1357
|
+
|
|
1358
|
+
Normalizes a raw record `type` value to one of the known [`MentionNameType`](#api-mentionnametype)
|
|
1359
|
+
keys. Unrecognized or empty values fall back to `person`, the neutral default
|
|
1360
|
+
used for untyped name records.
|
|
1361
|
+
|
|
1362
|
+
```ts
|
|
1363
|
+
function normalizeMentionNameType(type: string | null | undefined): MentionNameType;
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
<a id="api-parsementionlocationmatch"></a>
|
|
1367
|
+
|
|
1368
|
+
#### `parseMentionLocationMatch()`
|
|
1369
|
+
|
|
1370
|
+
Normalizes one raw dataset entry into a [`MentionLocationMatch`](#api-mentionlocationmatch), or
|
|
1371
|
+
returns `null` when it carries no usable identity.
|
|
1372
|
+
|
|
1373
|
+
```ts
|
|
1374
|
+
function parseMentionLocationMatch(value: unknown): MentionLocationMatch | null;
|
|
1375
|
+
```
|
|
1376
|
+
|
|
1377
|
+
<a id="api-parsementionlocationmatches"></a>
|
|
1378
|
+
|
|
1379
|
+
#### `parseMentionLocationMatches()`
|
|
1380
|
+
|
|
1381
|
+
Parses a whole dataset value (array or id-keyed object) into location records.
|
|
1382
|
+
|
|
1383
|
+
```ts
|
|
1384
|
+
function parseMentionLocationMatches(value: unknown): Array<MentionLocationMatch>;
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1387
|
+
<a id="api-parsementionnamematch"></a>
|
|
1388
|
+
|
|
1389
|
+
#### `parseMentionNameMatch()`
|
|
1390
|
+
|
|
1391
|
+
Normalizes one raw dataset entry into a [`MentionNameMatch`](#api-mentionnamematch), or returns
|
|
1392
|
+
`null` when it carries no usable identity. The literal id `'id'` is rejected
|
|
1393
|
+
because some generated files carry a header row.
|
|
1394
|
+
|
|
1395
|
+
```ts
|
|
1396
|
+
function parseMentionNameMatch(value: unknown): MentionNameMatch | null;
|
|
1397
|
+
```
|
|
1398
|
+
|
|
1399
|
+
<a id="api-parsementionnamematches"></a>
|
|
1400
|
+
|
|
1401
|
+
#### `parseMentionNameMatches()`
|
|
1402
|
+
|
|
1403
|
+
Parses a whole dataset value (array or id-keyed object) into name records.
|
|
1404
|
+
|
|
1405
|
+
```ts
|
|
1406
|
+
function parseMentionNameMatches(value: unknown): Array<MentionNameMatch>;
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
### Constants
|
|
1410
|
+
|
|
1411
|
+
<a id="api-bible_note_storage_manager_keys"></a>
|
|
1412
|
+
|
|
1413
|
+
#### `BIBLE_NOTE_STORAGE_MANAGER_KEYS`
|
|
1414
|
+
|
|
1415
|
+
Every key the editor reads from its storage manager before it renders. A
|
|
1416
|
+
host-side store that needs to know its keys up front (to prefetch or migrate
|
|
1417
|
+
them) can use this list.
|
|
1418
|
+
|
|
1419
|
+
```ts
|
|
1420
|
+
const BIBLE_NOTE_STORAGE_MANAGER_KEYS: readonly ["lexical-playground-settings", "lexical-playground-editor-state", "lexical-playground-comments", "lexical-playground-comments-panel-open", "lexical-playground-block-text-links", "lexical-playground-read-only-mode", "lexical-playground-insert-character-picker", "lexical-playground-editor-zoom-percent"]
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
<a id="api-editor_state_local_storage_key"></a>
|
|
1424
|
+
|
|
1425
|
+
#### `EDITOR_STATE_LOCAL_STORAGE_KEY`
|
|
1426
|
+
|
|
1427
|
+
The storage key of the note itself. The editor never hands this key to the
|
|
1428
|
+
host's `storageManager`: reads and writes of it go to `loadData` / `saveData`
|
|
1429
|
+
instead.
|
|
1430
|
+
|
|
1431
|
+
```ts
|
|
1432
|
+
const EDITOR_STATE_LOCAL_STORAGE_KEY = "lexical-playground-editor-state"
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1435
|
+
### Types
|
|
1436
|
+
|
|
1437
|
+
<a id="api-biblenotecolorscheme"></a>
|
|
1438
|
+
|
|
1439
|
+
#### `BibleNoteColorScheme`
|
|
1440
|
+
|
|
1441
|
+
The editor's two colour schemes.
|
|
1442
|
+
|
|
1443
|
+
```ts
|
|
1444
|
+
type BibleNoteColorScheme = 'dark' | 'light';
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
<a id="api-biblenotefooteractionbutton"></a>
|
|
1448
|
+
|
|
1449
|
+
#### `BibleNoteFooterActionButton`
|
|
1450
|
+
|
|
1451
|
+
A host-supplied button in the editor's footer.
|
|
1452
|
+
|
|
1453
|
+
| Property | Type | Required | Description |
|
|
1454
|
+
| --- | --- | --- | --- |
|
|
1455
|
+
| `id` | `string` | yes | Unique per editor; adding a button with an existing id replaces it in place. |
|
|
1456
|
+
| `description` | `string` | no | What the button does. Used as the button's tooltip when the button element has no `title` of its own. |
|
|
1457
|
+
| `shortcutKey` | `string` | no | A keyboard shortcut that clicks the button from anywhere in the page, written as modifiers plus one key joined by `+`: `"Ctrl+Shift+K"`, `"Cmd+Shift+K"`, `"Alt+Shift+K"` (`Ctrl`/`Control`, `Cmd`/`Command`/`Meta`, `Alt`/`Option`, `Shift`). It is appended to the tooltip and set as `aria-keyshortcuts`. |
|
|
1458
|
+
| `children` | `ReactNode` | yes | The button itself, normally a single `<button>`. When it is a single plain element, the editor adds the tooltip and `aria-keyshortcuts` to it. |
|
|
1459
|
+
|
|
1460
|
+
<a id="api-biblenotefooteractionbuttonplacement"></a>
|
|
1461
|
+
|
|
1462
|
+
#### `BibleNoteFooterActionButtonPlacement`
|
|
1463
|
+
|
|
1464
|
+
Which side of the built-in footer buttons a host button sits on.
|
|
1465
|
+
|
|
1466
|
+
```ts
|
|
1467
|
+
type BibleNoteFooterActionButtonPlacement = 'before' | 'after';
|
|
1468
|
+
```
|
|
1469
|
+
|
|
1470
|
+
<a id="api-biblenotefooteractionbuttons"></a>
|
|
1471
|
+
|
|
1472
|
+
#### `BibleNoteFooterActionButtons`
|
|
1473
|
+
|
|
1474
|
+
The host footer buttons on each side of the built-in ones, in order.
|
|
1475
|
+
|
|
1476
|
+
```ts
|
|
1477
|
+
type BibleNoteFooterActionButtons = Readonly<{
|
|
1478
|
+
before: ReadonlyArray<BibleNoteFooterActionButton>;
|
|
1479
|
+
after: ReadonlyArray<BibleNoteFooterActionButton>;
|
|
1480
|
+
}>;
|
|
1481
|
+
```
|
|
1482
|
+
|
|
1483
|
+
<a id="api-biblenoteprops"></a>
|
|
1484
|
+
|
|
1485
|
+
#### `BibleNoteProps`
|
|
1486
|
+
|
|
1487
|
+
Everything `new BibleNote(props)` needs from the host application.
|
|
1488
|
+
|
|
1489
|
+
| Property | Type | Required | Description |
|
|
1490
|
+
| --- | --- | --- | --- |
|
|
1491
|
+
| `namesLookupManager` | `NamesLookupManager` | yes | The person dataset behind `@` mentions, hover cards, the advanced panel and the lookup panel. Build it with `NamesLookupManager.fromRawDataset`. |
|
|
1492
|
+
| `locationsLookupManager` | `LocationsLookupManager` | yes | The place dataset behind `#` mentions, hover cards, the advanced panel and the lookup panel. Build it with `LocationsLookupManager.fromRawDataset`. |
|
|
1493
|
+
| `getLangCode` | `(text: string) => string` | yes | Returns the language code of a piece of text (`'en'` for English). Used to pick a font for pasted Bible text and Excalidraw text: when it returns a code other than `'en'`, the editor switches to the first font in `editorExtraFontFamilies` registered for that language. |
|
|
1494
|
+
| `editorExtraFontFamilies` | `ReadonlyArray<ExtraFontFamilyOption>` | yes | Fonts added to the toolbar's font menu and to Excalidraw, as `[fontFamily, languageCode]` pairs. The host must load the font faces itself; pass `[]` for the built-in fonts only. |
|
|
1495
|
+
| `excalidrawLibraryItems` | `LibraryItems` | no | Extra Excalidraw library items, offered next to the bundled Christian library. |
|
|
1496
|
+
| `excalidrawClearLibrariesFileList` | `() => void` | no | Forgets every Excalidraw library file `excalidrawSaveLibrariesFile` stored. |
|
|
1497
|
+
| `excalidrawLoadLibrariesFileList` | `() => string[]` | no | Returns the Excalidraw library files saved earlier (each a serialized library JSON string); read each time the Excalidraw editor opens. |
|
|
1498
|
+
| `excalidrawSaveLibrariesFile` | `(librariesFile: string) => void` | no | Persists a library the user imported in Excalidraw (a serialized library JSON string) so `excalidrawLoadLibrariesFileList` can return it next time. |
|
|
1499
|
+
| `stickyNoteExtraFontFamilies` | `ReadonlyArray<string>` | yes | Extra CSS font-family values offered in the sticky-note font picker, e.g. `'"Fasthand"'`. Pass `[]` for none. |
|
|
1500
|
+
| `storageManager` | `BibleNoteStorageManager` | yes | Stores every piece of editor state except the note itself: settings, comments, read-only mode, zoom, panel state. `createBrowserStorageManager()` keeps them in `localStorage`. The keys it receives are listed in `BIBLE_NOTE_STORAGE_MANAGER_KEYS`. |
|
|
1501
|
+
| `saveData` | `(data: string) => Promise<void> \| void` | yes | Saves the note: called with the serialized editor state (a JSON string) on every change to the document — the same string `BibleNote#content` returns. Called with `''` when the stored note could not be parsed and is discarded. |
|
|
1502
|
+
| `loadData` | `() => Promise<string \| null> \| string \| null` | yes | Loads the note saved by `saveData`. Return `null` or `''` for an empty editor. |
|
|
1503
|
+
| `resolveFilePath` | `FilePathResolver` | no | Maps a media file the user dropped or picked to a path or URL to store in the note instead of embedding it as a data URL. Return `null` to fall back to embedding. In a browser there is usually no path to give; in Electron this is where a file's location on disk comes from. |
|
|
1504
|
+
| `revealFile` | `FileRevealer` | no | Shows a media file's location to the user (e.g. Electron's `shell.showItemInFolder`). When provided, a selected image, video, audio or PDF whose source is a local file path gets a reveal button. |
|
|
1505
|
+
| `print` | `() => void` | no | Replaces the footer Print button's built-in printing, which prints the note laid out at the selected page size. |
|
|
1506
|
+
| `isOnApp` | `boolean` | no | The editor is embedded in an app rather than a web page: hides the footer's **Share as Link** and **Convert From Markdown** buttons. Defaults to `false`. |
|
|
1507
|
+
| `isMinimize` | `boolean` | no | Compact footer: folds Import, Export and Editor Information into a **More actions** menu. Defaults to `false`. |
|
|
1508
|
+
| `shortToVerseData` | `(shortText: string) => Promise<MentionedBibleDataType \| null>` | no | Resolves a short verse key (`GEN 1:1`) to its displayed title and text. Used for verse lists in mention panels and in the Word export's References appendix. Without it, those lists show the bare key. |
|
|
1509
|
+
| `verseFullTextToListShorts` | `(fullText: string) => Promise<string[] \| null>` | no | Lists the short verse keys a verse mention covers, given its full text. Enables the people and places mentioned in a verse, shown in that verse's advanced panel and in the Word export. |
|
|
1510
|
+
| `changeBibleKey` | `(event: React.MouseEvent<HTMLButtonElement>, verseFullText: string) => Promise<MentionedBibleDataType \| null>` | no | Offers the same verse in another Bible version. When provided, the version label in a verse's advanced panel becomes a button; resolve to the verse in the chosen version to open it in a new panel, or `null` to do nothing. |
|
|
1511
|
+
|
|
1512
|
+
<a id="api-biblenoterenderoptions"></a>
|
|
1513
|
+
|
|
1514
|
+
#### `BibleNoteRenderOptions`
|
|
1515
|
+
|
|
1516
|
+
Options for `BibleNote#render`.
|
|
1517
|
+
|
|
1518
|
+
| Property | Type | Required | Description |
|
|
1519
|
+
| --- | --- | --- | --- |
|
|
1520
|
+
| `settings` | `ReactNode` | no | The settings panel to mount, normally `<BibleNoteSettings />`. Omit it and the editor has no settings panel. |
|
|
1521
|
+
| `settingsContainerElement` | `Element \| DocumentFragment` | no | Where to portal the `settings` panel. Without it the panel renders inside the editor's own layout. |
|
|
1522
|
+
|
|
1523
|
+
<a id="api-biblenotesettingsprops"></a>
|
|
1524
|
+
|
|
1525
|
+
#### `BibleNoteSettingsProps`
|
|
1526
|
+
|
|
1527
|
+
Props of `BibleNoteSettings`.
|
|
1528
|
+
|
|
1529
|
+
| Property | Type | Required | Description |
|
|
1530
|
+
| --- | --- | --- | --- |
|
|
1531
|
+
| `setColorScheme` | `(mode: BibleNoteColorScheme) => void` | yes | Called when the Dark Mode switch flips. Pass `(mode) => bibleNote.setColorScheme(mode)` so the instance stays in step. |
|
|
1532
|
+
|
|
1533
|
+
<a id="api-biblenotestoragemanager"></a>
|
|
1534
|
+
|
|
1535
|
+
#### `BibleNoteStorageManager`
|
|
1536
|
+
|
|
1537
|
+
Where the editor keeps its own state — settings, comments, read-only mode,
|
|
1538
|
+
zoom, panel state — as string values under the keys in
|
|
1539
|
+
`BIBLE_NOTE_STORAGE_MANAGER_KEYS`. The note itself goes through
|
|
1540
|
+
`loadData` / `saveData` instead. Every key is read once, before the editor
|
|
1541
|
+
first renders; writes are fire-and-forget.
|
|
1542
|
+
|
|
1543
|
+
| Property | Type | Required | Description |
|
|
1544
|
+
| --- | --- | --- | --- |
|
|
1545
|
+
| `setSetting` | `setSetting(key: string, value: unknown): Promise<void>` | yes | Stores `value` (a string, or a value to `JSON.stringify`) under `key`. |
|
|
1546
|
+
| `getSetting` | `getSetting<T = unknown>(key: string): Promise<T \| null>` | yes | The value stored under `key`, or `null` when there is none. |
|
|
1547
|
+
| `deleteSetting` | `deleteSetting(key: string): Promise<void>` | yes | Removes `key`. |
|
|
1548
|
+
|
|
1549
|
+
<a id="api-extrafontfamilyoption"></a>
|
|
1550
|
+
|
|
1551
|
+
#### `ExtraFontFamilyOption`
|
|
1552
|
+
|
|
1553
|
+
A host font added to the editor: `[fontFamily, languageCode]`, e.g.
|
|
1554
|
+
`['Battambang', 'km']`. The language code is what `getLangCode` returns
|
|
1555
|
+
for text that should use this font.
|
|
1556
|
+
|
|
1557
|
+
```ts
|
|
1558
|
+
type ExtraFontFamilyOption = readonly [
|
|
1559
|
+
fontFamily: string,
|
|
1560
|
+
language: string
|
|
1561
|
+
];
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
<a id="api-filepathresolver"></a>
|
|
1565
|
+
|
|
1566
|
+
#### `FilePathResolver`
|
|
1567
|
+
|
|
1568
|
+
Maps a media file to the path or URL the note should reference. Return
|
|
1569
|
+
`null` (or throw) to let the editor embed the file as a data URL instead.
|
|
1570
|
+
|
|
1571
|
+
```ts
|
|
1572
|
+
type FilePathResolver = (file: File, context: FilePathResolverContext) => Promise<string | null> | string | null;
|
|
1573
|
+
```
|
|
1574
|
+
|
|
1575
|
+
<a id="api-filepathresolvercontext"></a>
|
|
1576
|
+
|
|
1577
|
+
#### `FilePathResolverContext`
|
|
1578
|
+
|
|
1579
|
+
Context passed to a `FilePathResolver`.
|
|
1580
|
+
|
|
1581
|
+
```ts
|
|
1582
|
+
type FilePathResolverContext = Readonly<{
|
|
1583
|
+
source: FilePathSource;
|
|
1584
|
+
}>;
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
<a id="api-filepathsource"></a>
|
|
1588
|
+
|
|
1589
|
+
#### `FilePathSource`
|
|
1590
|
+
|
|
1591
|
+
How a media file reached the editor: dropped/pasted, or picked in the media dialog.
|
|
1592
|
+
|
|
1593
|
+
```ts
|
|
1594
|
+
type FilePathSource = 'drop' | 'file-input';
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
<a id="api-filerevealer"></a>
|
|
1598
|
+
|
|
1599
|
+
#### `FileRevealer`
|
|
1600
|
+
|
|
1601
|
+
Shows a local media file to the user, e.g. in the system file manager.
|
|
1602
|
+
|
|
1603
|
+
```ts
|
|
1604
|
+
type FileRevealer = (filePath: string) => Promise<void> | void;
|
|
1605
|
+
```
|
|
1606
|
+
|
|
1607
|
+
<a id="api-fontfamilyoption"></a>
|
|
1608
|
+
|
|
1609
|
+
#### `FontFamilyOption`
|
|
1610
|
+
|
|
1611
|
+
A font in the toolbar's font menu: `[fontFamily, label, languageCode]`.
|
|
1612
|
+
|
|
1613
|
+
```ts
|
|
1614
|
+
type FontFamilyOption = readonly [
|
|
1615
|
+
fontFamily: string,
|
|
1616
|
+
label: string,
|
|
1617
|
+
language: string
|
|
1618
|
+
];
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
<a id="api-locationslookupmanagerdatamap"></a>
|
|
1622
|
+
|
|
1623
|
+
#### `LocationsLookupManagerDataMap`
|
|
1624
|
+
|
|
1625
|
+
Location datasets keyed by language code, e.g. `{ en: …, km: … }`.
|
|
1626
|
+
|
|
1627
|
+
```ts
|
|
1628
|
+
type LocationsLookupManagerDataMap = {
|
|
1629
|
+
[langCode: string]: LocationsLookupManagerLangData;
|
|
1630
|
+
};
|
|
1631
|
+
```
|
|
1632
|
+
|
|
1633
|
+
<a id="api-locationslookupmanagerlangdata"></a>
|
|
1634
|
+
|
|
1635
|
+
#### `LocationsLookupManagerLangData`
|
|
1636
|
+
|
|
1637
|
+
One language's location dataset, as `LocationsLookupManager`'s constructor takes it.
|
|
1638
|
+
|
|
1639
|
+
| Property | Type | Required | Description |
|
|
1640
|
+
| --- | --- | --- | --- |
|
|
1641
|
+
| `records` | `ReadonlyArray<MentionLocationMatch>` | yes | The normalized records (see `parseMentionLocationMatches`). |
|
|
1642
|
+
| `verseLocationsMap` | `VerseRecordIdsMap` | no | Short verse key (e.g. `"EXO 6:23"`) to the ids of the locations it mentions. |
|
|
1643
|
+
|
|
1644
|
+
<a id="api-lookupmanagerstyle"></a>
|
|
1645
|
+
|
|
1646
|
+
#### `LookupManagerStyle`
|
|
1647
|
+
|
|
1648
|
+
Extra inline style the UI applies wherever it renders one manager's records —
|
|
1649
|
+
the mention popup and hover card, the advanced panel, and the lookup list.
|
|
1650
|
+
Its purpose is a dataset-wide `fontFamily` for a language the editor's own
|
|
1651
|
+
font does not cover; anything a `style` attribute accepts works.
|
|
1652
|
+
|
|
1653
|
+
```ts
|
|
1654
|
+
type LookupManagerStyle = CSSProperties;
|
|
1655
|
+
```
|
|
1656
|
+
|
|
1657
|
+
<a id="api-lookuppaginationoptions"></a>
|
|
1658
|
+
|
|
1659
|
+
#### `LookupPaginationOptions`
|
|
1660
|
+
|
|
1661
|
+
Options for the `…Pagination` searches.
|
|
1662
|
+
|
|
1663
|
+
| Property | Type | Required | Description |
|
|
1664
|
+
| --- | --- | --- | --- |
|
|
1665
|
+
| `query` | `string` | no | Search text; empty or omitted lists every record in importance order. |
|
|
1666
|
+
| `lang` | `string` | no | Language to search; falls back to `defaultLang` when absent or unknown. |
|
|
1667
|
+
| `page` | `number` | no | 1-based page number, clamped to the available pages. Defaults to 1. |
|
|
1668
|
+
| `pageSize` | `number` | no | Records per page (at least 1). Defaults to 20. |
|
|
1669
|
+
|
|
1670
|
+
<a id="api-lookuppaginationresult"></a>
|
|
1671
|
+
|
|
1672
|
+
#### `LookupPaginationResult`
|
|
1673
|
+
|
|
1674
|
+
One page of search results.
|
|
1675
|
+
|
|
1676
|
+
| Property | Type | Required | Description |
|
|
1677
|
+
| --- | --- | --- | --- |
|
|
1678
|
+
| `lang` | `string` | yes | The language actually searched. |
|
|
1679
|
+
| `totalRecords` | `number` | yes | Matches across all pages. |
|
|
1680
|
+
| `page` | `number` | yes | The page returned, after clamping. |
|
|
1681
|
+
| `totalPages` | `number` | yes | Number of pages; at least 1, even with no matches. |
|
|
1682
|
+
| `pageSize` | `number` | yes | |
|
|
1683
|
+
| `records` | `Array<TRecord>` | yes | This page's records. |
|
|
1684
|
+
|
|
1685
|
+
<a id="api-lookupsearchoptions"></a>
|
|
1686
|
+
|
|
1687
|
+
#### `LookupSearchOptions`
|
|
1688
|
+
|
|
1689
|
+
Options for `searchNames` / `searchLocations`.
|
|
1690
|
+
|
|
1691
|
+
| Property | Type | Required | Description |
|
|
1692
|
+
| --- | --- | --- | --- |
|
|
1693
|
+
| `lang` | `string` | no | Language to search; falls back to `defaultLang` when absent or unknown. |
|
|
1694
|
+
| `limit` | `number` | no | Maximum number of results; all matches when omitted. |
|
|
1695
|
+
|
|
1696
|
+
<a id="api-mentionlocationcoordinates"></a>
|
|
1697
|
+
|
|
1698
|
+
#### `MentionLocationCoordinates`
|
|
1699
|
+
|
|
1700
|
+
WGS 84 decimal degrees.
|
|
1701
|
+
|
|
1702
|
+
| Property | Type | Required | Description |
|
|
1703
|
+
| --- | --- | --- | --- |
|
|
1704
|
+
| `latitude` | `number` | yes | |
|
|
1705
|
+
| `longitude` | `number` | yes | |
|
|
1706
|
+
|
|
1707
|
+
<a id="api-mentionlocationlink"></a>
|
|
1708
|
+
|
|
1709
|
+
#### `MentionLocationLink`
|
|
1710
|
+
|
|
1711
|
+
An external reference about a location; same shape as [`MentionNameLink`](#api-mentionnamelink).
|
|
1712
|
+
|
|
1713
|
+
| Property | Type | Required | Description |
|
|
1714
|
+
| --- | --- | --- | --- |
|
|
1715
|
+
| `type` | `string` | yes | |
|
|
1716
|
+
| `url` | `string` | yes | |
|
|
1717
|
+
|
|
1718
|
+
<a id="api-mentionlocationmatch"></a>
|
|
1719
|
+
|
|
1720
|
+
#### `MentionLocationMatch`
|
|
1721
|
+
|
|
1722
|
+
One place/location record — what `LocationsLookupManager` searches and
|
|
1723
|
+
returns, and what a `#` mention shows.
|
|
1724
|
+
|
|
1725
|
+
| Property | Type | Required | Description |
|
|
1726
|
+
| --- | --- | --- | --- |
|
|
1727
|
+
| `id` | `string` | yes | Stable record id; mentions in saved notes refer to it. |
|
|
1728
|
+
| `name` | `string` | yes | The name as printed in this dataset's Bible text. |
|
|
1729
|
+
| `kjvName` | `string \| null` | yes | The KJV English name; see [`MentionNameMatch.kjvName`](#api-mentionnamematch). |
|
|
1730
|
+
| `oldName` | `string \| null` | yes | A former name, searchable like `name`; `null` when none. |
|
|
1731
|
+
| `title` | `string` | yes | A one-line identification, with inline reference links like [`MentionNameMatch.title`](#api-mentionnamematch). |
|
|
1732
|
+
| `description` | `string` | yes | A paragraph about the place, with the same inline links. |
|
|
1733
|
+
| `type` | `string` | yes | The kind of place, e.g. `city`, `region`, `mountain`. |
|
|
1734
|
+
| `relatedLocations` | `Array<string>` | yes | Ids of other location records. |
|
|
1735
|
+
| `modernIdentification` | `string \| null` | yes | The modern site or name, when known. |
|
|
1736
|
+
| `coordinates` | `MentionLocationCoordinates \| null` | yes | |
|
|
1737
|
+
| `verses` | `Array<string>` | yes | Short verse keys where the Bible prints the name; ranges are collapsed. |
|
|
1738
|
+
| `links` | `Array<MentionLocationLink>` | yes | External references (Wikipedia, Easton's, New Advent…). |
|
|
1739
|
+
| `wikipedia` | `string \| null` | yes | The record's Wikipedia URL, or `null`. |
|
|
1740
|
+
| `uncertainty` | `boolean` | yes | `true` when the identification or location is uncertain. |
|
|
1741
|
+
| `matterRange` | `number` | yes | Importance rank on the same scale as [`MentionNameMatch.matterRange`](#api-mentionnamematch). |
|
|
1742
|
+
|
|
1743
|
+
<a id="api-mentionlocationpreview"></a>
|
|
1744
|
+
|
|
1745
|
+
#### `MentionLocationPreview`
|
|
1746
|
+
|
|
1747
|
+
A location record as the mention UI displays it: the dataset record, or a
|
|
1748
|
+
fallback built from what a mention in the note carries. `id` is `null` when
|
|
1749
|
+
the mention has no record id.
|
|
1750
|
+
|
|
1751
|
+
```ts
|
|
1752
|
+
type MentionLocationPreview = Omit<MentionLocationMatch, 'id'> & {
|
|
1753
|
+
id: string | null;
|
|
1754
|
+
};
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
<a id="api-mentionnamelink"></a>
|
|
1758
|
+
|
|
1759
|
+
#### `MentionNameLink`
|
|
1760
|
+
|
|
1761
|
+
An external reference about a record.
|
|
1762
|
+
|
|
1763
|
+
| Property | Type | Required | Description |
|
|
1764
|
+
| --- | --- | --- | --- |
|
|
1765
|
+
| `type` | `string` | yes | The source, e.g. `wikipedia`, `easton`, `newadvent`. |
|
|
1766
|
+
| `url` | `string` | yes | |
|
|
1767
|
+
|
|
1768
|
+
<a id="api-mentionnamematch"></a>
|
|
1769
|
+
|
|
1770
|
+
#### `MentionNameMatch`
|
|
1771
|
+
|
|
1772
|
+
One person/name record — what `NamesLookupManager` searches and returns, and
|
|
1773
|
+
what an `@` mention shows. Fields holding other records (`parents`,
|
|
1774
|
+
`locations`, …) hold their ids; resolve them with `getRecordsByIds`.
|
|
1775
|
+
|
|
1776
|
+
| Property | Type | Required | Description |
|
|
1777
|
+
| --- | --- | --- | --- |
|
|
1778
|
+
| `id` | `string` | yes | Stable record id; mentions in saved notes refer to it. |
|
|
1779
|
+
| `name` | `string` | yes | The name as printed in this dataset's Bible text. |
|
|
1780
|
+
| `kjvName` | `string \| null` | yes | The KJV English name, carried only by translated datasets (the km-BFBS mirror and any future one) where `name` holds the translated form. `null` on the KJV dataset itself, whose `name` already is the English one. The lookup managers index it alongside `name`, so a translated dataset stays searchable by its English name, and the UI shows it beside the translated name the way a Bible book reads "លោកុប្បត្តិ (Genesis)". |
|
|
1781
|
+
| `oldName` | `string \| null` | yes | A former name (e.g. Abram for Abraham), searchable like `name`; `null` when none. |
|
|
1782
|
+
| `title` | `string` | yes | A one-line identification ("prophet who led Israel out of Egypt"). Like `description`, it may carry inline reference links: `[Egypt](location-id://…)`, `[Amram](name-id://…)`, `[Genesis 1:1](verse-key://GEN 1:1)`, `[Genesis](book-key://GEN)`, `[Genesis 14](chapter-key://GEN 14)`. |
|
|
1783
|
+
| `description` | `string` | yes | A paragraph about the person, with the same inline links as `title`. |
|
|
1784
|
+
| `gender` | `string` | yes | `male`, `female` or `unknown` in the generated datasets; `''` when absent. |
|
|
1785
|
+
| `age` | `string` | yes | Age as stated in the text (e.g. `120 years`); `''` when unknown. |
|
|
1786
|
+
| `years` | `Array<MentionNameYearRange>` | yes | Dated spans such as a king's reign; usually empty. |
|
|
1787
|
+
| `locations` | `Array<string>` | yes | Ids of location records tied to the person. |
|
|
1788
|
+
| `spouses` | `Array<string>` | yes | Ids of name records. |
|
|
1789
|
+
| `children` | `Array<string>` | yes | Ids of name records. |
|
|
1790
|
+
| `parents` | `Array<string>` | yes | Ids of name records. |
|
|
1791
|
+
| `siblings` | `Array<string>` | yes | Ids of name records. |
|
|
1792
|
+
| `cousin` | `Array<string>` | yes | Ids of name records. |
|
|
1793
|
+
| `type` | `string` | yes | The raw type; `normalizeMentionNameType` maps it to a [`MentionNameType`](#api-mentionnametype). |
|
|
1794
|
+
| `verses` | `Array<string>` | yes | Short verse keys where the Bible prints the name, e.g. `GEN 1:1` or a collapsed range `1SA 17:1-4` (so the array length is not a verse count). |
|
|
1795
|
+
| `links` | `Array<MentionNameLink>` | yes | External references (Wikipedia, Easton's, New Advent…). |
|
|
1796
|
+
| `wikipedia` | `string \| null` | yes | The record's Wikipedia URL, or `null`. |
|
|
1797
|
+
| `matterRange` | `number` | yes | How much the record matters, ascending: 0 is the most important on this dataset's scale. Orders every listing and breaks ties in search. Records without a rank get `Infinity` and sort to the very end. |
|
|
1798
|
+
|
|
1799
|
+
<a id="api-mentionnamepreview"></a>
|
|
1800
|
+
|
|
1801
|
+
#### `MentionNamePreview`
|
|
1802
|
+
|
|
1803
|
+
A name record as the mention UI displays it: the dataset record, or a
|
|
1804
|
+
fallback built from what a mention in the note carries when the dataset has
|
|
1805
|
+
no such record. `id` is `null` when the mention has no record id.
|
|
1806
|
+
|
|
1807
|
+
```ts
|
|
1808
|
+
type MentionNamePreview = Omit<MentionNameMatch, 'id'> & {
|
|
1809
|
+
id: string | null;
|
|
1810
|
+
};
|
|
1811
|
+
```
|
|
1812
|
+
|
|
1813
|
+
<a id="api-mentionnametype"></a>
|
|
1814
|
+
|
|
1815
|
+
#### `MentionNameType`
|
|
1816
|
+
|
|
1817
|
+
The set of name "types" carried by biblical name records. Each type maps to a
|
|
1818
|
+
distinct icon so mentions can be told apart at a glance in the editor pills,
|
|
1819
|
+
the typeahead menu, the hover card, and the advanced panel.
|
|
1820
|
+
|
|
1821
|
+
When adding a new type here, add a matching `data-lexical-mention-name-type`
|
|
1822
|
+
mask rule in `AppComp.scss` so the editor pill icon stays in sync, and an
|
|
1823
|
+
entry in `NAME_TYPE_ICON_CLASS` in `plugins/MentionNamePlugin/nameTypeIcons`.
|
|
1824
|
+
|
|
1825
|
+
```ts
|
|
1826
|
+
type MentionNameType = 'person' | 'concept' | 'place' | 'group' | 'deity' | 'month' | 'supernatural' | 'life' | 'unknown';
|
|
1827
|
+
```
|
|
1828
|
+
|
|
1829
|
+
<a id="api-mentionnameyearrange"></a>
|
|
1830
|
+
|
|
1831
|
+
#### `MentionNameYearRange`
|
|
1832
|
+
|
|
1833
|
+
A dated span in a person's life, e.g. a reign.
|
|
1834
|
+
|
|
1835
|
+
| Property | Type | Required | Description |
|
|
1836
|
+
| --- | --- | --- | --- |
|
|
1837
|
+
| `type` | `string` | yes | What the span is, e.g. `reign` or `coregency`. |
|
|
1838
|
+
| `start` | `number` | yes | |
|
|
1839
|
+
| `end` | `number` | yes | |
|
|
1840
|
+
|
|
1841
|
+
<a id="api-nameslookupmanagerdatamap"></a>
|
|
1842
|
+
|
|
1843
|
+
#### `NamesLookupManagerDataMap`
|
|
1844
|
+
|
|
1845
|
+
Name datasets keyed by language code, e.g. `{ en: …, km: … }`.
|
|
1846
|
+
|
|
1847
|
+
```ts
|
|
1848
|
+
type NamesLookupManagerDataMap = {
|
|
1849
|
+
[langCode: string]: NamesLookupManagerLangData;
|
|
1850
|
+
};
|
|
1851
|
+
```
|
|
1852
|
+
|
|
1853
|
+
<a id="api-nameslookupmanagerlangdata"></a>
|
|
1854
|
+
|
|
1855
|
+
#### `NamesLookupManagerLangData`
|
|
1856
|
+
|
|
1857
|
+
One language's name dataset, as `NamesLookupManager`'s constructor takes it.
|
|
1858
|
+
|
|
1859
|
+
| Property | Type | Required | Description |
|
|
1860
|
+
| --- | --- | --- | --- |
|
|
1861
|
+
| `records` | `ReadonlyArray<MentionNameMatch>` | yes | The normalized records (see `parseMentionNameMatches`). |
|
|
1862
|
+
| `versePersonsMap` | `VerseRecordIdsMap` | no | Short verse key (e.g. `"EXO 6:23"`) to the ids of the names it mentions. |
|
|
1863
|
+
|
|
1864
|
+
<a id="api-nameslookuppaginationoptions"></a>
|
|
1865
|
+
|
|
1866
|
+
#### `NamesLookupPaginationOptions`
|
|
1867
|
+
|
|
1868
|
+
`LookupPaginationOptions` plus a name-type filter.
|
|
1869
|
+
|
|
1870
|
+
```ts
|
|
1871
|
+
type NamesLookupPaginationOptions = LookupPaginationOptions & {
|
|
1872
|
+
/** Only records of this type. */
|
|
1873
|
+
type?: MentionNameType;
|
|
1874
|
+
};
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
<a id="api-nameslookupsearchoptions"></a>
|
|
1878
|
+
|
|
1879
|
+
#### `NamesLookupSearchOptions`
|
|
1880
|
+
|
|
1881
|
+
`LookupSearchOptions` plus a name-type filter.
|
|
1882
|
+
|
|
1883
|
+
```ts
|
|
1884
|
+
type NamesLookupSearchOptions = LookupSearchOptions & {
|
|
1885
|
+
/** Only records of this type; applied before `limit`. */
|
|
1886
|
+
type?: MentionNameType;
|
|
1887
|
+
};
|
|
1888
|
+
```
|
|
1889
|
+
|
|
1890
|
+
<a id="api-nametypecount"></a>
|
|
1891
|
+
|
|
1892
|
+
#### `NameTypeCount`
|
|
1893
|
+
|
|
1894
|
+
How many records of one name type a dataset holds.
|
|
1895
|
+
|
|
1896
|
+
| Property | Type | Required | Description |
|
|
1897
|
+
| --- | --- | --- | --- |
|
|
1898
|
+
| `type` | `MentionNameType` | yes | |
|
|
1899
|
+
| `count` | `number` | yes | |
|
|
1900
|
+
|
|
1901
|
+
<a id="api-verserecordidsmap"></a>
|
|
1902
|
+
|
|
1903
|
+
#### `VerseRecordIdsMap`
|
|
1904
|
+
|
|
1905
|
+
```ts
|
|
1906
|
+
type VerseRecordIdsMap = Record<string, ReadonlyArray<string>>;
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
### Supporting types
|
|
1910
|
+
|
|
1911
|
+
Not exported, but used by the public signatures above — shown so every shape a host has to produce or consume is spelled out.
|
|
1912
|
+
|
|
1913
|
+
#### `LibraryItems`
|
|
1914
|
+
|
|
1915
|
+
```ts
|
|
1916
|
+
type LibraryItems = readonly any[];
|
|
1917
|
+
```
|
|
1918
|
+
|
|
1919
|
+
#### `MentionedBibleDataType`
|
|
1920
|
+
|
|
1921
|
+
A Bible verse as the host renders it: a title line plus the full text.
|
|
1922
|
+
|
|
1923
|
+
| Property | Type | Required | Description |
|
|
1924
|
+
| --- | --- | --- | --- |
|
|
1925
|
+
| `title` | `string` | yes | The verse reference as displayed, e.g. `(KJV) Genesis 1:1`. |
|
|
1926
|
+
| `fullText` | `string` | yes | The title line followed by the verse lines, in the same shape the editor accepts when Bible text is pasted after `^`: `(KJV) Genesis 1:1\n(1): In the beginning…`. |
|
|
1927
|
+
| `style` | `CSSProperties` | no | Extra CSS for this verse's text, e.g. a font for a non-Latin version. |
|