Skip to content

Commit 8471b0f

Browse files
committed
Add Nutrient document task skill scripts
1 parent 1517a80 commit 8471b0f

23 files changed

+1168
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
name: nutrient-document-tasks
3+
description: Execute common document-processing tasks with @nutrient-sdk/dws-client-typescript in Node.js scripts. Use when the user asks to convert, merge, split, OCR, extract text/tables/key-value pairs, watermark, redact, sign, optimize, protect, or reorder PDF content, or when they need a custom multi-step document pipeline script built from Nutrient DWS workflow actions.
4+
---
5+
6+
# Nutrient Document Tasks
7+
8+
## Quick Start
9+
10+
1. Ensure Node.js 18+ is available.
11+
2. Install the latest client package in the target project:
12+
- `node skills/nutrient-document-tasks/scripts/setup-latest-client.mjs npm`
13+
3. Export the API key before running scripts:
14+
- `export NUTRIENT_API_KEY="nutr_sk_..."`
15+
4. Run task scripts with `node` from the repository root.
16+
17+
## Task Scripts
18+
19+
Use one script per operation.
20+
21+
- Convert formats: `scripts/convert.mjs`
22+
- Merge files: `scripts/merge.mjs`
23+
- Split by ranges: `scripts/split.mjs`
24+
- OCR documents: `scripts/ocr.mjs`
25+
- Extract text: `scripts/extract-text.mjs`
26+
- Extract tables: `scripts/extract-table.mjs`
27+
- Extract key-value pairs: `scripts/extract-key-value-pairs.mjs`
28+
- Add text watermark: `scripts/watermark-text.mjs`
29+
- AI redaction: `scripts/redact-ai.mjs`
30+
- Rotate pages: `scripts/rotate.mjs`
31+
- Sign PDF: `scripts/sign.mjs`
32+
- Optimize PDF: `scripts/optimize.mjs`
33+
- Password protect PDF: `scripts/password-protect.mjs`
34+
- Add blank pages: `scripts/add-pages.mjs`
35+
- Delete pages: `scripts/delete-pages.mjs`
36+
- Duplicate/reorder pages: `scripts/duplicate-pages.mjs`
37+
38+
Check exact arguments with `node <script> --help`.
39+
40+
## Custom Pipelines
41+
42+
When the user asks for a workflow not covered by the scripts above, create a new script rather than forcing ad hoc one-off commands.
43+
44+
1. Start from `assets/templates/custom-workflow-template.mjs`.
45+
2. Save the new script in `scripts/` with a task-specific name (for example `scripts/redact-and-watermark.mjs`).
46+
3. Keep API usage on `@nutrient-sdk/dws-client-typescript@latest`.
47+
4. Prefer direct methods (`client.convert`, `client.merge`, etc.) for single-step tasks.
48+
5. Use `client.workflow()` and `BuildActions` for multi-step tasks.
49+
6. Keep every custom script CLI-driven (`--input`, `--out`, explicit options), deterministic, and runnable end-to-end.
50+
7. Run the script with sample input to verify behavior before finalizing.
51+
52+
## Implementation Rules
53+
54+
- Fail fast when required arguments are missing.
55+
- Require local input for operations that do not support URL input (`sign`).
56+
- Write outputs to explicit paths and print created files.
57+
- Do not log secrets.
58+
- If the package import fails, install latest with `npm install @nutrient-sdk/dws-client-typescript@latest`.
59+
60+
## References
61+
62+
- Script matrix and method mapping: `references/script-catalog.md`
63+
- Custom pipeline patterns: `references/custom-pipeline-guidelines.md`
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Nutrient DWS Doc Ops"
3+
short_description: "Run common document automation scripts with Nutrient DWS"
4+
default_prompt: "Use this skill to run existing scripts or generate new script-based document pipelines with @nutrient-sdk/dws-client-typescript."
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env node
2+
3+
import {
4+
createClient,
5+
handleError,
6+
isHelpRequested,
7+
parseArgs,
8+
requireArg,
9+
toFileInput,
10+
writeWorkflowOutput,
11+
} from './lib/common.mjs';
12+
13+
import { BuildActions } from '@nutrient-sdk/dws-client-typescript';
14+
15+
const USAGE = `
16+
Template for multi-step custom workflows.
17+
18+
Usage:
19+
node <script>.mjs --input <path-or-url> --out <output-pdf>
20+
`;
21+
22+
const args = parseArgs();
23+
if (isHelpRequested(args)) {
24+
console.log(USAGE.trim());
25+
process.exit(0);
26+
}
27+
28+
try {
29+
const input = requireArg(args, 'input', USAGE);
30+
const out = requireArg(args, 'out', USAGE);
31+
32+
const client = await createClient();
33+
34+
// Customize this action list for the requested pipeline.
35+
const actions = [
36+
BuildActions.ocr('english'),
37+
BuildActions.watermarkText('DRAFT', { opacity: 0.25, rotation: 45 }),
38+
];
39+
40+
const result = await client
41+
.workflow()
42+
.addFilePart(toFileInput(input), undefined, actions)
43+
.outputPdf()
44+
.execute();
45+
46+
await writeWorkflowOutput(result, out);
47+
} catch (error) {
48+
handleError(error);
49+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Custom Pipeline Guidelines
2+
3+
## When to Build a New Script
4+
5+
Build a custom script when the user needs:
6+
- Multiple actions in one run (for example OCR + redact + watermark + optimize)
7+
- Conditional logic around extraction results
8+
- Organization-specific defaults or output layout
9+
10+
## Preferred Construction Order
11+
12+
1. Validate CLI inputs and parse options.
13+
2. Create client with `NUTRIENT_API_KEY`.
14+
3. Build workflow using either:
15+
- Direct methods for single operation
16+
- `client.workflow()` for multi-step actions
17+
4. Execute and write outputs to deterministic paths.
18+
5. Print file outputs and exit non-zero on failures.
19+
20+
## Script Quality Requirements
21+
22+
- Keep scripts non-interactive.
23+
- Accept all runtime values by args/env vars.
24+
- Avoid hard-coded secrets and absolute local paths.
25+
- Emit structured output files (PDF/JSON/TXT) instead of console-only output.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Script Catalog
2+
3+
## Setup
4+
5+
- `scripts/setup-latest-client.mjs`
6+
- Install `@nutrient-sdk/dws-client-typescript@latest` with npm/pnpm/yarn.
7+
8+
## Core Document Operations
9+
10+
- `scripts/convert.mjs`
11+
- Method: `client.convert(input, format)`
12+
- Common use: office-to-pdf, pdf-to-markdown/html/image
13+
14+
- `scripts/merge.mjs`
15+
- Method: `client.merge(files)`
16+
- Common use: combine reports, append cover pages
17+
18+
- `scripts/split.mjs`
19+
- Method: `client.split(file, ranges)`
20+
- Common use: split sections into separate files
21+
22+
- `scripts/ocr.mjs`
23+
- Method: `client.ocr(file, language|language[])`
24+
- Common use: searchable text from scanned PDFs
25+
26+
- `scripts/extract-text.mjs`
27+
- Method: `client.extractText(file, pages?)`
28+
- Common use: content indexing and summarization input
29+
30+
- `scripts/extract-table.mjs`
31+
- Method: `client.extractTable(file, pages?)`
32+
- Common use: analytics ingest from PDFs
33+
34+
- `scripts/extract-key-value-pairs.mjs`
35+
- Method: `client.extractKeyValuePairs(file, pages?)`
36+
- Common use: forms, invoices, claims data extraction
37+
38+
## PDF Editing and Security
39+
40+
- `scripts/watermark-text.mjs`
41+
- Method: `client.watermarkText(file, text, options?)`
42+
43+
- `scripts/redact-ai.mjs`
44+
- Method: `client.createRedactionsAI(file, criteria, mode, pages?)`
45+
46+
- `scripts/rotate.mjs`
47+
- Method: `client.rotate(file, angle, pages?)`
48+
49+
- `scripts/sign.mjs`
50+
- Method: `client.sign(file, signatureData?, options?)`
51+
- Note: input must be local file path
52+
53+
- `scripts/optimize.mjs`
54+
- Method: `client.optimize(file, options?)`
55+
56+
- `scripts/password-protect.mjs`
57+
- Method: `client.passwordProtect(file, userPassword, ownerPassword, permissions?)`
58+
59+
- `scripts/add-pages.mjs`
60+
- Method: `client.addPage(file, count, index?)`
61+
62+
- `scripts/delete-pages.mjs`
63+
- Method: `client.deletePages(file, pageIndices)`
64+
65+
- `scripts/duplicate-pages.mjs`
66+
- Method: `client.duplicatePages(file, pageIndices)`
67+
68+
## Page Range Conventions
69+
70+
Use `start:end` and comma-separated lists for multi-range inputs.
71+
72+
Examples:
73+
- `0:2` -> first three pages
74+
- `-3:-1` -> last three pages
75+
- `0:2,3:5` -> two segments
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env node
2+
3+
import {
4+
createClient,
5+
handleError,
6+
isHelpRequested,
7+
parseArgs,
8+
requireArg,
9+
toFileInput,
10+
writeWorkflowOutput,
11+
} from './lib/common.mjs';
12+
13+
const USAGE = `
14+
Add blank pages to a PDF.
15+
16+
Usage:
17+
node scripts/add-pages.mjs --input <path-or-url> --count <n> --out <output-pdf> [--index <insert-index>]
18+
`;
19+
20+
const args = parseArgs();
21+
if (isHelpRequested(args)) {
22+
console.log(USAGE.trim());
23+
process.exit(0);
24+
}
25+
26+
try {
27+
const input = requireArg(args, 'input', USAGE);
28+
const count = Number.parseInt(requireArg(args, 'count', USAGE), 10);
29+
if (!Number.isInteger(count) || count <= 0) {
30+
throw new Error('--count must be a positive integer.');
31+
}
32+
33+
const out = requireArg(args, 'out', USAGE);
34+
const index = args.index !== undefined ? Number.parseInt(String(args.index), 10) : undefined;
35+
36+
const client = await createClient();
37+
const result = await client.addPage(toFileInput(input), count, index);
38+
await writeWorkflowOutput(result, out);
39+
} catch (error) {
40+
handleError(error);
41+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env node
2+
3+
import {
4+
createClient,
5+
handleError,
6+
isHelpRequested,
7+
parseArgs,
8+
requireArg,
9+
toFileInput,
10+
writeWorkflowOutput,
11+
} from './lib/common.mjs';
12+
13+
const USAGE = `
14+
Convert a document to another format.
15+
16+
Usage:
17+
node scripts/convert.mjs --input <path-or-url> --format <pdf|pdfa|pdfua|docx|xlsx|pptx|png|jpeg|jpg|webp|html|markdown> --out <output-file>
18+
`;
19+
20+
const args = parseArgs();
21+
if (isHelpRequested(args)) {
22+
console.log(USAGE.trim());
23+
process.exit(0);
24+
}
25+
26+
try {
27+
const input = requireArg(args, 'input', USAGE);
28+
const format = requireArg(args, 'format', USAGE);
29+
const out = requireArg(args, 'out', USAGE);
30+
31+
const client = await createClient();
32+
const result = await client.convert(toFileInput(input), format);
33+
await writeWorkflowOutput(result, out);
34+
} catch (error) {
35+
handleError(error);
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env node
2+
3+
import {
4+
createClient,
5+
handleError,
6+
isHelpRequested,
7+
parseArgs,
8+
parseIntegerCsv,
9+
requireArg,
10+
toFileInput,
11+
usageError,
12+
writeWorkflowOutput,
13+
} from './lib/common.mjs';
14+
15+
const USAGE = `
16+
Delete specific pages from a PDF.
17+
18+
Usage:
19+
node scripts/delete-pages.mjs --input <path-or-url> --pages <index,index,...> --out <output-pdf>
20+
21+
Examples:
22+
node scripts/delete-pages.mjs --input doc.pdf --pages 0,2,-1 --out doc-without-pages.pdf
23+
`;
24+
25+
const args = parseArgs();
26+
if (isHelpRequested(args)) {
27+
console.log(USAGE.trim());
28+
process.exit(0);
29+
}
30+
31+
try {
32+
const input = requireArg(args, 'input', USAGE);
33+
const pagesRaw = requireArg(args, 'pages', USAGE);
34+
const out = requireArg(args, 'out', USAGE);
35+
36+
const pageIndices = parseIntegerCsv(pagesRaw, 'pages');
37+
if (pageIndices.length === 0) {
38+
throw usageError('--pages must include at least one index.', USAGE);
39+
}
40+
41+
const client = await createClient();
42+
const result = await client.deletePages(toFileInput(input), pageIndices);
43+
await writeWorkflowOutput(result, out);
44+
} catch (error) {
45+
handleError(error);
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env node
2+
3+
import {
4+
createClient,
5+
handleError,
6+
isHelpRequested,
7+
parseArgs,
8+
parseIntegerCsv,
9+
requireArg,
10+
toFileInput,
11+
usageError,
12+
writeWorkflowOutput,
13+
} from './lib/common.mjs';
14+
15+
const USAGE = `
16+
Create a new PDF from specific page indices (supports duplicates/reordering).
17+
18+
Usage:
19+
node scripts/duplicate-pages.mjs --input <path-or-url> --pages <index,index,...> --out <output-pdf>
20+
21+
Examples:
22+
node scripts/duplicate-pages.mjs --input doc.pdf --pages 2,0,1,1 --out reordered.pdf
23+
`;
24+
25+
const args = parseArgs();
26+
if (isHelpRequested(args)) {
27+
console.log(USAGE.trim());
28+
process.exit(0);
29+
}
30+
31+
try {
32+
const input = requireArg(args, 'input', USAGE);
33+
const pagesRaw = requireArg(args, 'pages', USAGE);
34+
const out = requireArg(args, 'out', USAGE);
35+
36+
const pageIndices = parseIntegerCsv(pagesRaw, 'pages');
37+
if (pageIndices.length === 0) {
38+
throw usageError('--pages must include at least one index.', USAGE);
39+
}
40+
41+
const client = await createClient();
42+
const result = await client.duplicatePages(toFileInput(input), pageIndices);
43+
await writeWorkflowOutput(result, out);
44+
} catch (error) {
45+
handleError(error);
46+
}

0 commit comments

Comments
 (0)