@readium/shared 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2277 -1487
- package/dist/index.umd.cjs +3 -3
- package/package.json +17 -16
- package/src/opds/Acquisition.ts +1 -1
- package/src/publication/BelongsTo.ts +1 -1
- package/src/publication/Contributor.ts +2 -2
- package/src/publication/GuidedNavigation.ts +1 -1
- package/src/publication/Link.ts +2 -2
- package/src/publication/LocatorCollection.ts +1 -1
- package/src/publication/Metadata.ts +9 -1
- package/src/publication/PublicationCollection.ts +3 -3
- package/src/publication/Subject.ts +1 -1
- package/src/publication/accessibility/Accessibility.ts +860 -0
- package/src/publication/accessibility/AccessibilityMetadataDisplayGuide.ts +1055 -0
- package/src/publication/accessibility/Localization.md +203 -0
- package/src/publication/accessibility/Localization.ts +115 -0
- package/src/publication/accessibility/index.ts +3 -0
- package/src/publication/accessibility/locales/en.json +231 -0
- package/src/publication/accessibility/locales/fr.json +231 -0
- package/src/publication/index.ts +1 -0
- package/src/publication/opds/Properties.ts +1 -1
- package/src/util/JSONParse.ts +1 -1
- package/types/src/publication/Metadata.d.ts +3 -0
- package/types/src/publication/accessibility/Accessibility.d.ts +321 -0
- package/types/src/publication/accessibility/Localization.d.ts +8 -0
- package/types/src/publication/index.d.ts +1 -0
|
@@ -0,0 +1,1055 @@
|
|
|
1
|
+
import { Accessibility, Feature, AccessMode, PrimaryAccessMode, Hazard } from './Accessibility';
|
|
2
|
+
import { Publication } from '../Publication';
|
|
3
|
+
import { AccessibilityProfile } from './Accessibility';
|
|
4
|
+
|
|
5
|
+
import { Localization } from './Localization';
|
|
6
|
+
import { Layout } from '../Layout';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a single accessibility claim
|
|
10
|
+
*/
|
|
11
|
+
export interface AccessibilityDisplayStatement {
|
|
12
|
+
id: string;
|
|
13
|
+
compactString?: string;
|
|
14
|
+
descriptiveString?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Represents a collection of related accessibility claims which should be
|
|
19
|
+
* displayed together in a section
|
|
20
|
+
*/
|
|
21
|
+
export interface AccessibilityDisplayField {
|
|
22
|
+
// Unique identifier for this display field
|
|
23
|
+
id: string;
|
|
24
|
+
|
|
25
|
+
// Title for this display field
|
|
26
|
+
title: string;
|
|
27
|
+
|
|
28
|
+
// List of accessibility claims to display for this field
|
|
29
|
+
statements: AccessibilityDisplayStatement[];
|
|
30
|
+
|
|
31
|
+
// Indicates whether this display field should be rendered
|
|
32
|
+
shouldDisplay: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Represents the different ways visual adjustments can be made
|
|
37
|
+
*/
|
|
38
|
+
export enum VisualAdjustments {
|
|
39
|
+
Unknown = 'unknown',
|
|
40
|
+
Modifiable = 'modifiable',
|
|
41
|
+
Unmodifiable = 'unmodifiable'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Represents the different types of non-visual reading
|
|
46
|
+
*/
|
|
47
|
+
export enum NonvisualReading {
|
|
48
|
+
NoMetadata = 'noMetadata',
|
|
49
|
+
Readable = 'readable',
|
|
50
|
+
NotFully = 'notFully',
|
|
51
|
+
Unreadable = 'unreadable'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Represents the different types of prerecorded audio
|
|
56
|
+
*/
|
|
57
|
+
export enum PrerecordedAudio {
|
|
58
|
+
NoMetadata = 'noMetadata',
|
|
59
|
+
Synchronized = 'synchronized',
|
|
60
|
+
AudioOnly = 'audioOnly',
|
|
61
|
+
AudioComplementary = 'audioComplementary'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The ways of reading display field is a banner heading that groups
|
|
66
|
+
* together the following information about how the content facilitates
|
|
67
|
+
* access.
|
|
68
|
+
*/
|
|
69
|
+
export class WaysOfReading implements AccessibilityDisplayField {
|
|
70
|
+
public readonly id = "ways-of-reading.title";
|
|
71
|
+
public readonly title: string;
|
|
72
|
+
public readonly shouldDisplay: boolean;
|
|
73
|
+
|
|
74
|
+
public readonly visualAdjustments: VisualAdjustments;
|
|
75
|
+
public readonly nonvisualReading: NonvisualReading;
|
|
76
|
+
public readonly nonvisualReadingAltText: boolean;
|
|
77
|
+
public readonly prerecordedAudio: PrerecordedAudio;
|
|
78
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
79
|
+
|
|
80
|
+
private constructor(
|
|
81
|
+
visualAdjustments: VisualAdjustments = VisualAdjustments.Unknown,
|
|
82
|
+
nonvisualReading: NonvisualReading = NonvisualReading.NoMetadata,
|
|
83
|
+
nonvisualReadingAltText: boolean = false,
|
|
84
|
+
prerecordedAudio: PrerecordedAudio = PrerecordedAudio.NoMetadata
|
|
85
|
+
) {
|
|
86
|
+
this.visualAdjustments = visualAdjustments;
|
|
87
|
+
this.nonvisualReading = nonvisualReading;
|
|
88
|
+
this.nonvisualReadingAltText = nonvisualReadingAltText;
|
|
89
|
+
this.prerecordedAudio = prerecordedAudio;
|
|
90
|
+
|
|
91
|
+
// This should be displayed even if there is no metadata
|
|
92
|
+
this.shouldDisplay = true;
|
|
93
|
+
|
|
94
|
+
const titleLocale = Localization.getString(this.id);
|
|
95
|
+
this.title = titleLocale.compact;
|
|
96
|
+
|
|
97
|
+
this.statements = [];
|
|
98
|
+
|
|
99
|
+
// Visual Adjustments
|
|
100
|
+
const visualAdjustmentsKey = visualAdjustments === VisualAdjustments.Modifiable
|
|
101
|
+
? "ways-of-reading.visual-adjustments.modifiable"
|
|
102
|
+
: visualAdjustments === VisualAdjustments.Unmodifiable
|
|
103
|
+
? "ways-of-reading.visual-adjustments.unmodifiable"
|
|
104
|
+
: "ways-of-reading.visual-adjustments.unknown";
|
|
105
|
+
|
|
106
|
+
const visualAdjustmentsLocale = Localization.getString(visualAdjustmentsKey);
|
|
107
|
+
this.statements.push({
|
|
108
|
+
id: visualAdjustmentsKey,
|
|
109
|
+
compactString: visualAdjustmentsLocale.compact,
|
|
110
|
+
descriptiveString: visualAdjustmentsLocale.descriptive
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Non-visual Reading
|
|
114
|
+
let nonvisualReadingKey = "";
|
|
115
|
+
if (nonvisualReading === NonvisualReading.Readable) {
|
|
116
|
+
nonvisualReadingKey = "ways-of-reading.nonvisual-reading.readable";
|
|
117
|
+
} else if (nonvisualReading === NonvisualReading.NotFully) {
|
|
118
|
+
nonvisualReadingKey = "ways-of-reading.nonvisual-reading.not-fully";
|
|
119
|
+
} else if (nonvisualReading === NonvisualReading.Unreadable) {
|
|
120
|
+
nonvisualReadingKey = "ways-of-reading.nonvisual-reading.none";
|
|
121
|
+
} else if (nonvisualReading === NonvisualReading.NoMetadata) {
|
|
122
|
+
nonvisualReadingKey = "ways-of-reading.nonvisual-reading.no-metadata";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const nonvisualReadingLocale = Localization.getString(nonvisualReadingKey);
|
|
126
|
+
this.statements.push({
|
|
127
|
+
id: nonvisualReadingKey,
|
|
128
|
+
compactString: nonvisualReadingLocale.compact,
|
|
129
|
+
descriptiveString: nonvisualReadingLocale.descriptive
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Non-visual Reading Alt Text
|
|
133
|
+
if (nonvisualReadingAltText) {
|
|
134
|
+
const altTextLocale = Localization.getString("ways-of-reading.nonvisual-reading.alt-text");
|
|
135
|
+
this.statements.push({
|
|
136
|
+
id: "ways-of-reading.nonvisual-reading.alt-text",
|
|
137
|
+
compactString: altTextLocale.compact,
|
|
138
|
+
descriptiveString: altTextLocale.descriptive
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Prerecorded Audio
|
|
143
|
+
let prerecordedAudioKey = "";
|
|
144
|
+
if (prerecordedAudio === PrerecordedAudio.Synchronized) {
|
|
145
|
+
prerecordedAudioKey = "ways-of-reading.prerecorded-audio.synchronized";
|
|
146
|
+
} else if (prerecordedAudio === PrerecordedAudio.AudioOnly) {
|
|
147
|
+
prerecordedAudioKey = "ways-of-reading.prerecorded-audio.only";
|
|
148
|
+
} else if (prerecordedAudio === PrerecordedAudio.AudioComplementary) {
|
|
149
|
+
prerecordedAudioKey = "ways-of-reading.prerecorded-audio.complementary";
|
|
150
|
+
} else if (prerecordedAudio === PrerecordedAudio.NoMetadata) {
|
|
151
|
+
prerecordedAudioKey = "ways-of-reading.prerecorded-audio.no-metadata";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const prerecordedAudioLocale = Localization.getString(prerecordedAudioKey);
|
|
155
|
+
this.statements.push({
|
|
156
|
+
id: prerecordedAudioKey,
|
|
157
|
+
compactString: prerecordedAudioLocale.compact,
|
|
158
|
+
descriptiveString: prerecordedAudioLocale.descriptive
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static fromPublication(publication: Publication): WaysOfReading {
|
|
163
|
+
const a11y = publication.metadata.accessibility ?? new Accessibility();
|
|
164
|
+
const features = a11y.feature ?? [];
|
|
165
|
+
const isFXL = publication.metadata.layout === Layout.fixed;
|
|
166
|
+
|
|
167
|
+
const visualAdjustments = features.some(f => f.value === Feature.DISPLAY_TRANSFORMABILITY.value)
|
|
168
|
+
? VisualAdjustments.Modifiable
|
|
169
|
+
: isFXL
|
|
170
|
+
? VisualAdjustments.Unmodifiable
|
|
171
|
+
: VisualAdjustments.Unknown;
|
|
172
|
+
|
|
173
|
+
const accessModes = a11y.accessMode ?? [];
|
|
174
|
+
const accessModeSufficient = a11y.accessModeSufficient ?? [];
|
|
175
|
+
|
|
176
|
+
const allText = accessModes.length > 0 && accessModes.every((m: AccessMode) => m.value === AccessMode.TEXTUAL.value) ||
|
|
177
|
+
accessModeSufficient.some((modes: PrimaryAccessMode) => {
|
|
178
|
+
const modeValue = modes.value;
|
|
179
|
+
if (Array.isArray(modeValue)) {
|
|
180
|
+
return modeValue.every(mode => mode === AccessMode.TEXTUAL.value);
|
|
181
|
+
}
|
|
182
|
+
return modeValue === AccessMode.TEXTUAL.value;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const someText = accessModes.some((m: AccessMode) => m.value === AccessMode.TEXTUAL.value) ||
|
|
186
|
+
accessModeSufficient.some((modes: PrimaryAccessMode) => {
|
|
187
|
+
const modeValue = modes.value;
|
|
188
|
+
if (Array.isArray(modeValue)) {
|
|
189
|
+
return modeValue.some(mode => mode === AccessMode.TEXTUAL.value);
|
|
190
|
+
}
|
|
191
|
+
return modeValue === AccessMode.TEXTUAL.value;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const noText = !(accessModes.length === 0 && accessModeSufficient.length === 0) &&
|
|
195
|
+
!accessModes.some((m: AccessMode) => m.value === AccessMode.TEXTUAL.value) &&
|
|
196
|
+
!accessModeSufficient.some((modes: PrimaryAccessMode) => {
|
|
197
|
+
const modeValue = modes.value;
|
|
198
|
+
if (Array.isArray(modeValue)) {
|
|
199
|
+
return modeValue.some(mode => mode === AccessMode.TEXTUAL.value);
|
|
200
|
+
}
|
|
201
|
+
return modeValue === AccessMode.TEXTUAL.value;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const hasTextAlt = features.some(f => [
|
|
205
|
+
Feature.LONG_DESCRIPTION.value,
|
|
206
|
+
Feature.ALTERNATIVE_TEXT.value,
|
|
207
|
+
Feature.DESCRIBED_MATH.value,
|
|
208
|
+
Feature.TRANSCRIPT.value
|
|
209
|
+
].includes(f.value));
|
|
210
|
+
|
|
211
|
+
const nonvisualReading = allText
|
|
212
|
+
? NonvisualReading.Readable
|
|
213
|
+
: (someText || hasTextAlt)
|
|
214
|
+
? NonvisualReading.NotFully
|
|
215
|
+
: noText
|
|
216
|
+
? NonvisualReading.Unreadable
|
|
217
|
+
: NonvisualReading.NoMetadata;
|
|
218
|
+
|
|
219
|
+
const nonvisualReadingAltText = hasTextAlt;
|
|
220
|
+
|
|
221
|
+
const prerecordedAudio = features.some(f => f.value === Feature.SYNCHRONIZED_AUDIO_TEXT.value)
|
|
222
|
+
? PrerecordedAudio.Synchronized
|
|
223
|
+
: accessModeSufficient.some((modes: PrimaryAccessMode) => {
|
|
224
|
+
const modeValue = modes.value;
|
|
225
|
+
if (Array.isArray(modeValue)) {
|
|
226
|
+
return modeValue.some(mode => mode === AccessMode.AUDITORY.value);
|
|
227
|
+
}
|
|
228
|
+
return modeValue === AccessMode.AUDITORY.value;
|
|
229
|
+
})
|
|
230
|
+
? PrerecordedAudio.AudioOnly
|
|
231
|
+
: accessModes.some((m: AccessMode) => m.value === AccessMode.AUDITORY.value)
|
|
232
|
+
? PrerecordedAudio.AudioComplementary
|
|
233
|
+
: PrerecordedAudio.NoMetadata;
|
|
234
|
+
|
|
235
|
+
return new WaysOfReading(
|
|
236
|
+
visualAdjustments,
|
|
237
|
+
nonvisualReading,
|
|
238
|
+
nonvisualReadingAltText,
|
|
239
|
+
prerecordedAudio
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Navigation features of the content
|
|
246
|
+
*/
|
|
247
|
+
export class Navigation implements AccessibilityDisplayField {
|
|
248
|
+
public readonly id = "navigation.title";
|
|
249
|
+
public readonly title: string;
|
|
250
|
+
public readonly shouldDisplay: boolean;
|
|
251
|
+
|
|
252
|
+
public readonly noMetadata: boolean;
|
|
253
|
+
public readonly tableOfContents: boolean;
|
|
254
|
+
public readonly index: boolean;
|
|
255
|
+
public readonly headings: boolean;
|
|
256
|
+
public readonly page: boolean;
|
|
257
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
258
|
+
|
|
259
|
+
private constructor(
|
|
260
|
+
tableOfContents: boolean = false,
|
|
261
|
+
index: boolean = false,
|
|
262
|
+
headings: boolean = false,
|
|
263
|
+
page: boolean = false
|
|
264
|
+
) {
|
|
265
|
+
this.tableOfContents = tableOfContents;
|
|
266
|
+
this.index = index;
|
|
267
|
+
this.headings = headings;
|
|
268
|
+
this.page = page;
|
|
269
|
+
this.noMetadata = !tableOfContents && !index && !headings && !page;
|
|
270
|
+
|
|
271
|
+
const titleLocale = Localization.getString(this.id);
|
|
272
|
+
this.title = titleLocale.compact;
|
|
273
|
+
|
|
274
|
+
this.shouldDisplay = !this.noMetadata;
|
|
275
|
+
|
|
276
|
+
this.statements = [];
|
|
277
|
+
if (tableOfContents) {
|
|
278
|
+
const tocLocale = Localization.getString("navigation.toc");
|
|
279
|
+
this.statements.push({
|
|
280
|
+
id: "navigation.toc",
|
|
281
|
+
compactString: tocLocale.compact,
|
|
282
|
+
descriptiveString: tocLocale.descriptive
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
if (index) {
|
|
286
|
+
const indexLocale = Localization.getString("navigation.index");
|
|
287
|
+
this.statements.push({
|
|
288
|
+
id: "navigation.index",
|
|
289
|
+
compactString: indexLocale.compact,
|
|
290
|
+
descriptiveString: indexLocale.descriptive
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
if (headings) {
|
|
294
|
+
const headingsLocale = Localization.getString("navigation.structural");
|
|
295
|
+
this.statements.push({
|
|
296
|
+
id: "navigation.structural",
|
|
297
|
+
compactString: headingsLocale.compact,
|
|
298
|
+
descriptiveString: headingsLocale.descriptive
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (page) {
|
|
302
|
+
const pageNavLocale = Localization.getString("navigation.page-navigation");
|
|
303
|
+
this.statements.push({
|
|
304
|
+
id: "navigation.page-navigation",
|
|
305
|
+
compactString: pageNavLocale.compact,
|
|
306
|
+
descriptiveString: pageNavLocale.descriptive
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (this.statements.length === 0) {
|
|
311
|
+
const noNavLocale = Localization.getString("navigation.no-metadata");
|
|
312
|
+
this.statements.push({
|
|
313
|
+
id: "navigation.no-metadata",
|
|
314
|
+
compactString: noNavLocale.compact,
|
|
315
|
+
descriptiveString: noNavLocale.descriptive
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
public static fromPublication(publication: Publication): Navigation {
|
|
321
|
+
const a11y = publication.metadata.accessibility ?? new Accessibility();
|
|
322
|
+
const features = a11y.feature ?? [];
|
|
323
|
+
|
|
324
|
+
return new Navigation(
|
|
325
|
+
features.some(f => f.value === Feature.TABLE_OF_CONTENTS.value),
|
|
326
|
+
features.some(f => f.value === Feature.INDEX.value),
|
|
327
|
+
features.some(f => f.value === Feature.STRUCTURAL_NAVIGATION.value),
|
|
328
|
+
features.some(f => f.value === Feature.PAGE_NAVIGATION.value)
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Represents the different types of rich content
|
|
335
|
+
*/
|
|
336
|
+
export enum RichContentType {
|
|
337
|
+
Math = 'math',
|
|
338
|
+
Chemistry = 'chemistry',
|
|
339
|
+
Music = 'music',
|
|
340
|
+
Diagram = 'diagram',
|
|
341
|
+
Chart = 'chart',
|
|
342
|
+
Graph = 'graph',
|
|
343
|
+
Table = 'table',
|
|
344
|
+
Image = 'image'
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Rich content features of the content
|
|
349
|
+
*/
|
|
350
|
+
export class RichContent implements AccessibilityDisplayField {
|
|
351
|
+
public readonly id = "rich-content.title";
|
|
352
|
+
public readonly title: string;
|
|
353
|
+
public readonly shouldDisplay: boolean;
|
|
354
|
+
|
|
355
|
+
public readonly noMetadata: boolean;
|
|
356
|
+
public readonly extendedAltTextDescriptions: boolean;
|
|
357
|
+
public readonly mathFormula: boolean;
|
|
358
|
+
public readonly mathFormulaAsMathML: boolean;
|
|
359
|
+
public readonly mathFormulaAsLaTeX: boolean;
|
|
360
|
+
public readonly chemicalFormulaAsMathML: boolean;
|
|
361
|
+
public readonly chemicalFormulaAsLaTeX: boolean;
|
|
362
|
+
public readonly closedCaptions: boolean;
|
|
363
|
+
public readonly openCaptions: boolean;
|
|
364
|
+
public readonly transcript: boolean;
|
|
365
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
366
|
+
|
|
367
|
+
private constructor(
|
|
368
|
+
extendedAltTextDescriptions: boolean = false,
|
|
369
|
+
mathFormula: boolean = false,
|
|
370
|
+
mathFormulaAsMathML: boolean = false,
|
|
371
|
+
mathFormulaAsLaTeX: boolean = false,
|
|
372
|
+
chemicalFormulaAsMathML: boolean = false,
|
|
373
|
+
chemicalFormulaAsLaTeX: boolean = false,
|
|
374
|
+
closedCaptions: boolean = false,
|
|
375
|
+
openCaptions: boolean = false,
|
|
376
|
+
transcript: boolean = false
|
|
377
|
+
) {
|
|
378
|
+
this.extendedAltTextDescriptions = extendedAltTextDescriptions;
|
|
379
|
+
this.mathFormula = mathFormula;
|
|
380
|
+
this.mathFormulaAsMathML = mathFormulaAsMathML;
|
|
381
|
+
this.mathFormulaAsLaTeX = mathFormulaAsLaTeX;
|
|
382
|
+
this.chemicalFormulaAsMathML = chemicalFormulaAsMathML;
|
|
383
|
+
this.chemicalFormulaAsLaTeX = chemicalFormulaAsLaTeX;
|
|
384
|
+
this.closedCaptions = closedCaptions;
|
|
385
|
+
this.openCaptions = openCaptions;
|
|
386
|
+
this.transcript = transcript;
|
|
387
|
+
this.noMetadata = !extendedAltTextDescriptions && !mathFormula && !mathFormulaAsMathML &&
|
|
388
|
+
!mathFormulaAsLaTeX && !chemicalFormulaAsMathML && !chemicalFormulaAsLaTeX &&
|
|
389
|
+
!closedCaptions && !openCaptions && !transcript;
|
|
390
|
+
|
|
391
|
+
this.shouldDisplay = !this.noMetadata;
|
|
392
|
+
|
|
393
|
+
const titleLocale = Localization.getString(this.id);
|
|
394
|
+
this.title = titleLocale.compact;
|
|
395
|
+
|
|
396
|
+
this.statements = [];
|
|
397
|
+
if (extendedAltTextDescriptions) {
|
|
398
|
+
const extendedLocale = Localization.getString("rich-content.extended-descriptions");
|
|
399
|
+
this.statements.push({
|
|
400
|
+
id: "rich-content.extended-descriptions",
|
|
401
|
+
compactString: extendedLocale.compact,
|
|
402
|
+
descriptiveString: extendedLocale.descriptive
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (mathFormula) {
|
|
406
|
+
const mathLocale = Localization.getString("rich-content.accessible-math-described");
|
|
407
|
+
this.statements.push({
|
|
408
|
+
id: "rich-content.accessible-math-described",
|
|
409
|
+
compactString: mathLocale.compact,
|
|
410
|
+
descriptiveString: mathLocale.descriptive
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (mathFormulaAsMathML) {
|
|
414
|
+
const mathMLLocale = Localization.getString("rich-content.math-as-mathml");
|
|
415
|
+
this.statements.push({
|
|
416
|
+
id: "rich-content.math-as-mathml",
|
|
417
|
+
compactString: mathMLLocale.compact,
|
|
418
|
+
descriptiveString: mathMLLocale.descriptive
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
if (mathFormulaAsLaTeX) {
|
|
422
|
+
const latexLocale = Localization.getString("rich-content.accessible-math-as-latex");
|
|
423
|
+
this.statements.push({
|
|
424
|
+
id: "rich-content.accessible-math-as-latex",
|
|
425
|
+
compactString: latexLocale.compact,
|
|
426
|
+
descriptiveString: latexLocale.descriptive
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
if (chemicalFormulaAsMathML) {
|
|
430
|
+
const chemMLLocale = Localization.getString("rich-content.accessible-chemistry-as-mathml");
|
|
431
|
+
this.statements.push({
|
|
432
|
+
id: "rich-content.accessible-chemistry-as-mathml",
|
|
433
|
+
compactString: chemMLLocale.compact,
|
|
434
|
+
descriptiveString: chemMLLocale.descriptive
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (chemicalFormulaAsLaTeX) {
|
|
438
|
+
const chemLatexLocale = Localization.getString("rich-content.accessible-chemistry-as-latex");
|
|
439
|
+
this.statements.push({
|
|
440
|
+
id: "rich-content.accessible-chemistry-as-latex",
|
|
441
|
+
compactString: chemLatexLocale.compact,
|
|
442
|
+
descriptiveString: chemLatexLocale.descriptive
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
if (closedCaptions) {
|
|
446
|
+
const ccLocale = Localization.getString("rich-content.closed-captions");
|
|
447
|
+
this.statements.push({
|
|
448
|
+
id: "rich-content.closed-captions",
|
|
449
|
+
compactString: ccLocale.compact,
|
|
450
|
+
descriptiveString: ccLocale.descriptive
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (openCaptions) {
|
|
454
|
+
const ocLocale = Localization.getString("rich-content.open-captions");
|
|
455
|
+
this.statements.push({
|
|
456
|
+
id: "rich-content.open-captions",
|
|
457
|
+
compactString: ocLocale.compact,
|
|
458
|
+
descriptiveString: ocLocale.descriptive
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
if (transcript) {
|
|
462
|
+
const transcriptLocale = Localization.getString("rich-content.transcript");
|
|
463
|
+
this.statements.push({
|
|
464
|
+
id: "rich-content.transcript",
|
|
465
|
+
compactString: transcriptLocale.compact,
|
|
466
|
+
descriptiveString: transcriptLocale.descriptive
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (this.statements.length === 0) {
|
|
471
|
+
const unknownLocale = Localization.getString("rich-content.unknown");
|
|
472
|
+
this.statements.push({
|
|
473
|
+
id: "rich-content.unknown",
|
|
474
|
+
compactString: unknownLocale.compact,
|
|
475
|
+
descriptiveString: unknownLocale.descriptive
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
public static fromPublication(publication: Publication): RichContent {
|
|
481
|
+
const a11y = publication.metadata.accessibility ?? new Accessibility();
|
|
482
|
+
const features = a11y.feature ?? [];
|
|
483
|
+
|
|
484
|
+
return new RichContent(
|
|
485
|
+
features.some(f => f.value === Feature.LONG_DESCRIPTION.value),
|
|
486
|
+
features.some(f => f.value === Feature.DESCRIBED_MATH.value),
|
|
487
|
+
features.some(f => f.value === Feature.MATH_ML.value),
|
|
488
|
+
features.some(f => f.value === Feature.LATEX.value),
|
|
489
|
+
features.some(f => f.value === Feature.MATH_ML_CHEMISTRY.value),
|
|
490
|
+
features.some(f => f.value === Feature.LATEX_CHEMISTRY.value),
|
|
491
|
+
features.some(f => f.value === Feature.CLOSED_CAPTIONS.value),
|
|
492
|
+
features.some(f => f.value === Feature.OPEN_CAPTIONS.value),
|
|
493
|
+
features.some(f => f.value === Feature.TRANSCRIPT.value)
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Represents additional accessibility information
|
|
500
|
+
*/
|
|
501
|
+
export class AdditionalInformation implements AccessibilityDisplayField {
|
|
502
|
+
public readonly id = "additional-accessibility-information.title";
|
|
503
|
+
public readonly title: string;
|
|
504
|
+
public readonly shouldDisplay: boolean;
|
|
505
|
+
|
|
506
|
+
public readonly noMetadata: boolean;
|
|
507
|
+
public readonly pageBreakMarkers: boolean;
|
|
508
|
+
public readonly aria: boolean;
|
|
509
|
+
public readonly audioDescriptions: boolean;
|
|
510
|
+
public readonly braille: boolean;
|
|
511
|
+
public readonly rubyAnnotations: boolean;
|
|
512
|
+
public readonly fullRubyAnnotations: boolean;
|
|
513
|
+
public readonly highAudioContrast: boolean;
|
|
514
|
+
public readonly highDisplayContrast: boolean;
|
|
515
|
+
public readonly largePrint: boolean;
|
|
516
|
+
public readonly signLanguage: boolean;
|
|
517
|
+
public readonly tactileGraphics: boolean;
|
|
518
|
+
public readonly tactileObjects: boolean;
|
|
519
|
+
public readonly textToSpeechHinting: boolean;
|
|
520
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
521
|
+
|
|
522
|
+
private constructor(
|
|
523
|
+
pageBreakMarkers: boolean = false,
|
|
524
|
+
aria: boolean = false,
|
|
525
|
+
audioDescriptions: boolean = false,
|
|
526
|
+
braille: boolean = false,
|
|
527
|
+
rubyAnnotations: boolean = false,
|
|
528
|
+
fullRubyAnnotations: boolean = false,
|
|
529
|
+
highAudioContrast: boolean = false,
|
|
530
|
+
highDisplayContrast: boolean = false,
|
|
531
|
+
largePrint: boolean = false,
|
|
532
|
+
signLanguage: boolean = false,
|
|
533
|
+
tactileGraphics: boolean = false,
|
|
534
|
+
tactileObjects: boolean = false,
|
|
535
|
+
textToSpeechHinting: boolean = false
|
|
536
|
+
) {
|
|
537
|
+
this.pageBreakMarkers = pageBreakMarkers;
|
|
538
|
+
this.aria = aria;
|
|
539
|
+
this.audioDescriptions = audioDescriptions;
|
|
540
|
+
this.braille = braille;
|
|
541
|
+
this.rubyAnnotations = rubyAnnotations;
|
|
542
|
+
this.fullRubyAnnotations = fullRubyAnnotations;
|
|
543
|
+
this.highAudioContrast = highAudioContrast;
|
|
544
|
+
this.highDisplayContrast = highDisplayContrast;
|
|
545
|
+
this.largePrint = largePrint;
|
|
546
|
+
this.signLanguage = signLanguage;
|
|
547
|
+
this.tactileGraphics = tactileGraphics;
|
|
548
|
+
this.tactileObjects = tactileObjects;
|
|
549
|
+
this.textToSpeechHinting = textToSpeechHinting;
|
|
550
|
+
this.noMetadata = !pageBreakMarkers && !aria && !audioDescriptions &&
|
|
551
|
+
!braille && !rubyAnnotations && !fullRubyAnnotations &&
|
|
552
|
+
!highAudioContrast && !highDisplayContrast && !largePrint &&
|
|
553
|
+
!signLanguage && !tactileGraphics && !tactileObjects && !textToSpeechHinting;
|
|
554
|
+
|
|
555
|
+
this.shouldDisplay = !this.noMetadata;
|
|
556
|
+
|
|
557
|
+
const titleLocale = Localization.getString(this.id);
|
|
558
|
+
this.title = titleLocale.compact;
|
|
559
|
+
|
|
560
|
+
this.statements = [];
|
|
561
|
+
if (pageBreakMarkers) {
|
|
562
|
+
const pageBreaksLocale = Localization.getString("additional-accessibility-information.page-breaks");
|
|
563
|
+
this.statements.push({
|
|
564
|
+
id: "additional-accessibility-information.page-breaks",
|
|
565
|
+
compactString: pageBreaksLocale.compact,
|
|
566
|
+
descriptiveString: pageBreaksLocale.descriptive
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
if (aria) {
|
|
570
|
+
const ariaLocale = Localization.getString("additional-accessibility-information.aria");
|
|
571
|
+
this.statements.push({
|
|
572
|
+
id: "additional-accessibility-information.aria",
|
|
573
|
+
compactString: ariaLocale.compact,
|
|
574
|
+
descriptiveString: ariaLocale.descriptive
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
if (audioDescriptions) {
|
|
578
|
+
const audioDescLocale = Localization.getString("additional-accessibility-information.audio-descriptions");
|
|
579
|
+
this.statements.push({
|
|
580
|
+
id: "additional-accessibility-information.audio-descriptions",
|
|
581
|
+
compactString: audioDescLocale.compact,
|
|
582
|
+
descriptiveString: audioDescLocale.descriptive
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
if (braille) {
|
|
586
|
+
const brailleLocale = Localization.getString("additional-accessibility-information.braille");
|
|
587
|
+
this.statements.push({
|
|
588
|
+
id: "additional-accessibility-information.braille",
|
|
589
|
+
compactString: brailleLocale.compact,
|
|
590
|
+
descriptiveString: brailleLocale.descriptive
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
if (rubyAnnotations) {
|
|
594
|
+
const rubyLocale = Localization.getString("additional-accessibility-information.ruby-annotations");
|
|
595
|
+
this.statements.push({
|
|
596
|
+
id: "additional-accessibility-information.ruby-annotations",
|
|
597
|
+
compactString: rubyLocale.compact,
|
|
598
|
+
descriptiveString: rubyLocale.descriptive
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
if (fullRubyAnnotations) {
|
|
602
|
+
const fullRubyLocale = Localization.getString("additional-accessibility-information.full-ruby-annotations");
|
|
603
|
+
this.statements.push({
|
|
604
|
+
id: "additional-accessibility-information.full-ruby-annotations",
|
|
605
|
+
compactString: fullRubyLocale.compact,
|
|
606
|
+
descriptiveString: fullRubyLocale.descriptive
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
if (highAudioContrast) {
|
|
610
|
+
const audioContrastLocale = Localization.getString("additional-accessibility-information.high-contrast-between-foreground-and-background-audio");
|
|
611
|
+
this.statements.push({
|
|
612
|
+
id: "additional-accessibility-information.high-contrast-between-foreground-and-background-audio",
|
|
613
|
+
compactString: audioContrastLocale.compact,
|
|
614
|
+
descriptiveString: audioContrastLocale.descriptive
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
if (highDisplayContrast) {
|
|
618
|
+
const displayContrastLocale = Localization.getString("additional-accessibility-information.high-contrast-between-text-and-background");
|
|
619
|
+
this.statements.push({
|
|
620
|
+
id: "additional-accessibility-information.high-contrast-between-text-and-background",
|
|
621
|
+
compactString: displayContrastLocale.compact,
|
|
622
|
+
descriptiveString: displayContrastLocale.descriptive
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
if (largePrint) {
|
|
626
|
+
const largePrintLocale = Localization.getString("additional-accessibility-information.large-print");
|
|
627
|
+
this.statements.push({
|
|
628
|
+
id: "additional-accessibility-information.large-print",
|
|
629
|
+
compactString: largePrintLocale.compact,
|
|
630
|
+
descriptiveString: largePrintLocale.descriptive
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
if (signLanguage) {
|
|
634
|
+
const signLanguageLocale = Localization.getString("additional-accessibility-information.sign-language");
|
|
635
|
+
this.statements.push({
|
|
636
|
+
id: "additional-accessibility-information.sign-language",
|
|
637
|
+
compactString: signLanguageLocale.compact,
|
|
638
|
+
descriptiveString: signLanguageLocale.descriptive
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
if (tactileGraphics) {
|
|
642
|
+
const tactileGraphicsLocale = Localization.getString("additional-accessibility-information.tactile-graphics");
|
|
643
|
+
this.statements.push({
|
|
644
|
+
id: "additional-accessibility-information.tactile-graphics",
|
|
645
|
+
compactString: tactileGraphicsLocale.compact,
|
|
646
|
+
descriptiveString: tactileGraphicsLocale.descriptive
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
if (tactileObjects) {
|
|
650
|
+
const tactileObjectsLocale = Localization.getString("additional-accessibility-information.tactile-objects");
|
|
651
|
+
this.statements.push({
|
|
652
|
+
id: "additional-accessibility-information.tactile-objects",
|
|
653
|
+
compactString: tactileObjectsLocale.compact,
|
|
654
|
+
descriptiveString: tactileObjectsLocale.descriptive
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
if (textToSpeechHinting) {
|
|
658
|
+
const ttsHintingLocale = Localization.getString("additional-accessibility-information.text-to-speech-hinting");
|
|
659
|
+
this.statements.push({
|
|
660
|
+
id: "additional-accessibility-information.text-to-speech-hinting",
|
|
661
|
+
compactString: ttsHintingLocale.compact,
|
|
662
|
+
descriptiveString: ttsHintingLocale.descriptive
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
public static fromPublication(publication: Publication): AdditionalInformation {
|
|
668
|
+
const a11y = publication.metadata.accessibility ?? new Accessibility();
|
|
669
|
+
const features = a11y.feature ?? [];
|
|
670
|
+
|
|
671
|
+
return new AdditionalInformation(
|
|
672
|
+
features.some(f => f.value === Feature.PAGE_BREAK_MARKERS.value || f.value === Feature.PRINT_PAGE_NUMBERS.value),
|
|
673
|
+
features.some(f => f.value === Feature.ARIA.value),
|
|
674
|
+
features.some(f => f.value === Feature.AUDIO_DESCRIPTION.value),
|
|
675
|
+
features.some(f => f.value === Feature.BRAILLE.value),
|
|
676
|
+
features.some(f => f.value === Feature.RUBY_ANNOTATIONS.value),
|
|
677
|
+
features.some(f => f.value === Feature.FULL_RUBY_ANNOTATIONS.value),
|
|
678
|
+
features.some(f => f.value === Feature.HIGH_CONTRAST_AUDIO.value),
|
|
679
|
+
features.some(f => f.value === Feature.HIGH_CONTRAST_DISPLAY.value),
|
|
680
|
+
features.some(f => f.value === Feature.LARGE_PRINT.value),
|
|
681
|
+
features.some(f => f.value === Feature.SIGN_LANGUAGE.value),
|
|
682
|
+
features.some(f => f.value === Feature.TACTILE_GRAPHIC.value),
|
|
683
|
+
features.some(f => f.value === Feature.TACTILE_OBJECT.value),
|
|
684
|
+
features.some(f => f.value === Feature.TTS_MARKUP.value)
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export enum HazardType {
|
|
690
|
+
yes = 'yes',
|
|
691
|
+
no = 'no',
|
|
692
|
+
unknown = 'unknown',
|
|
693
|
+
noMetadata = 'noMetadata'
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Represents potential hazards in the content
|
|
698
|
+
*/
|
|
699
|
+
export class Hazards implements AccessibilityDisplayField {
|
|
700
|
+
public readonly id = "hazards.title";
|
|
701
|
+
public readonly title: string;
|
|
702
|
+
public readonly shouldDisplay: boolean;
|
|
703
|
+
public readonly noMetadata: boolean;
|
|
704
|
+
public readonly noHazards: boolean;
|
|
705
|
+
public readonly unknown: boolean;
|
|
706
|
+
public readonly flashing: HazardType;
|
|
707
|
+
public readonly motion: HazardType;
|
|
708
|
+
public readonly sound: HazardType;
|
|
709
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
710
|
+
|
|
711
|
+
private constructor(
|
|
712
|
+
flashing: HazardType = HazardType.unknown,
|
|
713
|
+
motion: HazardType = HazardType.unknown,
|
|
714
|
+
sound: HazardType = HazardType.unknown
|
|
715
|
+
) {
|
|
716
|
+
this.flashing = flashing;
|
|
717
|
+
this.motion = motion;
|
|
718
|
+
this.sound = sound;
|
|
719
|
+
|
|
720
|
+
const titleLocale = Localization.getString(this.id);
|
|
721
|
+
this.title = titleLocale.compact;
|
|
722
|
+
|
|
723
|
+
this.noMetadata = flashing === HazardType.noMetadata && motion === HazardType.noMetadata && sound === HazardType.noMetadata;
|
|
724
|
+
this.noHazards = flashing === HazardType.no && motion === HazardType.no && sound === HazardType.no;
|
|
725
|
+
this.unknown = flashing === HazardType.unknown && motion === HazardType.unknown && sound === HazardType.unknown;
|
|
726
|
+
|
|
727
|
+
this.shouldDisplay = !this.noMetadata;
|
|
728
|
+
|
|
729
|
+
this.statements = [];
|
|
730
|
+
if (this.noHazards) {
|
|
731
|
+
const noneLocale = Localization.getString("hazards.none");
|
|
732
|
+
this.statements.push({
|
|
733
|
+
id: "hazards.none",
|
|
734
|
+
compactString: noneLocale.compact,
|
|
735
|
+
descriptiveString: noneLocale.descriptive
|
|
736
|
+
});
|
|
737
|
+
} else if (this.unknown) {
|
|
738
|
+
const unknownLocale = Localization.getString("hazards.unknown");
|
|
739
|
+
this.statements.push({
|
|
740
|
+
id: "hazards.unknown",
|
|
741
|
+
compactString: unknownLocale.compact,
|
|
742
|
+
descriptiveString: unknownLocale.descriptive
|
|
743
|
+
});
|
|
744
|
+
} else if (this.noMetadata) {
|
|
745
|
+
const noMetadataLocale = Localization.getString("hazards.no-metadata");
|
|
746
|
+
this.statements.push({
|
|
747
|
+
id: "hazards.no-metadata",
|
|
748
|
+
compactString: noMetadataLocale.compact,
|
|
749
|
+
descriptiveString: noMetadataLocale.descriptive
|
|
750
|
+
});
|
|
751
|
+
} else {
|
|
752
|
+
if (flashing === HazardType.yes) {
|
|
753
|
+
const flashingLocale = Localization.getString("hazards.flashing");
|
|
754
|
+
this.statements.push({
|
|
755
|
+
id: "hazards.flashing",
|
|
756
|
+
compactString: flashingLocale.compact,
|
|
757
|
+
descriptiveString: flashingLocale.descriptive
|
|
758
|
+
});
|
|
759
|
+
} else if (flashing === HazardType.unknown) {
|
|
760
|
+
const flashingUnknownLocale = Localization.getString("hazards.flashing-unknown");
|
|
761
|
+
this.statements.push({
|
|
762
|
+
id: "hazards.flashing-unknown",
|
|
763
|
+
compactString: flashingUnknownLocale.compact,
|
|
764
|
+
descriptiveString: flashingUnknownLocale.descriptive
|
|
765
|
+
});
|
|
766
|
+
} else if (flashing === HazardType.no) {
|
|
767
|
+
const flashingNoneLocale = Localization.getString("hazards.flashing-none");
|
|
768
|
+
this.statements.push({
|
|
769
|
+
id: "hazards.flashing-none",
|
|
770
|
+
compactString: flashingNoneLocale.compact,
|
|
771
|
+
descriptiveString: flashingNoneLocale.descriptive
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
if (motion === HazardType.yes) {
|
|
775
|
+
const motionLocale = Localization.getString("hazards.motion");
|
|
776
|
+
this.statements.push({
|
|
777
|
+
id: "hazards.motion",
|
|
778
|
+
compactString: motionLocale.compact,
|
|
779
|
+
descriptiveString: motionLocale.descriptive
|
|
780
|
+
});
|
|
781
|
+
} else if (motion === HazardType.unknown) {
|
|
782
|
+
const motionUnknownLocale = Localization.getString("hazards.motion-unknown");
|
|
783
|
+
this.statements.push({
|
|
784
|
+
id: "hazards.motion-unknown",
|
|
785
|
+
compactString: motionUnknownLocale.compact,
|
|
786
|
+
descriptiveString: motionUnknownLocale.descriptive
|
|
787
|
+
});
|
|
788
|
+
} else if (motion === HazardType.no) {
|
|
789
|
+
const motionNoneLocale = Localization.getString("hazards.motion-none");
|
|
790
|
+
this.statements.push({
|
|
791
|
+
id: "hazards.motion-none",
|
|
792
|
+
compactString: motionNoneLocale.compact,
|
|
793
|
+
descriptiveString: motionNoneLocale.descriptive
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
if (sound === HazardType.yes) {
|
|
797
|
+
const soundLocale = Localization.getString("hazards.sound");
|
|
798
|
+
this.statements.push({
|
|
799
|
+
id: "hazards.sound",
|
|
800
|
+
compactString: soundLocale.compact,
|
|
801
|
+
descriptiveString: soundLocale.descriptive
|
|
802
|
+
});
|
|
803
|
+
} else if (sound === HazardType.unknown) {
|
|
804
|
+
const soundUnknownLocale = Localization.getString("hazards.sound-unknown");
|
|
805
|
+
this.statements.push({
|
|
806
|
+
id: "hazards.sound-unknown",
|
|
807
|
+
compactString: soundUnknownLocale.compact,
|
|
808
|
+
descriptiveString: soundUnknownLocale.descriptive
|
|
809
|
+
});
|
|
810
|
+
} else if (sound === HazardType.no) {
|
|
811
|
+
const soundNoneLocale = Localization.getString("hazards.sound-none");
|
|
812
|
+
this.statements.push({
|
|
813
|
+
id: "hazards.sound-none",
|
|
814
|
+
compactString: soundNoneLocale.compact,
|
|
815
|
+
descriptiveString: soundNoneLocale.descriptive
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
public static fromPublication(publication: Publication): Hazards {
|
|
822
|
+
const hazards = publication.metadata.accessibility?.hazard ?? [];
|
|
823
|
+
|
|
824
|
+
let fallback: HazardType;
|
|
825
|
+
if (hazards.some(h => h.value === Hazard.NONE.value)) {
|
|
826
|
+
fallback = HazardType.no;
|
|
827
|
+
} else if (hazards.some(h => h.value === Hazard.UNKNOWN.value)) {
|
|
828
|
+
fallback = HazardType.unknown;
|
|
829
|
+
} else {
|
|
830
|
+
fallback = HazardType.noMetadata;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
let flashing: HazardType;
|
|
834
|
+
if (hazards.some(h => h.value === Hazard.FLASHING.value)) {
|
|
835
|
+
flashing = HazardType.yes;
|
|
836
|
+
} else if (hazards.some(h => h.value === Hazard.NO_FLASHING_HAZARD.value)) {
|
|
837
|
+
flashing = HazardType.no;
|
|
838
|
+
} else if (hazards.some(h => h.value === Hazard.UNKNOWN_FLASHING_HAZARD.value)) {
|
|
839
|
+
flashing = HazardType.unknown;
|
|
840
|
+
} else {
|
|
841
|
+
flashing = fallback;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
let motion: HazardType;
|
|
845
|
+
if (hazards.some(h => h.value === Hazard.MOTION_SIMULATION.value)) {
|
|
846
|
+
motion = HazardType.yes;
|
|
847
|
+
} else if (hazards.some(h => h.value === Hazard.NO_MOTION_SIMULATION_HAZARD.value)) {
|
|
848
|
+
motion = HazardType.no;
|
|
849
|
+
} else if (hazards.some(h => h.value === Hazard.UNKNOWN_MOTION_SIMULATION_HAZARD.value)) {
|
|
850
|
+
motion = HazardType.unknown;
|
|
851
|
+
} else {
|
|
852
|
+
motion = fallback;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
let sound: HazardType;
|
|
856
|
+
if (hazards.some(h => h.value === Hazard.SOUND.value)) {
|
|
857
|
+
sound = HazardType.yes;
|
|
858
|
+
} else if (hazards.some(h => h.value === Hazard.NO_SOUND_HAZARD.value)) {
|
|
859
|
+
sound = HazardType.no;
|
|
860
|
+
} else if (hazards.some(h => h.value === Hazard.UNKNOWN_SOUND_HAZARD.value)) {
|
|
861
|
+
sound = HazardType.unknown;
|
|
862
|
+
} else {
|
|
863
|
+
sound = fallback;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
return new Hazards(flashing, motion, sound);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Represents conformance to accessibility standards
|
|
872
|
+
*/
|
|
873
|
+
export class Conformance implements AccessibilityDisplayField {
|
|
874
|
+
public readonly id = "conformance.title";
|
|
875
|
+
public readonly title: string;
|
|
876
|
+
public readonly shouldDisplay: boolean;
|
|
877
|
+
public readonly profiles: AccessibilityProfile[];
|
|
878
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
879
|
+
|
|
880
|
+
private constructor(profiles: AccessibilityProfile[] = []) {
|
|
881
|
+
this.profiles = profiles;
|
|
882
|
+
|
|
883
|
+
// This should be displayed even if there is no metadata
|
|
884
|
+
this.shouldDisplay = true;
|
|
885
|
+
|
|
886
|
+
const titleLocale = Localization.getString(this.id);
|
|
887
|
+
this.title = titleLocale.compact;
|
|
888
|
+
|
|
889
|
+
this.statements = [];
|
|
890
|
+
if (profiles.length === 0) {
|
|
891
|
+
const noConformanceLocale = Localization.getString("conformance.no");
|
|
892
|
+
this.statements.push({
|
|
893
|
+
id: "conformance.no",
|
|
894
|
+
compactString: noConformanceLocale.compact,
|
|
895
|
+
descriptiveString: noConformanceLocale.descriptive
|
|
896
|
+
});
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
if (profiles.some(profile => profile.isWCAGLevelAAA)) {
|
|
901
|
+
const aaaLocale = Localization.getString("conformance.aaa");
|
|
902
|
+
this.statements.push({
|
|
903
|
+
id: "conformance.aaa",
|
|
904
|
+
compactString: aaaLocale.compact,
|
|
905
|
+
descriptiveString: aaaLocale.descriptive
|
|
906
|
+
});
|
|
907
|
+
} else if (profiles.some(profile => profile.isWCAGLevelAA)) {
|
|
908
|
+
const aaLocale = Localization.getString("conformance.aa");
|
|
909
|
+
this.statements.push({
|
|
910
|
+
id: "conformance.aa",
|
|
911
|
+
compactString: aaLocale.compact,
|
|
912
|
+
descriptiveString: aaLocale.descriptive
|
|
913
|
+
});
|
|
914
|
+
} else if (profiles.some(profile => profile.isWCAGLevelA)) {
|
|
915
|
+
const aLocale = Localization.getString("conformance.a");
|
|
916
|
+
this.statements.push({
|
|
917
|
+
id: "conformance.a",
|
|
918
|
+
compactString: aLocale.compact,
|
|
919
|
+
descriptiveString: aLocale.descriptive
|
|
920
|
+
});
|
|
921
|
+
} else {
|
|
922
|
+
const unknownLocale = Localization.getString("conformance.unknown-standard");
|
|
923
|
+
this.statements.push({
|
|
924
|
+
id: "conformance.unknown-standard",
|
|
925
|
+
compactString: unknownLocale.compact,
|
|
926
|
+
descriptiveString: unknownLocale.descriptive
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
public static fromPublication(publication: Publication): Conformance {
|
|
932
|
+
const profiles = publication.metadata.accessibility?.conformsTo ?? [];
|
|
933
|
+
return new Conformance(profiles);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Represents legal exemptions
|
|
938
|
+
*/
|
|
939
|
+
export class Legal implements AccessibilityDisplayField {
|
|
940
|
+
public readonly id = "legal-considerations.title";
|
|
941
|
+
public readonly title: string;
|
|
942
|
+
public readonly shouldDisplay: boolean;
|
|
943
|
+
public readonly exemption: boolean;
|
|
944
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
945
|
+
|
|
946
|
+
private constructor(
|
|
947
|
+
exemption: boolean = false
|
|
948
|
+
) {
|
|
949
|
+
this.exemption = exemption;
|
|
950
|
+
this.shouldDisplay = this.exemption;
|
|
951
|
+
|
|
952
|
+
const titleLocale = Localization.getString(this.id);
|
|
953
|
+
this.title = titleLocale.compact;
|
|
954
|
+
|
|
955
|
+
this.statements = [];
|
|
956
|
+
if (exemption) {
|
|
957
|
+
const exemptLocale = Localization.getString("legal-considerations.exempt");
|
|
958
|
+
this.statements.push({
|
|
959
|
+
id: "legal-considerations.exempt",
|
|
960
|
+
compactString: exemptLocale.compact,
|
|
961
|
+
descriptiveString: exemptLocale.descriptive
|
|
962
|
+
});
|
|
963
|
+
} else {
|
|
964
|
+
const noMetadataLocale = Localization.getString("legal-considerations.no-metadata");
|
|
965
|
+
this.statements.push({
|
|
966
|
+
id: "legal-considerations.no-metadata",
|
|
967
|
+
compactString: noMetadataLocale.compact,
|
|
968
|
+
descriptiveString: noMetadataLocale.descriptive
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
public static fromPublication(publication: Publication): Legal {
|
|
974
|
+
const exemptions = publication.metadata.accessibility?.exemption ?? [];
|
|
975
|
+
const hasExemption = exemptions.length > 0;
|
|
976
|
+
return new Legal(hasExemption);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Represents the accessibility summary
|
|
982
|
+
*/
|
|
983
|
+
export class AccessibilitySummary implements AccessibilityDisplayField {
|
|
984
|
+
public readonly id = "accessibility-summary.title";
|
|
985
|
+
public readonly title: string;
|
|
986
|
+
public readonly shouldDisplay: boolean;
|
|
987
|
+
|
|
988
|
+
public readonly statements: AccessibilityDisplayStatement[];
|
|
989
|
+
|
|
990
|
+
private constructor(publication: Publication) {
|
|
991
|
+
this.shouldDisplay = true;
|
|
992
|
+
|
|
993
|
+
const titleLocale = Localization.getString(this.id);
|
|
994
|
+
this.title = titleLocale.compact;
|
|
995
|
+
|
|
996
|
+
const summary = publication.metadata.accessibility?.summary;
|
|
997
|
+
this.statements = [];
|
|
998
|
+
|
|
999
|
+
if (this.shouldDisplay && summary) {
|
|
1000
|
+
this.statements.push({
|
|
1001
|
+
id: "accessibility-summary.summary",
|
|
1002
|
+
compactString: summary,
|
|
1003
|
+
descriptiveString: summary
|
|
1004
|
+
});
|
|
1005
|
+
} else {
|
|
1006
|
+
const locale = Localization.getString("accessibility-summary.no-metadata");
|
|
1007
|
+
this.statements.push({
|
|
1008
|
+
id: "accessibility-summary.no-metadata",
|
|
1009
|
+
compactString: locale.compact,
|
|
1010
|
+
descriptiveString: locale.descriptive
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
public static fromPublication(publication: Publication): AccessibilitySummary {
|
|
1016
|
+
return new AccessibilitySummary(publication);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Main accessibility metadata display guide
|
|
1022
|
+
*/
|
|
1023
|
+
export class AccessibilityMetadataDisplayGuide {
|
|
1024
|
+
public readonly waysOfReading: WaysOfReading;
|
|
1025
|
+
public readonly navigation: Navigation;
|
|
1026
|
+
public readonly richContent: RichContent;
|
|
1027
|
+
public readonly additionalInformation: AdditionalInformation;
|
|
1028
|
+
public readonly hazards: Hazards;
|
|
1029
|
+
public readonly conformance: Conformance;
|
|
1030
|
+
public readonly legal: Legal;
|
|
1031
|
+
public readonly accessibilitySummary: AccessibilitySummary;
|
|
1032
|
+
public readonly fields: AccessibilityDisplayField[];
|
|
1033
|
+
|
|
1034
|
+
constructor(publication: Publication) {
|
|
1035
|
+
this.waysOfReading = WaysOfReading.fromPublication(publication);
|
|
1036
|
+
this.navigation = Navigation.fromPublication(publication);
|
|
1037
|
+
this.richContent = RichContent.fromPublication(publication);
|
|
1038
|
+
this.additionalInformation = AdditionalInformation.fromPublication(publication);
|
|
1039
|
+
this.hazards = Hazards.fromPublication(publication);
|
|
1040
|
+
this.conformance = Conformance.fromPublication(publication);
|
|
1041
|
+
this.legal = Legal.fromPublication(publication);
|
|
1042
|
+
this.accessibilitySummary = AccessibilitySummary.fromPublication(publication);
|
|
1043
|
+
|
|
1044
|
+
this.fields = [
|
|
1045
|
+
this.waysOfReading,
|
|
1046
|
+
this.navigation,
|
|
1047
|
+
this.richContent,
|
|
1048
|
+
this.additionalInformation,
|
|
1049
|
+
this.hazards,
|
|
1050
|
+
this.conformance,
|
|
1051
|
+
this.legal,
|
|
1052
|
+
this.accessibilitySummary
|
|
1053
|
+
];
|
|
1054
|
+
}
|
|
1055
|
+
}
|