react-native-text-reader 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.
package/README.md CHANGED
@@ -12,11 +12,11 @@ npm install react-native-text-reader
12
12
 
13
13
 
14
14
  ```js
15
- import { multiply } from 'react-native-text-reader';
15
+ import { read } from 'react-native-text-reader';
16
16
 
17
17
  // ...
18
18
 
19
- const result = await multiply(3, 7);
19
+ const result = await read('imageUri');
20
20
  ```
21
21
 
22
22
 
@@ -95,5 +95,16 @@ dependencies {
95
95
  //noinspection GradleDynamicVersion
96
96
  implementation "com.facebook.react:react-native:+"
97
97
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
98
+
99
+ // To recognize Latin script
100
+ implementation 'com.google.mlkit:text-recognition:16.0.0'
101
+ // To recognize Chinese script
102
+ implementation 'com.google.mlkit:text-recognition-chinese:16.0.0'
103
+ // To recognize Devanagari script
104
+ implementation 'com.google.mlkit:text-recognition-devanagari:16.0.0'
105
+ // To recognize Japanese script
106
+ implementation 'com.google.mlkit:text-recognition-japanese:16.0.0'
107
+ // To recognize Korean script
108
+ implementation 'com.google.mlkit:text-recognition-korean:16.0.0'
98
109
  }
99
110
 
@@ -5,21 +5,152 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
5
  import com.facebook.react.bridge.ReactMethod
6
6
  import com.facebook.react.bridge.Promise
7
7
 
8
+ import android.graphics.Point
9
+ import android.graphics.Rect
10
+ import android.net.Uri
11
+ import android.graphics.BitmapFactory
12
+ import android.graphics.Bitmap
13
+ import androidx.annotation.NonNull
14
+ import androidx.annotation.Nullable
15
+ import com.facebook.react.bridge.*
16
+ import com.google.android.gms.tasks.OnFailureListener
17
+ import com.google.android.gms.tasks.OnSuccessListener
18
+ import com.google.mlkit.vision.common.InputImage
19
+ import com.google.mlkit.vision.text.Text
20
+ import com.google.mlkit.vision.text.TextRecognition
21
+ import com.google.mlkit.vision.text.TextRecognizer
22
+ import com.google.mlkit.vision.text.TextRecognizerOptionsInterface
23
+ import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
24
+ import com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions
25
+ import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions
26
+ import com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions
27
+ import com.google.mlkit.vision.text.latin.TextRecognizerOptions
28
+ import java.io.IOException
29
+ import java.net.URL
30
+
31
+
8
32
  class TextReaderModule(reactContext: ReactApplicationContext) :
9
33
  ReactContextBaseJavaModule(reactContext) {
34
+ override fun getName(): String {
35
+ return NAME
36
+ }
37
+
38
+ @Throws(IOException::class)
39
+ private fun getInputImage(reactContext: ReactApplicationContext, url: String): InputImage {
40
+ return if (url.contains("http://") || url.contains("https://")) {
41
+ val urlInput = URL(url)
42
+ val image: Bitmap = BitmapFactory.decodeStream(urlInput.openConnection().getInputStream())
43
+ InputImage.fromBitmap(image, 0)
44
+ } else {
45
+ val uri = Uri.parse(url)
46
+ InputImage.fromFilePath(reactContext, uri)
47
+ }
48
+ }
49
+
50
+ private fun rectToMap(rect: Rect): WritableMap {
51
+ return Arguments.createMap().apply {
52
+ putInt("width", rect.width())
53
+ putInt("height", rect.height())
54
+ putInt("top", rect.top)
55
+ putInt("left", rect.left)
56
+ }
57
+ }
58
+
59
+ private fun cornerPointsToMap(points: Array<Point>): WritableArray {
60
+ return Arguments.createArray().apply {
61
+ points.forEach { point ->
62
+ pushMap(Arguments.createMap().apply {
63
+ putInt("x", point.x)
64
+ putInt("y", point.y)
65
+ })
66
+ }
67
+ }
68
+ }
69
+
70
+ private fun langToMap(lang: String): WritableArray {
71
+ return Arguments.createArray().apply {
72
+ pushMap(Arguments.createMap().apply {
73
+ putString("languageCode", lang)
74
+ })
75
+ }
76
+ }
77
+
78
+ private fun lineToMap(line: Text.Line): WritableMap {
79
+ return Arguments.createMap().apply {
80
+ putString("text", line.text)
81
+ line.boundingBox?.let { putMap("frame", rectToMap(it)) }
82
+ line.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
83
+ putArray("recognizedLanguages", langToMap(line.recognizedLanguage))
84
+
85
+ val elementsArray = Arguments.createArray()
86
+ line.elements.forEach { element ->
87
+ elementsArray.pushMap(Arguments.createMap().apply {
88
+ putString("text", element.text)
89
+ element.boundingBox?.let { putMap("frame", rectToMap(it)) }
90
+ element.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
91
+ })
92
+ }
93
+ putArray("elements", elementsArray)
94
+ }
95
+ }
96
+
97
+ private fun blockToMap(block: Text.TextBlock): WritableMap {
98
+ return Arguments.createMap().apply {
99
+ putString("text", block.text)
100
+ block.boundingBox?.let { putMap("frame", rectToMap(it)) }
101
+ block.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
102
+
103
+ val linesArray = Arguments.createArray()
104
+ block.lines.forEach { line ->
105
+ linesArray.pushMap(lineToMap(line))
106
+ }
107
+ putArray("lines", linesArray)
108
+ putArray("recognizedLanguages", langToMap(block.recognizedLanguage))
109
+ }
110
+ }
111
+
112
+ @NonNull
113
+ private fun getScriptTextRecognizerOptions(@Nullable script: String?): TextRecognizerOptionsInterface {
114
+ return when (script) {
115
+ "Chinese" -> ChineseTextRecognizerOptions.Builder().build()
116
+ "Devanagari" -> DevanagariTextRecognizerOptions.Builder().build()
117
+ "Japanese" -> JapaneseTextRecognizerOptions.Builder().build()
118
+ "Korean" -> KoreanTextRecognizerOptions.Builder().build()
119
+ else -> TextRecognizerOptions.DEFAULT_OPTIONS
120
+ }
121
+ }
122
+
123
+ @ReactMethod
124
+ fun read(url: String, script: String, promise: Promise) {
125
+ try {
126
+ val image = getInputImage(reactApplicationContext, url)
127
+ val options = getScriptTextRecognizerOptions(script)
128
+ val recognizer: TextRecognizer = TextRecognition.getClient(options)
129
+
130
+ recognizer.process(image)
131
+ .addOnSuccessListener { visionText ->
132
+ val result = Arguments.createMap()
133
+ result.putString("text", visionText.text)
134
+
135
+ val blocksArray = Arguments.createArray()
136
+ visionText.textBlocks.forEach { block ->
137
+ blocksArray.pushMap(blockToMap(block))
138
+ }
139
+ result.putArray("blocks", blocksArray)
140
+
141
+ promise.resolve(result)
142
+ }
143
+ .addOnFailureListener { e ->
144
+ e.printStackTrace()
145
+ promise.reject("Text recognition failed", e)
146
+ }
147
+ } catch (e: IOException) {
148
+ e.printStackTrace()
149
+ promise.reject("Text recognition failed", e)
150
+ }
151
+ }
10
152
 
11
- override fun getName(): String {
12
- return NAME
13
- }
14
-
15
- // Example method
16
- // See https://reactnative.dev/docs/native-modules-android
17
- @ReactMethod
18
- fun multiply(a: Double, b: Double, promise: Promise) {
19
- promise.resolve(a * b)
20
- }
21
-
22
- companion object {
23
- const val NAME = "TextReader"
24
- }
25
- }
153
+ companion object {
154
+ const val NAME = "TextReader"
155
+ }
156
+ }
package/ios/TextReader.mm CHANGED
@@ -1,10 +1,12 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
 
3
- @interface RCT_EXTERN_MODULE(TextReader, NSObject)
3
+ @interface RCT_EXTERN_MODULE (TextReader, NSObject)
4
4
 
5
- RCT_EXTERN_METHOD(multiply:(float)a withB:(float)b
6
- withResolver:(RCTPromiseResolveBlock)resolve
7
- withRejecter:(RCTPromiseRejectBlock)reject)
5
+ RCT_EXTERN_METHOD(read
6
+ : (NSString *)imgPath withOptions
7
+ : (NSDictionary *)options withResolver
8
+ : (RCTPromiseResolveBlock)resolve withRejecter
9
+ : (RCTPromiseRejectBlock)reject)
8
10
 
9
11
  + (BOOL)requiresMainQueueSetup
10
12
  {
@@ -1,8 +1,56 @@
1
+ import Vision
2
+
3
+ extension String {
4
+ func stripPrefix(_ prefix: String) -> String {
5
+ guard hasPrefix(prefix) else { return self }
6
+ return String(dropFirst(prefix.count))
7
+ }
8
+ }
9
+
1
10
  @objc(TextReader)
2
11
  class TextReader: NSObject {
12
+ @objc static func requiresMainQueueSetup() -> Bool { return true }
13
+ @objc(read:withOptions:withResolver:withRejecter:)
14
+ func read(imgPath: String, options: [String: Float], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
15
+ guard !imgPath.isEmpty else { reject("ERR", "Image path cannot be empty.", nil); return }
16
+
17
+ let formattedImgPath = imgPath.stripPrefix("file://")
18
+ var threshold: Float = 0.0
19
+
20
+ if !(options["visionIgnoreThreshold"]?.isZero ?? true) {
21
+ threshold = options["visionIgnoreThreshold"] ?? 0.0
22
+ }
23
+
24
+ do {
25
+ let imgData = try Data(contentsOf: URL(fileURLWithPath: formattedImgPath))
26
+ let image = UIImage(data: imgData)
3
27
 
4
- @objc(multiply:withB:withResolver:withRejecter:)
5
- func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
6
- resolve(a*b)
28
+ guard let cgImage = image?.cgImage else { return }
29
+
30
+ let requestHandler = VNImageRequestHandler(cgImage: cgImage)
31
+
32
+ let ocrRequest = VNRecognizeTextRequest { (request: VNRequest, error: Error?) in
33
+ self.textReaderHandler(request: request, threshold: threshold, error: error, resolve: resolve, reject: reject)
34
+ }
35
+
36
+ try requestHandler.perform([ocrRequest])
37
+ } catch {
38
+ print(error)
39
+ reject("ERR", error.localizedDescription, nil)
40
+ }
7
41
  }
8
- }
42
+
43
+ func textReaderHandler(request: VNRequest, threshold: Float, error _: Error?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
44
+ guard let observations = request.results as? [VNRecognizedTextObservation] else { reject("ERR", "Failed to read the text.", nil); return }
45
+
46
+ let strings = observations.compactMap { observation -> String? in
47
+ if observation.topCandidates(1).first?.confidence ?? 0 >= threshold {
48
+ return observation.topCandidates(1).first?.string
49
+ } else {
50
+ return nil
51
+ }
52
+ }
53
+
54
+ resolve(strings)
55
+ }
56
+ }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.multiply = multiply;
6
+ exports.default = void 0;
7
7
  var _reactNative = require("react-native");
8
8
  const LINKING_ERROR = `The package 'react-native-text-reader' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
9
9
  ios: "- You have run 'pod install'\n",
@@ -14,7 +14,17 @@ const TextReader = _reactNative.NativeModules.TextReader ? _reactNative.NativeMo
14
14
  throw new Error(LINKING_ERROR);
15
15
  }
16
16
  });
17
- function multiply(a, b) {
18
- return TextReader.multiply(a, b);
17
+ /**
18
+ * Extrae texto de una imagen.
19
+ * @param imagePath - La URI de la imagen de la que se extraerá el texto.
20
+ * @param options - Opciones adicionales.
21
+ * @param options.visionIgnoreThreshold - Umbral de ignoración de la visión.
22
+ * @returns Una promesa que se resuelve con el texto extraído.
23
+ */
24
+ async function read(imagePath, options) {
25
+ return await TextReader.read(imagePath, options || {});
19
26
  }
27
+ var _default = exports.default = {
28
+ read
29
+ };
20
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","TextReader","NativeModules","Proxy","get","Error","multiply","a","b"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,mFAAmF,GACnFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,UAAU,GAAGC,0BAAa,CAACD,UAAU,GACvCC,0BAAa,CAACD,UAAU,GACxB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEE,SAASU,QAAQA,CAACC,CAAS,EAAEC,CAAS,EAAmB;EAC9D,OAAOP,UAAU,CAACK,QAAQ,CAACC,CAAC,EAAEC,CAAC,CAAC;AAClC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","TextReader","NativeModules","Proxy","get","Error","read","imagePath","options","_default","exports"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,mFAAmF,GACnFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,UAAU,GAAGC,0BAAa,CAACD,UAAU,GACvCC,0BAAa,CAACD,UAAU,GACxB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAUL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeU,IAAIA,CACjBC,SAAiB,EACjBC,OAA2B,EACR;EACnB,OAAO,MAAMP,UAAU,CAACK,IAAI,CAACC,SAAS,EAAEC,OAAO,IAAI,CAAC,CAAC,CAAC;AACxD;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAV,OAAA,GAEc;EAAEM;AAAK,CAAC","ignoreList":[]}
@@ -10,7 +10,17 @@ const TextReader = NativeModules.TextReader ? NativeModules.TextReader : new Pro
10
10
  throw new Error(LINKING_ERROR);
11
11
  }
12
12
  });
13
- export function multiply(a, b) {
14
- return TextReader.multiply(a, b);
13
+ /**
14
+ * Extrae texto de una imagen.
15
+ * @param imagePath - La URI de la imagen de la que se extraerá el texto.
16
+ * @param options - Opciones adicionales.
17
+ * @param options.visionIgnoreThreshold - Umbral de ignoración de la visión.
18
+ * @returns Una promesa que se resuelve con el texto extraído.
19
+ */
20
+ async function read(imagePath, options) {
21
+ return await TextReader.read(imagePath, options || {});
15
22
  }
23
+ export default {
24
+ read
25
+ };
16
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","TextReader","Proxy","get","Error","multiply","a","b"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,mFAAmF,GACnFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,UAAU,GAAGN,aAAa,CAACM,UAAU,GACvCN,aAAa,CAACM,UAAU,GACxB,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,SAASQ,QAAQA,CAACC,CAAS,EAAEC,CAAS,EAAmB;EAC9D,OAAON,UAAU,CAACI,QAAQ,CAACC,CAAC,EAAEC,CAAC,CAAC;AAClC","ignoreList":[]}
1
+ {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","TextReader","Proxy","get","Error","read","imagePath","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,mFAAmF,GACnFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,UAAU,GAAGN,aAAa,CAACM,UAAU,GACvCN,aAAa,CAACM,UAAU,GACxB,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAUL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeQ,IAAIA,CACjBC,SAAiB,EACjBC,OAA2B,EACR;EACnB,OAAO,MAAMN,UAAU,CAACI,IAAI,CAACC,SAAS,EAAEC,OAAO,IAAI,CAAC,CAAC,CAAC;AACxD;AAEA,eAAe;EAAEF;AAAK,CAAC","ignoreList":[]}
@@ -1,2 +1,9 @@
1
- export declare function multiply(a: number, b: number): Promise<number>;
1
+ export type TextReaderOptions = {
2
+ visionIgnoreThreshold?: number;
3
+ };
4
+ type TextReaderType = {
5
+ read(imagePath: string, options?: TextReaderOptions): Promise<string[]>;
6
+ };
7
+ declare const _default: TextReaderType;
8
+ export default _default;
2
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACzE,CAAC;wBAgByB,cAAc;AAAzC,wBAA0C"}
@@ -1,2 +1,9 @@
1
- export declare function multiply(a: number, b: number): Promise<number>;
1
+ export type TextReaderOptions = {
2
+ visionIgnoreThreshold?: number;
3
+ };
4
+ type TextReaderType = {
5
+ read(imagePath: string, options?: TextReaderOptions): Promise<string[]>;
6
+ };
7
+ declare const _default: TextReaderType;
8
+ export default _default;
2
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACzE,CAAC;wBAgByB,cAAc;AAAzC,wBAA0C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-text-reader",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "A React Native library for OCR (Optical Character Recognition) using Vision Framework on iOS and Firebase ML Kit on Android.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
package/src/index.tsx CHANGED
@@ -17,6 +17,26 @@ const TextReader = NativeModules.TextReader
17
17
  }
18
18
  );
19
19
 
20
- export function multiply(a: number, b: number): Promise<number> {
21
- return TextReader.multiply(a, b);
20
+ export type TextReaderOptions = {
21
+ visionIgnoreThreshold?: number;
22
+ };
23
+
24
+ type TextReaderType = {
25
+ read(imagePath: string, options?: TextReaderOptions): Promise<string[]>;
26
+ };
27
+
28
+ /**
29
+ * Extrae texto de una imagen.
30
+ * @param imagePath - La URI de la imagen de la que se extraerá el texto.
31
+ * @param options - Opciones adicionales.
32
+ * @param options.visionIgnoreThreshold - Umbral de ignoración de la visión.
33
+ * @returns Una promesa que se resuelve con el texto extraído.
34
+ */
35
+ async function read(
36
+ imagePath: string,
37
+ options?: TextReaderOptions
38
+ ): Promise<string[]> {
39
+ return await TextReader.read(imagePath, options || {});
22
40
  }
41
+
42
+ export default { read } as TextReaderType;