@readium/speech 0.1.1 → 0.3.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.
@@ -0,0 +1,4 @@
1
+ export declare const BINDING_PUNCT_CLASS = "\\p{Pe}\\p{Pf}.,;:!?\uFF0C\u3002\u3001\uFF1B\uFF1A\uFF01\uFF1F\u060C\u061B\u061F";
2
+ export declare const OPENING_PUNCT_CLASS = "\\p{Ps}\\p{Pi}\u00BF\u00A1";
3
+ export declare function startsWithBindingPunct(s: string): boolean;
4
+ export declare function startsWithOpeningPunct(s: string): boolean;
@@ -1,6 +1,6 @@
1
1
  export interface ReadiumSpeechUtterance {
2
2
  id?: string;
3
- text: string;
4
- ssml?: boolean;
3
+ plain?: string;
4
+ ssml?: string;
5
5
  language?: string;
6
6
  }
@@ -0,0 +1,2 @@
1
+ import { Announcements } from './types.js';
2
+ export declare const defaultAnnouncements: Announcements;
@@ -0,0 +1,12 @@
1
+ import { GndObject } from '../gnd/types.js';
2
+ import { ReadiumSpeechUtterance } from '../utterance.js';
3
+ import { ExtractUtterancesOptions } from './types.js';
4
+ /**
5
+ * Extracts an ordered list of read-aloud utterances from a Guided
6
+ * Navigation node tree, following the patterns documented at
7
+ * https://github.com/readium/guided-navigation/tree/main/examples/read-aloud.
8
+ *
9
+ * Accepts `GndObject[]` (as returned by `parseMarkup()`, or `GndDocument.guided`)
10
+ * rather than a wrapped document.
11
+ */
12
+ export declare function extractUtterances(nodes: GndObject[], options: ExtractUtterancesOptions): ReadiumSpeechUtterance[];
@@ -0,0 +1,4 @@
1
+ export { extractUtterances } from './extractUtterances.js';
2
+ export { skippableRoles } from './roles.js';
3
+ export { defaultAnnouncements } from './announcements.js';
4
+ export type { Announcement, AnnouncementKey, AnnouncementPair, Announcements, RoleAnnouncement, ExtractUtterancesOptions, } from './types.js';
@@ -0,0 +1 @@
1
+ export declare function stripLangTags(ssml: string): string;
@@ -0,0 +1,2 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ export declare const skippableRoles: GndRole[];
@@ -0,0 +1,54 @@
1
+ import { GndObject } from '../gnd/types.js';
2
+ export interface ResolvedNodeText {
3
+ plain?: string;
4
+ ssml?: string;
5
+ language?: string;
6
+ }
7
+ /**
8
+ * Resolves a `GndObject.text` value (a plain string, or a `GndText`
9
+ * carrying separate plain/SSML variants) into the shape an utterance needs.
10
+ *
11
+ * Mirrors the Readium text object as-is: `plain` and `ssml` are independent
12
+ * alternatives, not one derived from the other, so both are passed through
13
+ * whenever the source provides both (e.g. a footnote reference, where the
14
+ * SSML carries an embedded `<readium:noteref>` placeholder and the plain
15
+ * variant already omits it). The SSML variant gets `stripPlaceholders`
16
+ * applied first, since this extractor speaks referenced objects (noterefs,
17
+ * pagebreaks) separately via the normal children walk rather than inline —
18
+ * and if stripping a placeholder leaves no actual SSML markup behind, `ssml`
19
+ * is dropped entirely rather than reported as a duplicate of `plain`.
20
+ *
21
+ * `language` is carried alongside either variant: the GND converter attaches
22
+ * the nearest ancestor's declared language (e.g. `<html lang="fr">`) to every
23
+ * text node under it, so this is the only place that document-declared
24
+ * language would otherwise be lost.
25
+ */
26
+ export declare function resolveNodeText(text: GndObject["text"]): ResolvedNodeText | undefined;
27
+ export declare function stripSsmlTags(ssml: string): string;
28
+ export interface LangSegment {
29
+ plain: string;
30
+ language?: string;
31
+ }
32
+ export declare function hasLangTag(ssml: string): boolean;
33
+ /**
34
+ * Splits an SSML string into per-language runs of plain text (`format:
35
+ * "plain"` has no `<lang>` markup, so a language shift mid-string becomes
36
+ * separate segments instead). Punctuation touching a `<lang>` boundary —
37
+ * separated by nothing or only whitespace — joins the tagged run rather
38
+ * than staying with its lexical run: close-punct after `</lang>` joins the
39
+ * run that just closed, open-punct before `<lang>` joins the run about to
40
+ * start.
41
+ */
42
+ export declare function splitOnLangTags(ssml: string, baseLanguage: string | undefined): LangSegment[];
43
+ export interface SsmlSegment {
44
+ ssml?: string;
45
+ placeholderId?: string;
46
+ }
47
+ export declare function hasPlaceholder(ssml: string): boolean;
48
+ /**
49
+ * Splits a raw (pre-`stripPlaceholders`) SSML string on its embedded
50
+ * `<readium:TAG id="...">` placeholders, for `interruptSentence`: each
51
+ * placeholder becomes its own segment (resolved via the `GndObject` sharing
52
+ * its `id`) instead of being spoken after the whole enclosing text.
53
+ */
54
+ export declare function splitOnPlaceholders(ssml: string): SsmlSegment[];
@@ -0,0 +1,18 @@
1
+ import { GndRole } from '../gnd/types.js';
2
+ export type AnnouncementKey = string;
3
+ export type Announcement = string | ((params?: Record<string, string>) => string);
4
+ export interface AnnouncementPair {
5
+ start: Announcement;
6
+ end: Announcement;
7
+ }
8
+ export type RoleAnnouncement = Announcement | AnnouncementPair;
9
+ export declare function isAnnouncementPair(a: RoleAnnouncement): a is AnnouncementPair;
10
+ export type Announcements = Record<AnnouncementKey, RoleAnnouncement>;
11
+ export interface ExtractUtterancesOptions {
12
+ format?: "plain" | "ssml";
13
+ announcements?: Announcements;
14
+ skip?: GndRole[];
15
+ language?: "none" | "block-level" | "always";
16
+ interruptSentence?: boolean;
17
+ contextualize?: boolean;
18
+ }
@@ -1,4 +1,4 @@
1
- import { ReadiumSpeechVoice } from './types';
1
+ import { ReadiumSpeechJSONVoice } from './types';
2
2
  export interface LanguageWithRegions {
3
3
  baseLang: string;
4
4
  regions: string[];
@@ -15,9 +15,9 @@ export declare const normalizeLanguageCode: (lang: string) => string;
15
15
  /**
16
16
  * Get all voices for a specific language
17
17
  * @param {string} lang - Language code (e.g., "en", "fr", "zh-CN")
18
- * @returns {Promise<ReadiumSpeechVoice[]>} Promise resolving to array of voices for the specified language
18
+ * @returns {Promise<ReadiumSpeechJSONVoice[]>} Promise resolving to array of voices for the specified language
19
19
  */
20
- export declare const getVoices: (lang: string) => Promise<ReadiumSpeechVoice[]>;
20
+ export declare const getVoices: (lang: string) => Promise<ReadiumSpeechJSONVoice[]>;
21
21
  /**
22
22
  * Get all available language codes
23
23
  * @returns {string[]} Array of available language codes
@@ -46,13 +46,6 @@ export interface ReadiumSpeechJSONVoice {
46
46
  browser?: TBrowser[];
47
47
  preloaded?: boolean;
48
48
  }
49
- export interface VoiceFilterData {
50
- voices: Array<{
51
- name: string;
52
- altNames?: string[];
53
- [key: string]: any;
54
- }>;
55
- }
56
49
  export interface ReadiumSpeechVoice {
57
50
  source: TSource;
58
51
  label: string;
@@ -77,11 +70,14 @@ export interface ReadiumSpeechVoice {
77
70
  nativeID?: string | string[];
78
71
  note?: string;
79
72
  provider?: string;
80
- [key: string]: any;
73
+ isDefault?: boolean;
74
+ offlineAvailability?: boolean;
75
+ isNovelty?: boolean;
76
+ isLowQuality?: boolean;
81
77
  }
82
78
  export interface VoiceData {
83
79
  language: string;
84
80
  defaultRegion: string;
85
81
  testUtterance: string;
86
- voices: ReadiumSpeechVoice[];
82
+ voices: ReadiumSpeechJSONVoice[];
87
83
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@readium/speech",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "A TypeScript library for implementing read aloud features with Web technologies, following best practices for digital publishing.",
5
5
  "author": "Readium Foundation",
6
6
  "keywords": [
7
- "readium",
8
- "speech",
9
- "tts",
10
- "text-to-speech",
11
- "read-aloud",
7
+ "readium",
8
+ "speech",
9
+ "tts",
10
+ "text-to-speech",
11
+ "read-aloud",
12
12
  "accessibility"
13
13
  ],
14
14
  "homepage": "https://readium.org/speech/",
@@ -37,7 +37,12 @@
37
37
  },
38
38
  "scripts": {
39
39
  "test": "npm run build && NODE_NO_WARNINGS=1 ava test/**/*.test.ts",
40
+ "test:voices": "npm run build && NODE_NO_WARNINGS=1 ava test/WebSpeechVoiceManager/*.test.ts",
41
+ "test:gnd": "NODE_NO_WARNINGS=1 ava test/gnd/*.test.ts",
42
+ "test:utterances": "NODE_NO_WARNINGS=1 ava test/utterances/*.test.ts",
40
43
  "generate-metadata": "node scripts/generate-metadata.js",
44
+ "generate-fixtures-manifest": "node scripts/build-fixtures-manifest.js",
45
+ "generate-utterances": "npm run build && node scripts/generate-utterances.js",
41
46
  "clean": "rimraf ./build",
42
47
  "build": "vite build",
43
48
  "start": "http-server ./",
@@ -47,6 +52,7 @@
47
52
  "@ava/typescript": "^6.0.0",
48
53
  "ava": "^6.4.0",
49
54
  "http-server": "^14.1.1",
55
+ "linkedom": "^0.18.13",
50
56
  "rimraf": "^6.0.1",
51
57
  "ts-node": "^10.9.2",
52
58
  "typescript": "^5.8.3",
@@ -54,6 +60,8 @@
54
60
  "vite-plugin-dts": "^4.5.4"
55
61
  },
56
62
  "dependencies": {
63
+ "@readium/decorator": "^1.0.1",
64
+ "@readium/shared": "^2.3.1",
57
65
  "string-strip-html": "^13.4.23"
58
66
  }
59
67
  }