@aspan-corporation/ac-shared 1.2.36 → 1.2.38
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/lib/utils/diary.d.ts +21 -0
- package/lib/utils/diary.js +26 -3
- package/package.json +1 -1
package/lib/utils/diary.d.ts
CHANGED
|
@@ -15,8 +15,21 @@ export declare const TAG_DIARY_TITLE = "ac:diary:title";
|
|
|
15
15
|
export declare const TAG_DIARY_PREVIEW = "ac:diary:preview";
|
|
16
16
|
/** One per embedded photo: value is the referenced media key. */
|
|
17
17
|
export declare const TAG_DIARY_PHOTO = "ac:diary:photo";
|
|
18
|
+
/** One per embedded audio recording: value is the referenced diary key. */
|
|
19
|
+
export declare const TAG_DIARY_AUDIO = "ac:diary:audio";
|
|
18
20
|
/** Namespace for body word tokens: `ac:text:<word>`. */
|
|
19
21
|
export declare const TEXT_TOKEN_PREFIX = "ac:text:";
|
|
22
|
+
/**
|
|
23
|
+
* Audio formats a browser MediaRecorder can produce: Safari records
|
|
24
|
+
* audio/mp4 (.m4a), Chromium/Firefox audio/webm or audio/ogg (opus).
|
|
25
|
+
* Deliberately kept SEPARATE from the image-only `isAllowedExtension`
|
|
26
|
+
* (thumbsKey.ts) — that allowlist is what keeps diary audio out of the
|
|
27
|
+
* meta-extractor/resizer dispatch on save, so recordings stay entry-only
|
|
28
|
+
* (no meta item, never in browse/search).
|
|
29
|
+
*/
|
|
30
|
+
export declare const AUDIO_EXTENSIONS: string[];
|
|
31
|
+
/** True when a key's extension is a supported diary audio format. */
|
|
32
|
+
export declare const isAllowedAudioExtension: (key: string) => boolean;
|
|
20
33
|
/** Max body characters surfaced in the preview tag. */
|
|
21
34
|
export declare const DIARY_PREVIEW_LENGTH = 160;
|
|
22
35
|
/** Upper bound on distinct word tokens written per entry (bounds item size). */
|
|
@@ -49,6 +62,14 @@ export declare const parseDiaryKeyDate: (key: string) => {
|
|
|
49
62
|
* words. Strips markdown syntax (code fences, image/link targets, formatting),
|
|
50
63
|
* drops stop-words and tokens shorter than 2 chars, and caps the result at
|
|
51
64
|
* `MAX_TEXT_TOKENS` to bound the meta-item size. No stemming (exact-word match).
|
|
65
|
+
*
|
|
66
|
+
* Word boundaries and lowercasing are Unicode-aware: tokens are split on any
|
|
67
|
+
* run of characters that are neither a Unicode letter (`\p{L}`) nor number
|
|
68
|
+
* (`\p{N}`), so non-Latin scripts (e.g. Cyrillic) survive as searchable words
|
|
69
|
+
* rather than being discarded. `toLowerCase()` is likewise Unicode-aware; we
|
|
70
|
+
* deliberately avoid `toLocaleLowerCase()` so tokenisation is deterministic and
|
|
71
|
+
* independent of the host locale (the indexer lambda and the browser that
|
|
72
|
+
* builds search queries must produce identical tokens).
|
|
52
73
|
*/
|
|
53
74
|
export declare const tokenizeText: (markdown: string) => string[];
|
|
54
75
|
/** Plain-text preview: strip markdown, collapse whitespace, truncate. */
|
package/lib/utils/diary.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* searchable by tokenising it into `ac:text:<word>` tags that ride the existing
|
|
6
6
|
* inverted-index search table.
|
|
7
7
|
*/
|
|
8
|
+
import { getKeyExtension } from "./thumbsKey.js";
|
|
8
9
|
/** Key prefix for every diary object (and the `folder`/id namespace). */
|
|
9
10
|
export const DIARY_PREFIX = "diary/";
|
|
10
11
|
/** Marks a meta item as a diary entry (value "true"). */
|
|
@@ -15,8 +16,21 @@ export const TAG_DIARY_TITLE = "ac:diary:title";
|
|
|
15
16
|
export const TAG_DIARY_PREVIEW = "ac:diary:preview";
|
|
16
17
|
/** One per embedded photo: value is the referenced media key. */
|
|
17
18
|
export const TAG_DIARY_PHOTO = "ac:diary:photo";
|
|
19
|
+
/** One per embedded audio recording: value is the referenced diary key. */
|
|
20
|
+
export const TAG_DIARY_AUDIO = "ac:diary:audio";
|
|
18
21
|
/** Namespace for body word tokens: `ac:text:<word>`. */
|
|
19
22
|
export const TEXT_TOKEN_PREFIX = "ac:text:";
|
|
23
|
+
/**
|
|
24
|
+
* Audio formats a browser MediaRecorder can produce: Safari records
|
|
25
|
+
* audio/mp4 (.m4a), Chromium/Firefox audio/webm or audio/ogg (opus).
|
|
26
|
+
* Deliberately kept SEPARATE from the image-only `isAllowedExtension`
|
|
27
|
+
* (thumbsKey.ts) — that allowlist is what keeps diary audio out of the
|
|
28
|
+
* meta-extractor/resizer dispatch on save, so recordings stay entry-only
|
|
29
|
+
* (no meta item, never in browse/search).
|
|
30
|
+
*/
|
|
31
|
+
export const AUDIO_EXTENSIONS = ["m4a", "webm", "ogg"];
|
|
32
|
+
/** True when a key's extension is a supported diary audio format. */
|
|
33
|
+
export const isAllowedAudioExtension = (key) => AUDIO_EXTENSIONS.includes(getKeyExtension(key));
|
|
20
34
|
/** Max body characters surfaced in the preview tag. */
|
|
21
35
|
export const DIARY_PREVIEW_LENGTH = 160;
|
|
22
36
|
/** Upper bound on distinct word tokens written per entry (bounds item size). */
|
|
@@ -91,6 +105,14 @@ const STOP_WORDS = new Set([
|
|
|
91
105
|
* words. Strips markdown syntax (code fences, image/link targets, formatting),
|
|
92
106
|
* drops stop-words and tokens shorter than 2 chars, and caps the result at
|
|
93
107
|
* `MAX_TEXT_TOKENS` to bound the meta-item size. No stemming (exact-word match).
|
|
108
|
+
*
|
|
109
|
+
* Word boundaries and lowercasing are Unicode-aware: tokens are split on any
|
|
110
|
+
* run of characters that are neither a Unicode letter (`\p{L}`) nor number
|
|
111
|
+
* (`\p{N}`), so non-Latin scripts (e.g. Cyrillic) survive as searchable words
|
|
112
|
+
* rather than being discarded. `toLowerCase()` is likewise Unicode-aware; we
|
|
113
|
+
* deliberately avoid `toLocaleLowerCase()` so tokenisation is deterministic and
|
|
114
|
+
* independent of the host locale (the indexer lambda and the browser that
|
|
115
|
+
* builds search queries must produce identical tokens).
|
|
94
116
|
*/
|
|
95
117
|
export const tokenizeText = (markdown) => {
|
|
96
118
|
if (!markdown)
|
|
@@ -109,11 +131,12 @@ export const tokenizeText = (markdown) => {
|
|
|
109
131
|
// leftover markdown punctuation
|
|
110
132
|
.replace(/[#>*_~\-]+/g, " ");
|
|
111
133
|
const seen = new Set();
|
|
112
|
-
for (const raw of stripped.toLowerCase().split(/[
|
|
134
|
+
for (const raw of stripped.toLowerCase().split(/[^\p{L}\p{N}]+/u)) {
|
|
113
135
|
if (raw.length < 2)
|
|
114
136
|
continue;
|
|
115
|
-
// Drop pure
|
|
116
|
-
|
|
137
|
+
// Drop pure-number tokens (dates/counts add noise) in any script; keep
|
|
138
|
+
// alphanumerics like "v2".
|
|
139
|
+
if (/^\p{N}+$/u.test(raw))
|
|
117
140
|
continue;
|
|
118
141
|
if (STOP_WORDS.has(raw))
|
|
119
142
|
continue;
|