@regulaforensics/vp-frontend-document-components 7.5.1964-rc → 7.5.1965-nightly
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 +44 -16
- package/dist/index.d.ts +42 -18
- package/dist/main.iife.js +24 -50
- package/dist/main.js +12088 -15375
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -268,6 +268,7 @@ After adding `DocumentReaderService` to the global variable, you can change the
|
|
|
268
268
|
| **scenario** | Recognition scenario. | string | 'MrzAndLocate' | 'MrzAndLocate', 'MrzOrLocate', 'Mrz', 'Locate' |
|
|
269
269
|
| **multipageProcessing** | Whether to enable multi-page document processing mode. | boolean | `true` | `true`, `false` |
|
|
270
270
|
| **timeout** | Recognition timeout in milliseconds. After this time process will be finished. | number | 2000 | numbers > 0 |
|
|
271
|
+
| **timeoutFromFirstDetect** | Start the countdown from the moment the document is detected. | number | 5000 | numbers > 0 |
|
|
271
272
|
| **resultTypeOutput** | Types of results to return in response. [] - all available types. | number[] | [] | `1` - DocumentImageResult, `3` - TextDataResult, `5` - DocBarCodeInfo, `6` - GraphicsResult, `8` - DocumentTypesCandidatesResult, `9` - ChosenDocumentTypeResult, `20` - AuthenticityResult, `15` - LexicalAnalysisResult, `17` - TextDataResult, `18` - TextDataResult, `19` - GraphicsResult, `30` - ImageQualityResult, `33` - StatusResult, `36` - TextResult, `37` - ImagesResult, `85` - DocumentPositionResult, `102` - TextDataResult, `103` - GraphicsResult, `50` - LicenseResult, `49` - EncryptedRCLResult |
|
|
272
273
|
| **returnPackageForReprocess** | When enabled, returns the package for reprocessing on the backend. | boolean | `false` | `true`, `false` |
|
|
273
274
|
| **imageQa** | When enabled, image quality checks status affects document optical and overall status. | | | |
|
|
@@ -277,7 +278,6 @@ After adding `DocumentReaderService` to the global variable, you can change the
|
|
|
277
278
|
| **glaresCheckParams** | Settings for glare check. | | | |
|
|
278
279
|
| **imageOutputMaxHeight** | This parameter allows setting maximum height in pixels of output images and thus reducing image size to desired. Does not change the aspect ratio. Changes disabled if equals to 0. | number | 0 | numbers > 0 |
|
|
279
280
|
| **imageOutputMaxWidth** | This parameter allows setting maximum width in pixels of output images and thus reducing image size to desired. Does not change the aspect ratio. Changes disabled if equals to 0. | number | 0 | numbers > 0 |
|
|
280
|
-
| **fieldTypesFilter** | List of text field types to extract. If empty, all text fields from template will be extracted. Narrowing the list can shorten processing time. | number[] | [] | |
|
|
281
281
|
| **dateFormat** | This option allows you to set dates format so that solution will return dates in this format. For example, if you supply 'MM/dd/yyyy', and document have printed date '09 JUL 2020' for the date os issue, you will get '07/09/2020' as a result. By default it is set to system locale default (where the service is running). | string | | 'MM/dd/yyyy' |
|
|
282
282
|
| **measureSystem** | This option allows you to set the system of measurement used for converting original values in document to output result values. Metric by default. | number | 0 | `0` - Metric, `1` - Imperial |
|
|
283
283
|
| **imageDpiOutMax** | This parameter controls maximum resolution in dpi of output images. Resolution will remain original in case 0 is supplied. By default is set to return images in response with resolution not greater than 300 dpi for all scenarios except FullAuth. In FullAuth scenario this limit is 1000 dpi by default. | number | | numbers > 0 |
|
|
@@ -425,6 +425,7 @@ Available fields of `event.detail.data` object:
|
|
|
425
425
|
| `NO_CAMERA` | There is no camera available |
|
|
426
426
|
| `INCORRECT_CAMERA_ID` | Camera with this ID was not found |
|
|
427
427
|
| `CONNECTION_ERROR` | Connection errors |
|
|
428
|
+
| `BAD_CONFIGURATION` | Incompatible component settings are installed |
|
|
428
429
|
|
|
429
430
|
#### Remote action data
|
|
430
431
|
|
|
@@ -1016,10 +1017,11 @@ See all component's settings and attributes in the following table.
|
|
|
1016
1017
|
| **multipleFileInput** | **multiple** | Whether to allow uploading more than one file via the file system. Can be set to `true` only if `startScreen` is `true`. | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1017
1018
|
| **cameraId** | **camera-id** | Ability to select a camera. You can get the device ID using [navigator.mediaDevices.enumerateDevices()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices). | string | `undefined` | `camera id string value` | `document-reader`, `camera-snapshot` |
|
|
1018
1019
|
| **devLicense** | **license** | To use the component on test environments, set the base64 license value to the `license` attribute. | string | `undefined` | `base64 license value` | `document-reader` |
|
|
1019
|
-
| **regulaLogo** | **copyright** | Show Regula copyright footer.
|
|
1020
|
+
| **regulaLogo** | **copyright** | Show Regula copyright footer. (deprecated, use copyright instead) | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1020
1021
|
| **changeCameraButton** | **change-camera** | Show the camera switch button. | boolean | `false` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1021
1022
|
| **closeButton** | **close-button** | Show the close button. | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1022
1023
|
| **captureButton** | **capture-button** | Show the capture button. | boolean | `true` | `true`, `false` | `document-reader` |
|
|
1024
|
+
| **copyright** | | Show Regula copyright footer. | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1023
1025
|
| **skipButton** | | Show the skip button for the second page. | boolean | `true` | `true`, `false` | `document-reader` |
|
|
1024
1026
|
| **captureMode** | | Sets the capture mode. Mode `auto` - recognition starts immediately after the camera starts working. Mode `captureFrame` - recognition of the frame received after pressing the capture button. Mode `captureVideo` - recognition begins after pressing the button, pressing the button again will send the received frame for processing. | string | `auto` | `auto`, `captureVideo`, `captureFrame` | `document-reader` |
|
|
1025
1027
|
| **resolution** | | Sets the resolution of the video stream from the camera. | object | `{ width: 1920, height: 1080 }` | `{ width: number, height: number }` | `document-reader`, `camera-snapshot` |
|
|
@@ -1045,7 +1047,7 @@ See all component's settings and attributes in the following table.
|
|
|
1045
1047
|
| **cameraFrame** | | Show the capture frame. | boolean | `true` | `true`, `false` | `document-reader` |
|
|
1046
1048
|
| **captureButtonDelay** | | Show the capture button after delay. | number | `undefined` | `any number` | `document-reader` |
|
|
1047
1049
|
| **nonce** | | Sets the unique nonce value to maintain the CSP policy. | string | `undefined` | `unique nonce value` | `document-reader`, `camera-snapshot` |
|
|
1048
|
-
| **videoRecord** | | Sets the ability to record a video of the document scanning process. If set to true it records the entire process. You can also set the recording delay and recording duration. The video will be available in the component response. | boolean or object | `undefined` |
|
|
1050
|
+
| **videoRecord** | | Sets the ability to record a video of the document scanning process. If set to true it records the entire process. You can also set the recording delay and recording duration. The video will be available in the component response. | boolean or object | `undefined` | `true`, `false`, `{ delay: number, duration: number, bitrate: number }` | `document-reader` |
|
|
1049
1051
|
| **videoCaptureMotionControl** | | Enables device shaking control. | boolean | `false` | `true`, `false` | `document-reader` |
|
|
1050
1052
|
| **fromCameraButton** | | Show the camera button. | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
1051
1053
|
| **uploadFileButton** | | Show the files button. | boolean | `true` | `true`, `false` | `document-reader`, `camera-snapshot` |
|
|
@@ -1061,6 +1063,7 @@ You can send the results to the backend for further processing:
|
|
|
1061
1063
|
```javascript
|
|
1062
1064
|
window.RegulaDocumentSDK.recognizerProcessParam = {
|
|
1063
1065
|
processParam: {
|
|
1066
|
+
scenario: InternalScenarios.MrzAndLocate,
|
|
1064
1067
|
backendProcessing: {
|
|
1065
1068
|
serviceURL: 'YOUR_SERVICE_URL',
|
|
1066
1069
|
httpHeaders: { // you can set http headers if necessary
|
|
@@ -1090,11 +1093,19 @@ For cases when user's main device lacks camera or does not succeed to scan with
|
|
|
1090
1093
|
you have an option to delegate scanning to another available device (i.e. phone).
|
|
1091
1094
|
|
|
1092
1095
|
#### 1. "From other phone" action may be configured on the start screen:
|
|
1093
|
-
-
|
|
1094
|
-
- add 'delegateURL' and 'tag':
|
|
1096
|
+
- add 'delegateProcessing' and 'tag':
|
|
1095
1097
|
```javascript
|
|
1096
1098
|
processor.recognizerProcessParam = {
|
|
1097
|
-
|
|
1099
|
+
processParam: {
|
|
1100
|
+
scenario: InternalScenarios.MrzAndLocate,
|
|
1101
|
+
},
|
|
1102
|
+
delegateProcessing: {
|
|
1103
|
+
delegateURL: 'https://your-page.com?tag={tag}', // the page which will be used by other device
|
|
1104
|
+
serviceURL: 'https://my-service.com', // your backend service
|
|
1105
|
+
httpHeaders: { // http headers if needed
|
|
1106
|
+
header: 'value'
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1098
1109
|
tag: 123 // your session id, will be added to delegateURL in place of {tag} substring
|
|
1099
1110
|
}
|
|
1100
1111
|
```
|
|
@@ -1107,22 +1118,35 @@ you have an option to delegate scanning to another available device (i.e. phone)
|
|
|
1107
1118
|
|
|
1108
1119
|
#### 2. Configure Delegate page component on delegateURL:
|
|
1109
1120
|
- configure [backend reprocessing](#backend-reprocessing)
|
|
1121
|
+
- backendProcessing setting for the device and delegateProcessing setting for the main page must match
|
|
1122
|
+
- set transaction tag
|
|
1123
|
+
```javascript
|
|
1124
|
+
processor.recognizerProcessParam = {
|
|
1125
|
+
tag: new URL(window.location.href).searchParams.get('tag') // assume session Id tag was added to URL params
|
|
1126
|
+
}
|
|
1127
|
+
```
|
|
1110
1128
|
- use the same tag as on the main page
|
|
1111
1129
|
```javascript
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
element.settings = {
|
|
1117
|
-
startScreen: false, // From camera recognition is expected
|
|
1118
|
-
}
|
|
1130
|
+
element.settings = {
|
|
1131
|
+
startScreen: false, // From camera recognition is expected
|
|
1132
|
+
mobileDelegate: true
|
|
1133
|
+
}
|
|
1119
1134
|
```
|
|
1120
1135
|
- use finalizePackage() to send the data for further reprocessing
|
|
1121
1136
|
|
|
1122
|
-
|
|
1123
1137
|
### Appearance Customization
|
|
1124
1138
|
|
|
1125
|
-
####
|
|
1139
|
+
#### CSS part
|
|
1140
|
+
|
|
1141
|
+
Using ::part CSS pseudo-elements, you can set your own styles for component elements. Select the element you need in the developer console and use its part name to customize it.
|
|
1142
|
+
|
|
1143
|
+
```css
|
|
1144
|
+
document-reader::part(container) {
|
|
1145
|
+
background: red;
|
|
1146
|
+
}
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
#### CSS variables
|
|
1126
1150
|
|
|
1127
1151
|
Using CSS variables, you can change the font and the main colors of the components. See the table for the details.
|
|
1128
1152
|
|
|
@@ -1218,7 +1242,7 @@ See the following table with localized labels, used in the components.
|
|
|
1218
1242
|
| **keepDeviceStill** | Hold the device still | `document-reader` |
|
|
1219
1243
|
| **positionDocumentCenter** | Position the document in the center | `camera-snapshot` |
|
|
1220
1244
|
| **uploadPhoto** | Upload a photo | `camera-snapshot` |
|
|
1221
|
-
| **
|
|
1245
|
+
| **switchToMobile** | Switch to mobile | `document-reader` |
|
|
1222
1246
|
| **openPhoneCamera** | Open the camera on your mobile device, scan the QR code, and follow the link | `document-reader` |
|
|
1223
1247
|
| **pleaseWait** | Please wait... | `document-reader` |
|
|
1224
1248
|
| **mobileDevice** | Mobile device | `document-reader` |
|
|
@@ -1233,6 +1257,8 @@ See the following table with localized labels, used in the components.
|
|
|
1233
1257
|
| **fromFilesDesktop** | Pick a document from the files and upload it | `document-reader` |
|
|
1234
1258
|
| **fromMobileDesktop** | Use your mobile camera to capture a document | `document-reader` |
|
|
1235
1259
|
| **fromGalleryMobile** | Pick a document from the gallery and upload it | `document-reader` |
|
|
1260
|
+
| **returnToComputer** | Return to the computer | `document-reader` |
|
|
1261
|
+
| **documentCaptured** | Your document has been captured | `document-reader` |
|
|
1236
1262
|
|
|
1237
1263
|
## Document Reader Processor
|
|
1238
1264
|
|
|
@@ -1586,6 +1612,8 @@ In the given examples, change the `workerPath` parameter value to your custom so
|
|
|
1586
1612
|
|
|
1587
1613
|
**Attention!** The files must be located in the same directory and have the same names as were previously specified.
|
|
1588
1614
|
|
|
1615
|
+
To decrease files size, you can apply compression. On your server, you need to determine which <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding" target="_blank">compression method</a> is used for the files.
|
|
1616
|
+
|
|
1589
1617
|
## Potential Problems
|
|
1590
1618
|
|
|
1591
1619
|
UI components and SDK use the `getUserMedia` method to display the video stream from the camera. This feature is available only in secure contexts (HTTPS).
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ import { DocumentFormat } from '@regulaforensics/document-reader-webclient';
|
|
|
3
3
|
import { GetTransactionsByTagResponse } from '@regulaforensics/document-reader-webclient';
|
|
4
4
|
import { MeasureSystem } from '@regulaforensics/document-reader-webclient';
|
|
5
5
|
import { MRZFormat } from '@regulaforensics/document-reader-webclient';
|
|
6
|
+
import { ProcessResponse } from '@regulaforensics/document-reader-webclient';
|
|
6
7
|
import { Response as Response_2 } from '@regulaforensics/document-reader-webclient';
|
|
7
8
|
import { Result } from '@regulaforensics/document-reader-webclient';
|
|
8
9
|
import { TextFieldType } from '@regulaforensics/document-reader-webclient';
|
|
10
|
+
import { TransactionInfo } from '@regulaforensics/document-reader-webclient';
|
|
9
11
|
|
|
10
12
|
export declare interface BaseRequest {
|
|
11
13
|
tag?: string;
|
|
@@ -40,6 +42,7 @@ export declare interface CameraSnapshotSettings {
|
|
|
40
42
|
locale?: Locales | string;
|
|
41
43
|
multipleFileInput?: boolean;
|
|
42
44
|
regulaLogo?: boolean;
|
|
45
|
+
copyright?: boolean;
|
|
43
46
|
cameraId?: string;
|
|
44
47
|
changeCameraButton?: boolean;
|
|
45
48
|
closeButton?: boolean;
|
|
@@ -146,8 +149,8 @@ export declare class DocumentReaderProcessor {
|
|
|
146
149
|
isInitialized: boolean;
|
|
147
150
|
videoElement: HTMLVideoElement | null;
|
|
148
151
|
constructor(videoElement?: HTMLVideoElement);
|
|
149
|
-
get recognizeListener(): ((data: Response_2) => void) | null;
|
|
150
|
-
set recognizeListener(listener: ((data: Response_2) => void) | null);
|
|
152
|
+
get recognizeListener(): ((data: Response_2 | ProcessRejectResponse) => void) | null;
|
|
153
|
+
set recognizeListener(listener: ((data: Response_2 | ProcessRejectResponse) => void) | null);
|
|
151
154
|
get streamParam(): Partial<StreamParams>;
|
|
152
155
|
set streamParam(params: Partial<StreamParams>);
|
|
153
156
|
get recognizerProcessParam(): ProcessingRequest;
|
|
@@ -221,9 +224,7 @@ export declare interface DocumentReaderProcessParam {
|
|
|
221
224
|
};
|
|
222
225
|
}
|
|
223
226
|
|
|
224
|
-
export declare type DocumentReaderResponseType = Response_2
|
|
225
|
-
TransactionInfo?: TransactionInfo;
|
|
226
|
-
};
|
|
227
|
+
export declare type DocumentReaderResponseType = Response_2;
|
|
227
228
|
|
|
228
229
|
export declare class DocumentReaderService {
|
|
229
230
|
private _worker;
|
|
@@ -231,11 +232,12 @@ export declare class DocumentReaderService {
|
|
|
231
232
|
private _initializeListener;
|
|
232
233
|
private _processingListener;
|
|
233
234
|
private _queueService;
|
|
235
|
+
private _initProcess;
|
|
236
|
+
onFinalize: TOnFinalize | null;
|
|
234
237
|
isAutoPrepare: boolean;
|
|
235
238
|
isPrepared: boolean;
|
|
236
239
|
isInitialized: boolean;
|
|
237
240
|
isProcessing: boolean;
|
|
238
|
-
_initProcess: Promise<License> | null;
|
|
239
241
|
initData: License | null;
|
|
240
242
|
recognizerProcessParam: ProcessingRequest;
|
|
241
243
|
imageProcessParam: ImageProcessingRequest;
|
|
@@ -259,13 +261,14 @@ export declare class DocumentReaderService {
|
|
|
259
261
|
doInitialize(initData?: {
|
|
260
262
|
license: string | undefined;
|
|
261
263
|
}): Promise<License>;
|
|
264
|
+
private doProcess;
|
|
262
265
|
processImageBase64(base64ImagesArray: Array<string>, params: ProcessingRequest): Promise<Response_2>;
|
|
263
266
|
process(imageDataArray: Array<ImageData>, params?: ProcessingRequest): Promise<Response_2>;
|
|
264
267
|
processImage(imageDataArray: Array<ImageData>, params?: ProcessingRequest): Promise<Response_2>;
|
|
265
268
|
startNewPage(): Promise<void>;
|
|
266
269
|
startNewDocument(metadata?: Record<string, any>): Promise<NewTransaction>;
|
|
267
270
|
createBackendTransaction(metadata?: Record<string, any>): Promise<NewTransaction>;
|
|
268
|
-
finalizePackage(): Promise<
|
|
271
|
+
finalizePackage(): Promise<TransactionIdentifier>;
|
|
269
272
|
addDataToPackage(data: Uint8ClampedArray, params: PackageParams): Promise<void>;
|
|
270
273
|
shutdown(): void;
|
|
271
274
|
}
|
|
@@ -383,7 +386,8 @@ export declare enum ErrorTypes {
|
|
|
383
386
|
INCORRECT_CAMERA_ID = "INCORRECT_CAMERA_ID",
|
|
384
387
|
CONNECTION_ERROR = "CONNECTION_ERROR",
|
|
385
388
|
HTTP_NOT_SUPPORTED = "HTTP_NOT_SUPPORTED",
|
|
386
|
-
INSECURE_PAGE_CONTEXT = "INSECURE_PAGE_CONTEXT"
|
|
389
|
+
INSECURE_PAGE_CONTEXT = "INSECURE_PAGE_CONTEXT",
|
|
390
|
+
BAD_CONFIGURATION = "BAD_CONFIGURATION"
|
|
387
391
|
}
|
|
388
392
|
|
|
389
393
|
export declare enum EventActions {
|
|
@@ -502,13 +506,7 @@ export declare enum MirrorType {
|
|
|
502
506
|
|
|
503
507
|
export declare interface NewTransaction {
|
|
504
508
|
ContainerList: ContainerList;
|
|
505
|
-
TransactionInfo:
|
|
506
|
-
ComputerName: string;
|
|
507
|
-
DateTime: string;
|
|
508
|
-
SystemInfo: string;
|
|
509
|
-
Tag: string;
|
|
510
|
-
TransactionID: string;
|
|
511
|
-
};
|
|
509
|
+
TransactionInfo: TransactionInfo;
|
|
512
510
|
sessionLogFolder: string;
|
|
513
511
|
}
|
|
514
512
|
|
|
@@ -520,13 +518,23 @@ export declare interface PackageParams {
|
|
|
520
518
|
|
|
521
519
|
export declare interface ProcessingRequest extends BaseRequest {
|
|
522
520
|
metadata?: Record<string, any>;
|
|
523
|
-
|
|
521
|
+
delegateProcessing?: {
|
|
522
|
+
serviceURL: string;
|
|
523
|
+
delegateURL: string;
|
|
524
|
+
httpHeaders?: Record<string, string>;
|
|
525
|
+
};
|
|
524
526
|
processParam: DocumentReaderProcessParam;
|
|
525
527
|
imagesList?: Array<DocumentReaderImage>;
|
|
526
528
|
imageInputParam?: ImageInputParamType;
|
|
527
529
|
}
|
|
528
530
|
|
|
529
|
-
declare
|
|
531
|
+
export declare interface ProcessRejectResponse extends ProcessResponse {
|
|
532
|
+
licensing_code: number;
|
|
533
|
+
reject_message: string;
|
|
534
|
+
reject_reason: number;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
declare type RecognizeListener = (data: Response_2 | ProcessRejectResponse) => void;
|
|
530
538
|
|
|
531
539
|
export declare type Resolution = Partial<WidthAndHeight>;
|
|
532
540
|
|
|
@@ -549,6 +557,8 @@ declare type TInitializeListener = ({ isInitialized }: {
|
|
|
549
557
|
isInitialized: boolean;
|
|
550
558
|
}) => void;
|
|
551
559
|
|
|
560
|
+
declare type TOnFinalize = (transaction: TransactionIdentifier) => void;
|
|
561
|
+
|
|
552
562
|
declare type TPrepareListener = ({ isPrepared }: {
|
|
553
563
|
isPrepared: boolean;
|
|
554
564
|
}) => void;
|
|
@@ -562,7 +572,8 @@ export declare interface TransactionEvent {
|
|
|
562
572
|
data: GetTransactionsByTagResponse;
|
|
563
573
|
}
|
|
564
574
|
|
|
565
|
-
export declare interface
|
|
575
|
+
export declare interface TransactionIdentifier {
|
|
576
|
+
metadata?: unknown;
|
|
566
577
|
tag: string;
|
|
567
578
|
transactionId: string;
|
|
568
579
|
}
|
|
@@ -598,6 +609,7 @@ export declare interface VideoData {
|
|
|
598
609
|
export declare interface VideoRecordSettings {
|
|
599
610
|
delay?: number;
|
|
600
611
|
duration?: number;
|
|
612
|
+
bitrate?: number;
|
|
601
613
|
}
|
|
602
614
|
|
|
603
615
|
export declare interface WidthAndHeight {
|
|
@@ -617,3 +629,15 @@ declare global {
|
|
|
617
629
|
RegulaDocumentSDK: DocumentReaderService;
|
|
618
630
|
}
|
|
619
631
|
}
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
declare namespace v3 {
|
|
635
|
+
var DNS: string;
|
|
636
|
+
var URL: string;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
declare namespace v5 {
|
|
641
|
+
var DNS: string;
|
|
642
|
+
var URL: string;
|
|
643
|
+
}
|