@azure-rest/ai-document-intelligence 1.0.0-alpha.20250130.1 → 1.0.0-alpha.20250203.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/README.md CHANGED
@@ -68,8 +68,9 @@ AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET
68
68
 
69
69
  ### Using a Token Credential
70
70
 
71
- ```ts
71
+ ```ts snippet:ReadmeSampleCreateClient_TokenCredential
72
72
  import DocumentIntelligence from "@azure-rest/ai-document-intelligence";
73
+ import { DefaultAzureCredential } from "@azure/identity";
73
74
 
74
75
  const client = DocumentIntelligence(
75
76
  process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
@@ -79,7 +80,7 @@ const client = DocumentIntelligence(
79
80
 
80
81
  ### Using an API KEY
81
82
 
82
- ```ts
83
+ ```ts snippet:ReadmeSampleCreateClient_APIKey
83
84
  import DocumentIntelligence from "@azure-rest/ai-document-intelligence";
84
85
 
85
86
  const client = DocumentIntelligence(process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"], {
@@ -91,7 +92,15 @@ const client = DocumentIntelligence(process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"
91
92
 
92
93
  ### Analyze prebuilt-layout (urlSource)
93
94
 
94
- ```ts
95
+ ```ts snippet:ReadmeSampleAnalyzePrebuiltLayoutUrlSource
96
+ import DocumentIntelligence from "@azure-rest/ai-document-intelligence";
97
+ import { DefaultAzureCredential } from "@azure/identity";
98
+
99
+ const client = DocumentIntelligence(
100
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
101
+ new DefaultAzureCredential(),
102
+ );
103
+
95
104
  const initialResponse = await client
96
105
  .path("/documentModels/{modelId}:analyze", "prebuilt-layout")
97
106
  .post({
@@ -106,12 +115,23 @@ const initialResponse = await client
106
115
 
107
116
  ### Analyze prebuilt-layout (base64Source)
108
117
 
109
- ```ts
110
- import fs from "fs";
111
- import path from "path";
118
+ ```ts snippet:ReadmeSampleAnalyzePrebuiltLayoutBase64Source
119
+ import DocumentIntelligence, {
120
+ isUnexpected,
121
+ getLongRunningPoller,
122
+ AnalyzeOperationOutput,
123
+ } from "@azure-rest/ai-document-intelligence";
124
+ import { DefaultAzureCredential } from "@azure/identity";
125
+ import { join } from "node:path";
126
+ import { readFile } from "node:fs/promises";
112
127
 
113
- const filePath = path.join(ASSET_PATH, "forms", "Invoice_1.pdf");
114
- const base64Source = fs.readFileSync(filePath, { encoding: "base64" });
128
+ const client = DocumentIntelligence(
129
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
130
+ new DefaultAzureCredential(),
131
+ );
132
+
133
+ const filePath = join("./assets", "forms", "Invoice_1.pdf");
134
+ const base64Source = await readFile(filePath, { encoding: "base64" });
115
135
  const initialResponse = await client
116
136
  .path("/documentModels/{modelId}:analyze", "prebuilt-layout")
117
137
  .post({
@@ -121,41 +141,29 @@ const initialResponse = await client
121
141
  },
122
142
  queryParameters: { locale: "en-IN" },
123
143
  });
124
- ```
125
-
126
- Continue creating the poller from initial response
127
-
128
- ```ts
129
- import {
130
- getLongRunningPoller,
131
- AnalyzeOperationOutput,
132
- isUnexpected,
133
- } from "@azure-rest/ai-document-intelligence";
134
144
 
135
145
  if (isUnexpected(initialResponse)) {
136
146
  throw initialResponse.body.error;
137
147
  }
148
+
138
149
  const poller = getLongRunningPoller(client, initialResponse);
139
150
  const result = (await poller.pollUntilDone()).body as AnalyzeOperationOutput;
140
151
  console.log(result);
141
- // {
142
- // status: 'succeeded',
143
- // createdDateTime: '2023-11-10T13:31:31Z',
144
- // lastUpdatedDateTime: '2023-11-10T13:31:34Z',
145
- // analyzeResult: {
146
- // apiVersion: '2023-10-31-preview',
147
- // .
148
- // .
149
- // .
150
- // contentFormat: 'text'
151
- // }
152
- // }
153
152
  ```
154
153
 
155
154
  ## Batch analysis
156
155
 
157
- ```ts
158
- import { parseResultIdFromResponse, isUnexpected } from "@azure-rest/ai-document-intelligence";
156
+ ```ts snippet:ReadmeSampleAnalyzeBatch
157
+ import DocumentIntelligence, {
158
+ isUnexpected,
159
+ parseResultIdFromResponse,
160
+ } from "@azure-rest/ai-document-intelligence";
161
+ import { DefaultAzureCredential } from "@azure/identity";
162
+
163
+ const client = DocumentIntelligence(
164
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
165
+ new DefaultAzureCredential(),
166
+ );
159
167
 
160
168
  // 1. Analyze a batch of documents
161
169
  const initialResponse = await client
@@ -164,9 +172,10 @@ const initialResponse = await client
164
172
  contentType: "application/json",
165
173
  body: {
166
174
  azureBlobSource: {
167
- containerUrl: batchTrainingFilesContainerUrl(),
175
+ containerUrl: process.env["DOCUMENT_INTELLIGENCE_BATCH_TRAINING_DATA_CONTAINER_SAS_URL"],
168
176
  },
169
- resultContainerUrl: batchTrainingFilesResultContainerUrl(),
177
+ resultContainerUrl:
178
+ process.env["DOCUMENT_INTELLIGENCE_BATCH_TRAINING_DATA_RESULT_CONTAINER_SAS_URL"],
170
179
  resultPrefix: "result",
171
180
  },
172
181
  });
@@ -174,6 +183,7 @@ const initialResponse = await client
174
183
  if (isUnexpected(initialResponse)) {
175
184
  throw initialResponse.body.error;
176
185
  }
186
+
177
187
  const resultId = parseResultIdFromResponse(initialResponse);
178
188
  console.log("resultId: ", resultId);
179
189
 
@@ -194,11 +204,14 @@ Supports output with Markdown content format along with the default plain _text_
194
204
 
195
205
  Service follows the GFM spec ([GitHub Flavored Markdown](https://github.github.com/gfm/)) for the Markdown format. Also introduces a new _contentFormat_ property with value "text" or "markdown" to indicate the result content format.
196
206
 
197
- ```ts
207
+ ```ts snippet:ReadmeSampleAnalyzeMarkdownContentFormat
198
208
  import DocumentIntelligence from "@azure-rest/ai-document-intelligence";
199
- const client = DocumentIntelligence(process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"], {
200
- key: process.env["DOCUMENT_INTELLIGENCE_API_KEY"],
201
- });
209
+ import { DefaultAzureCredential } from "@azure/identity";
210
+
211
+ const client = DocumentIntelligence(
212
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
213
+ new DefaultAzureCredential(),
214
+ );
202
215
 
203
216
  const initialResponse = await client
204
217
  .path("/documentModels/{modelId}:analyze", "prebuilt-layout")
@@ -216,7 +229,15 @@ const initialResponse = await client
216
229
 
217
230
  When this feature flag is specified, the service will further extract the values of the fields specified via the queryFields query parameter to supplement any existing fields defined by the model as fallback.
218
231
 
219
- ```ts
232
+ ```ts snippet:ReadmeSampleAnalyzeQueryFields
233
+ import DocumentIntelligence from "@azure-rest/ai-document-intelligence";
234
+ import { DefaultAzureCredential } from "@azure/identity";
235
+
236
+ const client = DocumentIntelligence(
237
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
238
+ new DefaultAzureCredential(),
239
+ );
240
+
220
241
  await client.path("/documentModels/{modelId}:analyze", "prebuilt-layout").post({
221
242
  contentType: "application/json",
222
243
  body: { urlSource: "..." },
@@ -247,18 +268,24 @@ To enable a wider set of scenarios, service introduces a "split" query parameter
247
268
 
248
269
  ## Document Classifiers #Build
249
270
 
250
- ```ts
251
- import {
252
- DocumentClassifierBuildOperationDetailsOutput,
253
- getLongRunningPoller,
271
+ ```ts snippet:ReadmeSampleDocumentClassifierBuild
272
+ import DocumentIntelligence, {
254
273
  isUnexpected,
274
+ getLongRunningPoller,
275
+ DocumentClassifierBuildOperationDetailsOutput,
255
276
  } from "@azure-rest/ai-document-intelligence";
277
+ import { DefaultAzureCredential } from "@azure/identity";
278
+
279
+ const client = DocumentIntelligence(
280
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
281
+ new DefaultAzureCredential(),
282
+ );
256
283
 
257
284
  const containerSasUrl = (): string =>
258
285
  process.env["DOCUMENT_INTELLIGENCE_TRAINING_CONTAINER_SAS_URL"];
259
286
  const initialResponse = await client.path("/documentClassifiers:build").post({
260
287
  body: {
261
- classifierId: `customClassifier${getRandomNumber()}`,
288
+ classifierId: `customClassifier-12345`,
262
289
  description: "Custom classifier description",
263
290
  docTypes: {
264
291
  foo: {
@@ -278,33 +305,34 @@ const initialResponse = await client.path("/documentClassifiers:build").post({
278
305
  if (isUnexpected(initialResponse)) {
279
306
  throw initialResponse.body.error;
280
307
  }
308
+
281
309
  const poller = getLongRunningPoller(client, initialResponse);
282
310
  const response = (await poller.pollUntilDone())
283
311
  .body as DocumentClassifierBuildOperationDetailsOutput;
284
312
  console.log(response);
285
- // {
286
- // operationId: '31466834048_f3ee629e-73fb-48ab-993b-1d55d73ca460',
287
- // kind: 'documentClassifierBuild',
288
- // status: 'succeeded',
289
- // .
290
- // .
291
- // result: {
292
- // classifierId: 'customClassifier10978',
293
- // createdDateTime: '2023-11-09T12:45:56Z',
294
- // .
295
- // .
296
- // description: 'Custom classifier description'
297
- // },
298
- // apiVersion: '2023-10-31-preview'
299
- // }
300
313
  ```
301
314
 
302
315
  ## Get the generated PDF output from document analysis
303
316
 
304
- ```ts
305
- const filePath = path.join(ASSET_PATH, "layout-pageobject.pdf");
317
+ ```ts snippet:ReadmeSampleGetPdfOutput
318
+ import DocumentIntelligence, {
319
+ isUnexpected,
320
+ getLongRunningPoller,
321
+ parseResultIdFromResponse,
322
+ streamToUint8Array,
323
+ } from "@azure-rest/ai-document-intelligence";
324
+ import { DefaultAzureCredential } from "@azure/identity";
325
+ import { join } from "node:path";
326
+ import { readFile, writeFile } from "node:fs/promises";
306
327
 
307
- const base64Source = await fs.readFile(filePath, { encoding: "base64" });
328
+ const client = DocumentIntelligence(
329
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
330
+ new DefaultAzureCredential(),
331
+ );
332
+
333
+ const filePath = join("./assets", "layout-pageobject.pdf");
334
+
335
+ const base64Source = await readFile(filePath, { encoding: "base64" });
308
336
 
309
337
  const initialResponse = await client
310
338
  .path("/documentModels/{modelId}:analyze", "prebuilt-read")
@@ -338,16 +366,31 @@ if (output.status !== "200" || !output.body) {
338
366
  }
339
367
 
340
368
  const pdfData = await streamToUint8Array(output.body);
341
- fs.promises.writeFile(`./output.pdf`, pdfData);
342
- // Or you can consume the NodeJS.ReadableStream directly
369
+ await writeFile(`./output.pdf`, pdfData);
343
370
  ```
344
371
 
345
372
  ## Get the generated cropped image of specified figure from document analysis
346
373
 
347
- ```ts
348
- const filePath = path.join(ASSET_PATH, "layout-pageobject.pdf");
374
+ ```ts snippet:ReadmeSampleGetFigureImage
375
+ import DocumentIntelligence, {
376
+ isUnexpected,
377
+ getLongRunningPoller,
378
+ AnalyzeOperationOutput,
379
+ parseResultIdFromResponse,
380
+ streamToUint8Array,
381
+ } from "@azure-rest/ai-document-intelligence";
382
+ import { DefaultAzureCredential } from "@azure/identity";
383
+ import { join } from "node:path";
384
+ import { readFile, writeFile } from "node:fs/promises";
349
385
 
350
- const base64Source = fs.readFileSync(filePath, { encoding: "base64" });
386
+ const client = DocumentIntelligence(
387
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
388
+ new DefaultAzureCredential(),
389
+ );
390
+
391
+ const filePath = join("./assets", "layout-pageobject.pdf");
392
+
393
+ const base64Source = await readFile(filePath, { encoding: "base64" });
351
394
 
352
395
  const initialResponse = await client
353
396
  .path("/documentModels/{modelId}:analyze", "prebuilt-layout")
@@ -363,14 +406,11 @@ if (isUnexpected(initialResponse)) {
363
406
  throw initialResponse.body.error;
364
407
  }
365
408
 
366
- const poller = getLongRunningPoller(client, initialResponse, { ...testPollingOptions });
409
+ const poller = getLongRunningPoller(client, initialResponse);
367
410
 
368
411
  const result = (await poller.pollUntilDone()).body as AnalyzeOperationOutput;
369
412
  const figures = result.analyzeResult?.figures;
370
- assert.isArray(figures);
371
- assert.isNotEmpty(figures?.[0]);
372
413
  const figureId = figures?.[0].id || "";
373
- assert.isDefined(figureId);
374
414
 
375
415
  const output = await client
376
416
  .path(
@@ -387,31 +427,44 @@ if (output.status !== "200" || !output.body) {
387
427
  }
388
428
 
389
429
  const imageData = await streamToUint8Array(output.body);
390
- fs.promises.writeFile(`./figures/${figureId}.png`, imageData);
391
- // Or you can consume the NodeJS.ReadableStream directly
430
+ await writeFile(`./figures/${figureId}.png`, imageData);
392
431
  ```
393
432
 
394
433
  ## Get Info
395
434
 
396
- ```ts
435
+ ```ts snippet:ReadmeSampleGetInfo
436
+ import DocumentIntelligence, { isUnexpected } from "@azure-rest/ai-document-intelligence";
437
+ import { DefaultAzureCredential } from "@azure/identity";
438
+
439
+ const client = DocumentIntelligence(
440
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
441
+ new DefaultAzureCredential(),
442
+ );
443
+
397
444
  const response = await client.path("/info").get();
398
445
  if (isUnexpected(response)) {
399
446
  throw response.body.error;
400
447
  }
448
+
401
449
  console.log(response.body.customDocumentModels.limit);
402
- // 20000
403
450
  ```
404
451
 
405
452
  ## List Document Models
406
453
 
407
- ```ts
408
- import { paginate } from "@azure-rest/ai-document-intelligence";
454
+ ```ts snippet:ReadmeSampleListDocumentModels
455
+ import DocumentIntelligence, { isUnexpected, paginate } from "@azure-rest/ai-document-intelligence";
456
+ import { DefaultAzureCredential } from "@azure/identity";
457
+
458
+ const client = DocumentIntelligence(
459
+ process.env["DOCUMENT_INTELLIGENCE_ENDPOINT"],
460
+ new DefaultAzureCredential(),
461
+ );
462
+
409
463
  const response = await client.path("/documentModels").get();
410
464
  if (isUnexpected(response)) {
411
465
  throw response.body.error;
412
466
  }
413
467
 
414
- const modelsInAccount: string[] = [];
415
468
  for await (const model of paginate(client, response)) {
416
469
  console.log(model.modelId);
417
470
  }
@@ -423,8 +476,8 @@ for await (const model of paginate(client, response)) {
423
476
 
424
477
  Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
425
478
 
426
- ```javascript
427
- const { setLogLevel } = require("@azure/logger");
479
+ ```ts snippet:SetLogLevel
480
+ import { setLogLevel } from "@azure/logger";
428
481
 
429
482
  setLogLevel("info");
430
483
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-rest/ai-document-intelligence",
3
- "version": "1.0.0-alpha.20250130.1",
3
+ "version": "1.0.0-alpha.20250203.1",
4
4
  "description": "Document Intelligence Rest Client",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -8,7 +8,7 @@
8
8
  "sideEffects": false,
9
9
  "autoPublish": false,
10
10
  "tshy": {
11
- "project": "tsconfig.src.json",
11
+ "project": "./tsconfig.src.json",
12
12
  "exports": {
13
13
  "./package.json": "./package.json",
14
14
  ".": "./src/index.ts"
@@ -33,11 +33,9 @@
33
33
  "author": "Microsoft Corporation",
34
34
  "license": "MIT",
35
35
  "files": [
36
- "dist",
36
+ "dist/",
37
37
  "README.md",
38
- "LICENSE",
39
- "review/*",
40
- "CHANGELOG.md"
38
+ "LICENSE"
41
39
  ],
42
40
  "sdk-type": "client",
43
41
  "repository": "github:Azure/azure-sdk-for-js",
@@ -57,51 +55,52 @@
57
55
  "dependencies": {
58
56
  "@azure-rest/core-client": "^2.3.1",
59
57
  "@azure/core-auth": "^1.9.0",
60
- "@azure/core-rest-pipeline": "^1.18.1",
58
+ "@azure/core-lro": "^3.1.0",
59
+ "@azure/core-rest-pipeline": "^1.18.2",
61
60
  "@azure/logger": "^1.1.4",
62
- "tslib": "^2.8.1",
63
- "@azure/core-lro": "^3.1.0"
61
+ "tslib": "^2.8.1"
64
62
  },
65
63
  "devDependencies": {
64
+ "@azure-tools/test-credential": "^2.0.0",
65
+ "@azure-tools/test-recorder": ">=4.1.0-alpha <4.1.0-alphb",
66
+ "@azure-tools/test-utils-vitest": ">=1.0.0-alpha <1.0.0-alphb",
66
67
  "@azure/abort-controller": "^2.1.2",
67
- "dotenv": "^16.0.0",
68
+ "@azure/dev-tool": ">=1.0.0-alpha <1.0.0-alphb",
69
+ "@azure/eslint-plugin-azure-sdk": ">=3.0.0-alpha <3.0.0-alphb",
70
+ "@azure/identity": "^4.6.0",
68
71
  "@types/node": "^18.0.0",
69
- "eslint": "^9.9.0",
70
- "typescript": "~5.7.2",
71
- "@azure/identity": "^4.2.1",
72
72
  "@vitest/browser": "^3.0.3",
73
73
  "@vitest/coverage-istanbul": "^3.0.3",
74
- "playwright": "^1.41.2",
75
- "vitest": "^3.0.3",
76
- "@azure-tools/test-credential": "^2.0.0",
77
- "@azure-tools/test-recorder": "^4.0.0",
78
- "@azure/dev-tool": ">=1.0.0-alpha <1.0.0-alphb",
79
- "@azure/eslint-plugin-azure-sdk": ">=3.0.0-alpha <3.0.0-alphb"
74
+ "dotenv": "^16.0.0",
75
+ "eslint": "^9.9.0",
76
+ "playwright": "^1.50.1",
77
+ "typescript": "~5.7.2",
78
+ "vitest": "^3.0.3"
80
79
  },
81
80
  "scripts": {
82
- "clean": "dev-tool run vendored rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz",
83
- "extract-api": "dev-tool run vendored rimraf review && dev-tool run extract-api",
84
- "pack": "npm pack 2>&1",
85
- "lint": "eslint package.json api-extractor.json src test",
86
- "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]",
87
- "unit-test": "npm run unit-test:node && npm run unit-test:browser",
88
- "unit-test:browser": "echo skipped",
89
- "unit-test:node": "dev-tool run test:vitest --test-proxy-debug",
90
- "integration-test": "npm run integration-test:node && npm run integration-test:browser",
91
- "integration-test:browser": "echo skipped",
92
- "integration-test:node": "dev-tool run test:vitest --esm",
81
+ "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api",
93
82
  "build:samples": "echo skipped",
83
+ "build:test": "npm run clean && dev-tool run build-package && dev-tool run build-test",
94
84
  "check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\" ",
85
+ "clean": "dev-tool run vendored rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz",
95
86
  "execute:samples": "echo skipped",
87
+ "extract-api": "dev-tool run vendored rimraf review && dev-tool run extract-api",
96
88
  "format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.{ts,cts,mts}\" \"test/**/*.{ts,cts,mts}\" \"samples-dev/*.{ts,cts,mts}\" \"*.{js,cjs,mjs,json}\" ",
97
89
  "generate:client": "echo skipped",
98
- "test:browser": "npm run clean && npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
90
+ "integration-test": "npm run integration-test:node && npm run integration-test:browser",
91
+ "integration-test:browser": "echo skipped",
92
+ "integration-test:node": "dev-tool run test:vitest --esm",
93
+ "lint": "eslint package.json api-extractor.json src test",
94
+ "lint:fix": "eslint package.json api-extractor.json src test --fix --fix-type [problem,suggestion]",
99
95
  "minify": "dev-tool run vendored uglifyjs -c -m --comments --source-map \"content='./dist/index.js.map'\" -o ./dist/index.min.js ./dist/index.js",
100
- "build:test": "npm run clean && dev-tool run build-package && dev-tool run build-test",
101
- "build": "npm run clean && dev-tool run build-package && dev-tool run extract-api",
102
- "test:node": "npm run clean && dev-tool run build-package && npm run unit-test:node && npm run integration-test:node",
96
+ "pack": "npm pack 2>&1",
103
97
  "test": "npm run clean && dev-tool run build-package && npm run unit-test:node && dev-tool run bundle && npm run unit-test:browser && npm run integration-test",
104
- "update-snippets": "echo skipped"
98
+ "test:browser": "npm run clean && npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
99
+ "test:node": "npm run clean && dev-tool run build-package && npm run unit-test:node && npm run integration-test:node",
100
+ "unit-test": "npm run unit-test:node && npm run unit-test:browser",
101
+ "unit-test:browser": "echo skipped",
102
+ "unit-test:node": "dev-tool run test:vitest",
103
+ "update-snippets": "dev-tool run update-snippets"
105
104
  },
106
105
  "exports": {
107
106
  "./package.json": "./package.json",
@@ -135,5 +134,7 @@
135
134
  "ai-document-intelligence"
136
135
  ],
137
136
  "disableDocsMs": true
138
- }
137
+ },
138
+ "browser": "./dist/browser/index.js",
139
+ "react-native": "./dist/react-native/index.js"
139
140
  }