File size: 2,742 Bytes
1b756c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { ClassicPreset } from 'rete';
import { BaseWorkflowNode } from './base-node';
import { pdfSocket } from '../sockets';
import type { SocketData } from '../types';
import { requirePdfInput, processBatch } from '../types';
import { PDFDocument } from 'pdf-lib';

export class EditMetadataNode extends BaseWorkflowNode {
  readonly category = 'Organize & Manage' as const;
  readonly icon = 'ph-file-code';
  readonly description = 'Edit PDF metadata';

  constructor() {
    super('Edit Metadata');
    this.addInput('pdf', new ClassicPreset.Input(pdfSocket, 'PDF'));
    this.addOutput('pdf', new ClassicPreset.Output(pdfSocket, 'PDF'));
    this.addControl(
      'title',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
    this.addControl(
      'author',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
    this.addControl(
      'subject',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
    this.addControl(
      'keywords',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
    this.addControl(
      'creator',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
    this.addControl(
      'producer',
      new ClassicPreset.InputControl('text', { initial: '' })
    );
  }

  async data(
    inputs: Record<string, SocketData[]>
  ): Promise<Record<string, SocketData>> {
    const pdfInputs = requirePdfInput(inputs, 'Edit Metadata');

    const getText = (key: string) => {
      const ctrl = this.controls[key] as
        | ClassicPreset.InputControl<'text'>
        | undefined;
      return ctrl?.value || '';
    };

    const title = getText('title');
    const author = getText('author');
    const subject = getText('subject');
    const keywords = getText('keywords');
    const creator = getText('creator');
    const producer = getText('producer');

    return {
      pdf: await processBatch(pdfInputs, async (input) => {
        const pdfDoc = await PDFDocument.load(input.bytes);

        if (title) pdfDoc.setTitle(title);
        if (author) pdfDoc.setAuthor(author);
        if (subject) pdfDoc.setSubject(subject);
        if (keywords)
          pdfDoc.setKeywords(
            keywords
              .split(',')
              .map((k) => k.trim())
              .filter(Boolean)
          );
        if (creator) pdfDoc.setCreator(creator);
        if (producer) pdfDoc.setProducer(producer);
        pdfDoc.setModificationDate(new Date());

        const pdfBytes = await pdfDoc.save();
        return {
          type: 'pdf',
          document: pdfDoc,
          bytes: new Uint8Array(pdfBytes),
          filename: input.filename.replace(/\.pdf$/i, '_metadata.pdf'),
        };
      }),
    };
  }
}