Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,19 @@
{
"PDF": "PDF",
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Text extrahieren",
"Convert to Image": "In Bild konvertieren",
"Text to PDF": "Text in PDF",
"Image to PDF": "Bild als PDF",
"PDF Page Count": "PDF-Seitenanzahl",
"Extract PDF Pages": "PDF-Seiten extrahieren",
"Merge PDFs": "PDFs zusammenführen",
"Extract text from PDF file or url": "Text aus PDF-Datei oder URL extrahieren",
"Convert a PDF file or URL to an image": "PDF-Datei oder URL in ein Bild konvertieren",
"Convert text to PDF": "Text in PDF konvertieren",
"Convert image to PDF": "Bild in PDF konvertieren",
"Get page count of PDF file.": "Seitenanzahl der PDF-Datei abrufen.",
"Extract or rearrange page(s)from PDF File.": "Entpacken oder ordnen Sie Seite(n) aus PDF Datei neu an.",
"Merges multiple PDF files into a single PDF document.": "Fügt mehrere PDF-Dateien zu einem einzigen PDF-Dokument zusammen.",
"PDF File or URL": "PDF-Datei oder URL",
"Output Image Type": "Ausgabebild Typ",
"text": "text",
"image": "bild",
"Markdown": "Markdown",
"Page Ranges": "Seitenbereiche",
"PDF Files": "PDF-Dateien",
"Output File Name": "Dateiname ausgeben",
"Enter text to convert": "Text zum Konvertieren eingeben",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Bild muss png sein, jpeg oder jpg und es wird auf die Seite reduziert, wenn das Bild größer ist als eine A4-Seite",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nDiese Aktion kann die Seiten in einer PDF Datei extrahieren oder neu anordnen.\n\n- Die Reihenfolge des Arrays bestimmt die Reihenfolge der Seiten.\n- Jedes Array-Element ist ein durchgängiger Bereich mit einer Start- und Endseite.\n- Seiten beginnen von 1 und 0 ist nicht gültig.\n- Startseite muss kleiner als Endseite sein.\n- Sie können eine Seite auswählen, indem Sie die gleiche Start- und Endseite setzen.\n- Um Seiten von Anfang an auszuwählen, geben Sie z.B. negative Seiten an. -1 ist die letzte Seite, -5 ist die 5. letzte Seite. Start: -5, Ende: -1 sind die letzten 5 Seiten.\n- Bereich kann sich nicht auf 0 erstrecken (z.B. Start: -3, End: 5.\n",
"Array of PDF files to merge": "Anordnung der zusammenzuführenden PDF-Dateien",
"Name for the merged PDF file (without extension)": "Name für die zusammengeführte PDF-Datei (ohne Erweiterung)",
"Single Combined Image": "Einzelnes kombiniertes Bild",
"Separate Image for Each Page": "Bild für jede Seite trennen"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Extraer texto",
"Convert to Image": "Convertir a imagen",
"Text to PDF": "Texto a PDF",
"Image to PDF": "Imagen a PDF",
"PDF Page Count": "Número de páginas PDF",
"Extract PDF Pages": "Extraer páginas PDF",
"Merge PDFs": "Combinar PDFs",
"Extract text from PDF file or url": "Extraer texto del archivo PDF o url",
"Convert a PDF file or URL to an image": "Convierte un archivo PDF o URL a una imagen",
"Convert text to PDF": "Convertir texto a PDF",
"Convert image to PDF": "Convertir imagen a PDF",
"Get page count of PDF file.": "Obtener el conteo de páginas del archivo PDF.",
"Extract or rearrange page(s)from PDF File.": "Extraer o reorganizar página(s) del archivo PDF.",
"Merges multiple PDF files into a single PDF document.": "Combina múltiples archivos PDF en un solo documento PDF.",
"PDF File or URL": "Archivo PDF o URL",
"Output Image Type": "Tipo de imagen de salida",
"text": "texto",
"image": "imagen",
"Markdown": "Markdown",
"Page Ranges": "Rangos de página",
"PDF Files": "Archivos PDF",
"Output File Name": "Nombre del archivo de salida",
"Enter text to convert": "Introduzca texto a convertir",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "La imagen tiene que ser png, jpeg o jpg y se reducirá para ajustarse a la página cuando la imagen sea mayor que una página A4",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "Arreglo de archivos PDF a combinar",
"Name for the merged PDF file (without extension)": "Nombre para el archivo PDF combinado (sin extensión)",
"Single Combined Image": "Imagen única combinada",
"Separate Image for Each Page": "Separar imagen para cada página"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Extraire le texte",
"Convert to Image": "Convertir en Image",
"Text to PDF": "Texte au format PDF",
"Image to PDF": "Image au format PDF",
"PDF Page Count": "Nombre de pages PDF",
"Extract PDF Pages": "Extraire les pages PDF",
"Merge PDFs": "Fusionner les PDF",
"Extract text from PDF file or url": "Extraire du texte du fichier PDF ou de l'URL",
"Convert a PDF file or URL to an image": "Convertir un fichier PDF ou une URL en image",
"Convert text to PDF": "Convertir le texte en PDF",
"Convert image to PDF": "Convertir l'image en PDF",
"Get page count of PDF file.": "Obtenir le nombre de pages du fichier PDF.",
"Extract or rearrange page(s)from PDF File.": "Extraire ou réorganiser la(les) page(s) depuis le fichier PDF.",
"Merges multiple PDF files into a single PDF document.": "Fusionne plusieurs fichiers PDF en un seul document PDF.",
"PDF File or URL": "Fichier PDF ou URL",
"Output Image Type": "Type d'image de sortie",
"text": "texte du texte",
"image": "image",
"Markdown": "Markdown",
"Page Ranges": "Intervalle de pages",
"PDF Files": "Fichiers PDF",
"Output File Name": "Nom du fichier de sortie",
"Enter text to convert": "Entrez le texte à convertir",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "L'image doit être en png, jpeg ou jpg et il sera redimensionné pour s'adapter à la page lorsque l'image est plus grande qu'une page A4",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "Tableau de fichiers PDF à fusionner",
"Name for the merged PDF file (without extension)": "Nom du fichier PDF fusionné (sans extension)",
"Single Combined Image": "Image unique combinée",
"Separate Image for Each Page": "Image séparée pour chaque page"
}

View File

@@ -0,0 +1,19 @@
{
"PDF": "PDF",
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,19 @@
{
"PDF": "PDF",
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "テキストを抽出",
"Convert to Image": "画像に変換",
"Text to PDF": "PDF にテキスト",
"Image to PDF": "PDFへの画像",
"PDF Page Count": "PDF ページ数",
"Extract PDF Pages": "PDFページを抽出",
"Merge PDFs": "PDF の結合",
"Extract text from PDF file or url": "PDFファイルまたはURLからテキストを抽出",
"Convert a PDF file or URL to an image": "PDFファイルまたはURLを画像に変換",
"Convert text to PDF": "テキストをPDFに変換する",
"Convert image to PDF": "画像をPDFに変換",
"Get page count of PDF file.": "PDF ファイルのページ数を取得します。",
"Extract or rearrange page(s)from PDF File.": "PDFファイルからページを抽出または並べ替えます。",
"Merges multiple PDF files into a single PDF document.": "複数の PDF ファイルを 1 つの PDF ドキュメントにマージします。",
"PDF File or URL": "PDFファイルまたはURL",
"Output Image Type": "出力イメージタイプ",
"text": "テキスト",
"image": "画像",
"Markdown": "Markdown",
"Page Ranges": "ページ範囲",
"PDF Files": "PDF ファイル",
"Output File Name": "出力ファイル名",
"Enter text to convert": "変換するテキストを入力してください",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "画像はpngでなければなりません jpegまたはjpgと画像がA4ページより大きいときにページに合わせて縮小します",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "マージするPDFファイルの配列",
"Name for the merged PDF file (without extension)": "統合された PDF ファイルの名前 (拡張子なし)",
"Single Combined Image": "単一の複合画像",
"Separate Image for Each Page": "各ページごとに画像を分離する"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Tekst uitpakken",
"Convert to Image": "Converteren naar afbeelding",
"Text to PDF": "Tekst naar PDF",
"Image to PDF": "Afbeelding naar PDF",
"PDF Page Count": "PDF pagina aantal",
"Extract PDF Pages": "PDF-pagina's uitpakken",
"Merge PDFs": "PDF's samenvoegen",
"Extract text from PDF file or url": "Tekst uit PDF-bestand of url halen",
"Convert a PDF file or URL to an image": "Converteer een PDF-bestand of URL naar een afbeelding",
"Convert text to PDF": "Tekst converteren naar PDF",
"Convert image to PDF": "Afbeelding converteren naar PDF",
"Get page count of PDF file.": "Haal het aantal pagina's op van het PDF-bestand.",
"Extract or rearrange page(s)from PDF File.": "Pagina('s) uitpakken of herschikken van PDF-bestand.",
"Merges multiple PDF files into a single PDF document.": "Voegt meerdere PDF-bestanden samen in een enkel PDF-document.",
"PDF File or URL": "PDF bestand of URL",
"Output Image Type": "Uitvoer afbeeldingstype",
"text": "tekstveld",
"image": "afbeelding",
"Markdown": "Markdown",
"Page Ranges": "Pagina Bereiken",
"PDF Files": "PDF bestanden",
"Output File Name": "Uitvoer bestandsnaam",
"Enter text to convert": "Voer tekst in om te converteren",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Afbeelding moet png, Jpeg of jpg en het zal naar beneden geschaald worden om te passen op de pagina wanneer de afbeelding groter is dan een A4 pagina",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nDeze actie kan de pagina's in een PDF uitpakken of herschikken.\n\n- De volgorde van de pagina's wordt bepaald door de volgorde van de pagina's.\n- Elk array element is een inclusief continu bereik met een startpagina en eindpagina.\n- Pagina's starten vanaf 1 en 0 is niet geldig.\n- Startpagina moet kleiner zijn dan de eindpagina.\n- U kunt één pagina selecteren door dezelfde start- en eindpagina in te stellen.\n- Om pagina's vanaf de start te selecteren, geef negatieve pagina's op. -1 is de laatste pagina, -5 is de 5e laatste pagina. Start: -5, einde: -1 zijn de laatste 5 pagina's.\n- Het bereik kan niet span tussen 0 bijv. start: -3, end: 5.\n",
"Array of PDF files to merge": "Array van PDF-bestanden samen te voegen",
"Name for the merged PDF file (without extension)": "Naam voor het samengevoegde PDF-bestand (zonder extensie)",
"Single Combined Image": "Enkele gecombineerde afbeelding",
"Separate Image for Each Page": "Aparte afbeelding voor elke pagina"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Extrair Texto",
"Convert to Image": "Converter para imagem",
"Text to PDF": "Texto para PDF",
"Image to PDF": "Imagem para PDF",
"PDF Page Count": "Contagem de Páginas PDF",
"Extract PDF Pages": "Extrair páginas em PDF",
"Merge PDFs": "Mesclar PDFs",
"Extract text from PDF file or url": "Extrair texto do arquivo PDF ou URL",
"Convert a PDF file or URL to an image": "Converta um arquivo PDF ou URL para uma imagem",
"Convert text to PDF": "Converter texto para PDF",
"Convert image to PDF": "Converter imagem para PDF",
"Get page count of PDF file.": "Obter a contagem de páginas do arquivo PDF.",
"Extract or rearrange page(s)from PDF File.": "Extrair ou reorganizar a(s) página(s) de arquivo PDF.",
"Merges multiple PDF files into a single PDF document.": "Mescla vários arquivos PDF em um único documento PDF.",
"PDF File or URL": "Arquivo PDF ou URL",
"Output Image Type": "Tipo de Imagem de Saída",
"text": "texto",
"image": "Imagem",
"Markdown": "Markdown",
"Page Ranges": "Intervalos de Página",
"PDF Files": "Arquivos PDF",
"Output File Name": "Nome do arquivo de saída",
"Enter text to convert": "Digite o texto a ser convertido",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "A imagem tem que ser png, jpeg ou jpg e ele será redimensionado para se encaixar na página quando a imagem é maior que uma página A4",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "Array de arquivos PDF para mesclar",
"Name for the merged PDF file (without extension)": "Nome para o arquivo PDF mesclado (sem extensão)",
"Single Combined Image": "Imagem Combinada Simples",
"Separate Image for Each Page": "Imagem separada para cada página"
}

View File

@@ -0,0 +1,26 @@
{
"PDF": "PDF",
"Extract Text": "Извлечь текст",
"Convert to Image": "Преобразовать в изображение",
"Text to PDF": "Текст в PDF",
"Image to PDF": "Изображение в PDF",
"PDF Page Count": "Счетчик PDF-страниц",
"Extract PDF Pages": "Извлечь PDF страницы",
"Extract text from PDF file or url": "Извлечь текст из PDF файла или url",
"Convert a PDF file or URL to an image": "Преобразовать PDF файл или URL в изображение",
"Convert text to PDF": "Преобразовать текст в PDF",
"Convert image to PDF": "Преобразовать изображение в PDF",
"Get page count of PDF file.": "Получить количество страниц в PDF файле.",
"Extract or rearrange page(s)from PDF File.": "Извлечь или изменить порядок страниц из PDF-файла.",
"PDF File or URL": "PDF файл или URL",
"Output Image Type": "Тип изображения вывода",
"text": "текст",
"image": "изображение",
"Markdown": "Markdown",
"Page Ranges": "Диапазоны страниц",
"Enter text to convert": "Введите текст для преобразования",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Изображение должно быть png, jpeg или jpg и он будет масштабирован вниз по размеру страницы, когда изображение больше страницы A4",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Single Combined Image": "Одно комбинированное изображение",
"Separate Image for Each Page": "Отдельное изображение для каждой страницы"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"PDF Page Count": "PDF Page Count",
"Extract PDF Pages": "Extract PDF Pages",
"Merge PDFs": "Merge PDFs",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"Get page count of PDF file.": "Get page count of PDF file.",
"Extract or rearrange page(s)from PDF File.": "Extract or rearrange page(s)from PDF File.",
"Merges multiple PDF files into a single PDF document.": "Merges multiple PDF files into a single PDF document.",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Markdown": "Markdown",
"Page Ranges": "Page Ranges",
"PDF Files": "PDF Files",
"Output File Name": "Output File Name",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "Array of PDF files to merge",
"Name for the merged PDF file (without extension)": "Name for the merged PDF file (without extension)",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,26 @@
{
"PDF": "PDF",
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"PDF Page Count": "PDF Page Count",
"Extract PDF Pages": "Extract PDF Pages",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"Get page count of PDF file.": "Get page count of PDF file.",
"Extract or rearrange page(s)from PDF File.": "Extract or rearrange page(s)from PDF File.",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Markdown": "Markdown",
"Page Ranges": "Page Ranges",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,31 @@
{
"Extract Text": "Extract Text",
"Convert to Image": "Convert to Image",
"Text to PDF": "Text to PDF",
"Image to PDF": "Image to PDF",
"PDF Page Count": "PDF Page Count",
"Extract PDF Pages": "Extract PDF Pages",
"Merge PDFs": "Merge PDFs",
"Extract text from PDF file or url": "Extract text from PDF file or url",
"Convert a PDF file or URL to an image": "Convert a PDF file or URL to an image",
"Convert text to PDF": "Convert text to PDF",
"Convert image to PDF": "Convert image to PDF",
"Get page count of PDF file.": "Get page count of PDF file.",
"Extract or rearrange page(s)from PDF File.": "Extract or rearrange page(s)from PDF File.",
"Merges multiple PDF files into a single PDF document.": "Merges multiple PDF files into a single PDF document.",
"PDF File or URL": "PDF File or URL",
"Output Image Type": "Output Image Type",
"text": "text",
"image": "image",
"Markdown": "Markdown",
"Page Ranges": "Page Ranges",
"PDF Files": "PDF Files",
"Output File Name": "Output File Name",
"Enter text to convert": "Enter text to convert",
"Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page": "Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page",
"\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cann": "\nThis action can extract or rearrange the pages in a PDF.\n\n- The order of array determines the sequence of pages.\n- Each array element is one inclusive continuous range with a start page and end page.\n- Pages start from 1, and 0 is not valid.\n- Start page has to be less than end page.\n- You can select one page by setting the same start and end page.\n- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.\n- Range cannot span across 0 eg. start: -3, end: 5.\n",
"Array of PDF files to merge": "Array of PDF files to merge",
"Name for the merged PDF file (without extension)": "Name for the merged PDF file (without extension)",
"Single Combined Image": "Single Combined Image",
"Separate Image for Each Page": "Separate Image for Each Page"
}

View File

@@ -0,0 +1,32 @@
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
import { extractText } from './lib/actions/extract-text';
import { convertToImage } from './lib/actions/convert-to-image';
import { textToPdf } from './lib/actions/text-to-pdf';
import { imageToPdf } from './lib/actions/image-to-pdf';
import { pdfPageCount } from './lib/actions/pdf-page-count';
import { extractPdfPages } from './lib/actions/extract-pdf-pages';
import { mergePdfs } from './lib/actions/merge-pdfs';
export const PDF = createPiece({
displayName: 'PDF',
auth: PieceAuth.None(),
minimumSupportedRelease: '0.34.2',
logoUrl: 'https://cdn.activepieces.com/pieces/pdf.svg',
authors: [
'nyamkamunhjin',
'abuaboud',
'AbdulTheActivepiecer',
'jmgb27',
'danielpoonwj',
],
actions: [
extractText,
convertToImage,
textToPdf,
imageToPdf,
pdfPageCount,
extractPdfPages,
mergePdfs,
],
triggers: [],
});

View File

@@ -0,0 +1,133 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { promises as fs } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import { nanoid } from 'nanoid';
import Jimp from 'jimp';
const execPromise = promisify(exec);
const pdftoppmPath = '/usr/bin/pdftoppm';
const MAX_FILE_SIZE = 16 * 1024 * 1024;
async function isPdftoppmInstalled(): Promise<boolean> {
const { stdout, stderr } = await execPromise(`command -v ${pdftoppmPath}`);
return !stderr && stdout.trim() === pdftoppmPath;
}
async function convertPdfToImages(dataBuffer: Buffer): Promise<Buffer[]> {
const tempDir = tmpdir();
const uniqueId = nanoid();
const inputFilePath = join(tempDir, `input-${uniqueId}.pdf`);
const outputDir = join(tempDir, `output-${uniqueId}`);
try {
await fs.mkdir(outputDir);
await fs.writeFile(inputFilePath, dataBuffer as any);
const { stderr } = await execPromise(`${pdftoppmPath} -png ${inputFilePath} ${join(outputDir, 'output')}`);
if (stderr) {
throw new Error(stderr);
}
const files = await fs.readdir(outputDir);
const imageBuffers = [];
for (const file of files) {
const filePath = join(outputDir, file);
const imageBuffer = await fs.readFile(filePath);
await fs.unlink(filePath);
imageBuffers.push(imageBuffer);
}
return imageBuffers;
} finally {
await fs.unlink(inputFilePath).catch(() => void 0);
await fs.rm(outputDir, { recursive: true, force: true }).catch(() => void 0);
}
}
async function concatImagesVertically(imageBuffers: Buffer[]): Promise<Buffer> {
const images = await Promise.all(imageBuffers.map(buffer => Jimp.read(buffer)));
const totalHeight = images.reduce((sum, image) => sum + image.getHeight(), 0);
const maxWidth = Math.max(...images.map(image => image.getWidth()));
const finalImage = new Jimp(maxWidth, totalHeight);
let yOffset = 0;
for (const image of images) {
finalImage.composite(image, 0, yOffset);
yOffset += image.getHeight();
}
return finalImage.getBufferAsync(Jimp.MIME_PNG);
}
export const convertToImage = createAction({
name: 'convertToImage',
displayName: 'Convert to Image',
description: 'Convert a PDF file or URL to an image',
props: {
file: Property.File({
displayName: 'PDF File or URL',
required: true,
}),
imageOutputType: Property.StaticDropdown({
displayName: 'Output Image Type',
required: true,
options: {
options: [
{ label: 'Single Combined Image', value: 'single' },
{ label: 'Separate Image for Each Page', value: 'multiple' },
],
},
defaultValue: 'multiple',
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true
},
},
async run(context) {
if (!await isPdftoppmInstalled()) {
throw new Error(`${pdftoppmPath} is not installed`);
}
const file = context.propsValue.file;
const returnConcatenatedImage = context.propsValue.imageOutputType === 'single';
// To prevent a DOS attack, we limit the file size to 16MB
if (file.data.buffer.byteLength > MAX_FILE_SIZE) {
throw new Error(`File size exceeds the limit of ${MAX_FILE_SIZE / (1024 * 1024)} MB.`);
}
const dataBuffer = Buffer.from(file.data.buffer);
const imageBuffers = await convertPdfToImages(dataBuffer);
if (returnConcatenatedImage) {
const finalImageBuffer = await concatImagesVertically(imageBuffers);
const imageLink = await context.files.write({
data: finalImageBuffer,
fileName: `converted_image.png`,
});
return {
image: imageLink,
};
} else {
const imageLinks = await Promise.all(imageBuffers.map((imageBuffer, index) =>
context.files.write({
data: imageBuffer,
fileName: `converted_image_page_${index + 1}.png`,
})
));
return {
images: imageLinks,
};
}
},
});

View File

@@ -0,0 +1,123 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { PDFDocument } from 'pdf-lib';
import { MarkdownVariant } from '@activepieces/shared';
export function pageRangeToIndexes(
startPage: number,
endPage: number,
totalPages: number
) {
if (startPage > endPage) {
throw Error(
`Range start (${startPage}) has to be less than range end (${endPage})`
);
}
if (startPage === 0 || endPage === 0) {
throw Error('Range start/end has to be a non-zero number');
}
if (startPage > totalPages || endPage > totalPages) {
throw Error(
'Range start/end has to be less or equal to the total number of pages'
);
}
if (startPage < 0 && endPage > 0) {
throw Error('Range start cannot be negative when end is positive');
}
// page is 1 indexed, handle positive case
let startIndex = startPage - 1;
// handle negative case
if (startPage < 0) {
startIndex = totalPages + startPage;
}
// page is 1 indexed, handle positive case
let endIndex = endPage - 1;
// handle negative case
if (endPage < 0) {
endIndex = totalPages + endPage;
}
return Array.from(
{ length: endIndex - startIndex + 1 },
(_, idx) => startIndex + idx
);
}
const markdownValue = `
This action can extract or rearrange the pages in a PDF.
- The order of array determines the sequence of pages.
- Each array element is one inclusive continuous range with a start page and end page.
- Pages start from 1, and 0 is not valid.
- Start page has to be less than end page.
- You can select one page by setting the same start and end page.
- To select pages from the start, specify negative pages eg. -1 is the last page, -5 is the 5th last page. start: -5, end: -1 are the last 5 pages.
- Range cannot span across 0 eg. start: -3, end: 5.
`;
export const extractPdfPages = createAction({
name: 'extractPdfPages',
displayName: 'Extract PDF Pages',
description: 'Extract or rearrange page(s)from PDF File.',
props: {
markdown: Property.MarkDown({
variant: MarkdownVariant.INFO,
value: markdownValue,
}),
file: Property.File({
displayName: 'PDF File or URL',
required: true,
}),
pageRanges: Property.Array({
displayName: 'Page Ranges',
properties: {
startPage: Property.Number({
displayName: 'Start Page',
required: true,
}),
endPage: Property.Number({
displayName: 'End Page',
required: true,
}),
},
required: true,
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true,
},
},
async run(context) {
try {
const srcDoc = await PDFDocument.load(context.propsValue.file.data as any);
const totalPages = srcDoc.getPageCount();
const pageIndexes = context.propsValue.pageRanges.flatMap(
(pageRange: any) =>
pageRangeToIndexes(pageRange.startPage, pageRange.endPage, totalPages)
);
const newDoc = await PDFDocument.create();
const newPages = await newDoc.copyPages(srcDoc, pageIndexes);
newPages.forEach((newPage) => newDoc.addPage(newPage));
const pdfBytes = await newDoc.save();
const base64Pdf = Buffer.from(pdfBytes).toString('base64');
return context.files.write({
data: Buffer.from(base64Pdf, 'base64'),
fileName: context.propsValue.file.filename,
});
} catch (error) {
throw new Error(`Failed to extract pages: ${(error as Error).message}`);
}
},
});

View File

@@ -0,0 +1,28 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import pdfParse from 'pdf-parse';
export const extractText = createAction({
name: 'extractText',
displayName: 'Extract Text',
description: 'Extract text from PDF file or url',
props: {
file: Property.File({
displayName: 'PDF File or URL',
required: true,
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true
},
},
async run(context) {
const file = context.propsValue.file;
const dataBuffer = Buffer.from(file.data.buffer);
const pdfData = await pdfParse(dataBuffer);
return pdfData.text;
},
});

View File

@@ -0,0 +1,210 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { PDFDocument, PDFImage, RotationTypes, PageSizes } from 'pdf-lib';
export const imageToPdf = createAction({
name: 'imageToPdf',
displayName: 'Image to PDF',
description: 'Convert image to PDF',
props: {
image: Property.File({
displayName: 'image',
description:
'Image has to be png, jpeg or jpg and it will be scaled down to fit the page when image is larger than an A4 page',
required: true,
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true,
},
},
async run(context) {
try {
const image = context.propsValue.image;
const imageExtension = image.extension?.toLowerCase();
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage();
const [pageWidth, pageHeight] = PageSizes.A4;
page.setSize(pageWidth, pageHeight);
const xMargin = 30;
const yMargin = 30;
const [maxCardWidth, maxCardHeight] = [pageWidth - xMargin * 2, pageHeight - yMargin * 2];
let result: PDFImage | null = null;
if (imageExtension === 'png') {
result = await pdfDoc.embedPng(image.data as any);
} else if (imageExtension === 'jpg' || imageExtension === 'jpeg') {
result = await pdfDoc.embedJpg(image.data as any);
} else {
throw new Error(`Unsupported image format: ${imageExtension}`);
}
if (result === null) {
throw new Error('Failed to embed image');
}
const exifOrientation = getImageOrientation(image.data.buffer as any);
const orientationCorrection = getOrientationCorrection(exifOrientation);
let scaledImage, correctedWidth, correctedHeight;
switch (exifOrientation) {
case ImageOrientation.FlipHorizontalRotate90:
case ImageOrientation.Rotate90:
case ImageOrientation.FlipVerticalRotate90:
case ImageOrientation.Rotate270:
// The uploaded image is rotated +/- 90 degrees
scaledImage = result.scaleToFit(maxCardHeight, maxCardWidth);
correctedWidth = scaledImage.height;
correctedHeight = scaledImage.width;
break;
default:
scaledImage = result.scaleToFit(maxCardWidth, maxCardHeight);
correctedWidth = scaledImage.width;
correctedHeight = scaledImage.height;
}
let xShift, yShift;
const yOffset = pageHeight - yMargin;
switch (exifOrientation) {
case ImageOrientation.FlipHorizontal:
xShift = pageWidth - xMargin - correctedWidth;
yShift = yOffset - correctedHeight;
break;
case ImageOrientation.Rotate180:
xShift = xMargin + correctedWidth;
yShift = yOffset;
break;
case ImageOrientation.FlipVertical:
xShift = pageWidth - xMargin;
yShift = yOffset;
break;
case ImageOrientation.FlipHorizontalRotate90:
xShift = xMargin + correctedWidth;
yShift = pageHeight - yOffset;
break;
case ImageOrientation.Rotate90:
xShift = xMargin;
yShift = yOffset;
break;
case ImageOrientation.FlipVerticalRotate90:
xShift = xMargin;
yShift = pageHeight - yOffset + correctedHeight;
break;
case ImageOrientation.Rotate270:
xShift = xMargin + correctedWidth;
yShift = yOffset - correctedHeight;
break;
default:
xShift = xMargin;
yShift = yOffset - correctedHeight;
}
page.drawImage(result, {
x: xShift,
y: yShift,
height: scaledImage.height,
width: scaledImage.width,
rotate: { angle: orientationCorrection.degrees, type: RotationTypes.Degrees },
});
const pdfBytes = await pdfDoc.save();
const base64Pdf = Buffer.from(pdfBytes).toString('base64');
return context.files.write({
data: Buffer.from(base64Pdf, 'base64'),
fileName: `${image.filename}.pdf`,
});
} catch (error) {
throw new Error(`Failed to convert text to PDF: ${(error as Error).message}`);
}
},
});
// https://sirv.com/help/articles/rotate-photos-to-be-upright/#exif-orientation-values
enum ImageOrientation {
Normal = 1, // "Image is in normal orientation, no rotation or flipping"
Rotate90 = 6, // "Image is rotated 90 degrees"
Rotate180 = 3, // "Image is rotated 180 degrees"
Rotate270 = 8, // "Image is rotated 270 degrees"
FlipHorizontal = 2, // "Image is flipped horizontally"
FlipVertical = 4, // "Image is flipped horizontally and rotated 180 degrees"
FlipHorizontalRotate90 = 5, // "Image is rotated 90 degrees and flipped horizontally"
FlipVerticalRotate90 = 7, // "Image is rotated 270 degrees and flipped horizontally"
Unknown= -1
}
// https://github.com/Hopding/pdf-lib/issues/1284
// https://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side/32490603#32490603
function getImageOrientation(file: ArrayBuffer): ImageOrientation {
const view = new DataView(file);
const length = view.byteLength;
let offset = 2;
while (offset < length) {
if (view.getUint16(offset + 2, false) <= 8) return ImageOrientation.Unknown;
const marker = view.getUint16(offset, false);
offset += 2;
// If EXIF buffer segment exists find the orientation
if (marker == 0xffe1) {
if (view.getUint32((offset += 2), false) != 0x45786966) {
return ImageOrientation.Unknown;
}
const little = view.getUint16((offset += 6), false) == 0x4949;
offset += view.getUint32(offset + 4, little);
const tags = view.getUint16(offset, little);
offset += 2;
for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + i * 12, little) == 0x0112) {
const orientation = view.getUint16(offset + i * 12 + 8, little);
switch (orientation) {
case 1: return ImageOrientation.Normal;
case 3: return ImageOrientation.Rotate180;
case 6: return ImageOrientation.Rotate90;
case 8: return ImageOrientation.Rotate270;
case 2: return ImageOrientation.FlipHorizontal;
case 4: return ImageOrientation.FlipVertical;
case 5: return ImageOrientation.FlipHorizontalRotate90;
case 7: return ImageOrientation.FlipVerticalRotate90;
default: return ImageOrientation.Unknown;
}
}
}
} else if ((marker & 0xff00) != 0xff00) {
break;
} else {
offset += view.getUint16(offset, false);
}
}
return ImageOrientation.Unknown;
}
function getOrientationCorrection(orientation: number): { degrees: number; mirrored?: 'x' | 'y' } {
switch (orientation) {
case ImageOrientation.FlipHorizontal:
return { degrees: 0, mirrored: 'x' };
case ImageOrientation.Rotate180:
return { degrees: -180 };
case ImageOrientation.FlipVertical:
return { degrees: 180, mirrored: 'x' };
case ImageOrientation.FlipHorizontalRotate90:
return { degrees: 90, mirrored: 'y' };
case ImageOrientation.Rotate90:
return { degrees: -90 };
case ImageOrientation.FlipVerticalRotate90:
return { degrees: -90, mirrored: 'y' };
case ImageOrientation.Rotate270:
return { degrees: 90 };
default:
return { degrees: 0 };
}
}

View File

@@ -0,0 +1,101 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { PDFDocument } from 'pdf-lib';
export const mergePdfs = createAction({
name: 'mergePdfs',
displayName: 'Merge PDFs',
description: 'Merges multiple PDF files into a single PDF document.',
props: {
pdfFiles: Property.Array({
displayName: 'PDF Files',
description: 'Array of PDF files to merge',
required: true,
properties: {
file: Property.File({
displayName: 'PDF File',
required: true,
}),
},
}),
outputFileName: Property.ShortText({
displayName: 'Output File Name',
description: 'Name for the merged PDF file (without extension)',
required: false,
defaultValue: 'merged-document',
}),
},
async run(context) {
try {
const { pdfFiles, outputFileName } = context.propsValue;
// pdfFiles is already an array from Property.Array
if (!pdfFiles || !Array.isArray(pdfFiles) || pdfFiles.length < 2) {
throw new Error('At least 2 PDF files are required for merging');
}
const mergedPdf = await PDFDocument.create();
for (let i = 0; i < pdfFiles.length; i++) {
const fileItem = pdfFiles[i] as any;
const file = fileItem.file;
if (!file) {
throw new Error(`File at index ${i} is null or undefined`);
}
// Handle PDF files only
let fileData: Buffer;
const fileName = file.filename || file.name || `file-${i}.pdf`;
// Validate it's a PDF file
if (fileName && !fileName.toLowerCase().endsWith('.pdf')) {
throw new Error(`File at index ${i} (${fileName}) is not a PDF file`);
}
if (file.data) {
// Handle base64 strings
if (typeof file.data === 'string') {
fileData = Buffer.from(file.data, 'base64');
}
// Handle Buffer objects serialized as JSON
else if (file.data.type === 'Buffer' && Array.isArray(file.data.data)) {
fileData = Buffer.from(file.data.data);
}
// Handle direct Buffer
else if (Buffer.isBuffer(file.data)) {
fileData = file.data;
}
else {
throw new Error(`Unsupported data format for PDF file ${i}: ${typeof file.data}`);
}
}
else {
throw new Error(`PDF file at index ${i} has no data property`);
}
try {
const pdfDoc = await PDFDocument.load(new Uint8Array(fileData));
const pageCount = pdfDoc.getPageCount();
const pageIndices = Array.from({ length: pageCount }, (_, idx) => idx);
const copiedPages = await mergedPdf.copyPages(pdfDoc, pageIndices);
copiedPages.forEach((page) => mergedPdf.addPage(page));
} catch (error) {
throw new Error(`Failed to process PDF file at index ${i} (${fileName}): ${(error as Error).message}`);
}
}
const pdfBytes = await mergedPdf.save();
return context.files.write({
data: Buffer.from(pdfBytes),
fileName: `${outputFileName || 'merged-document'}.pdf`,
});
} catch (error) {
throw new Error(`Failed to merge PDFs: ${(error as Error).message}`);
}
},
});

View File

@@ -0,0 +1,30 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { PDFDocument } from 'pdf-lib';
export const pdfPageCount = createAction({
name: 'pdfPageCount',
displayName: 'PDF Page Count',
description: 'Get page count of PDF file.',
props: {
file: Property.File({
displayName: 'PDF File or URL',
required: true,
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true,
},
},
async run({ propsValue }) {
try {
const pdfDoc = await PDFDocument.load(propsValue.file.data as any);
return pdfDoc.getPageCount();
} catch (error) {
throw new Error(`Failed to get page count: ${(error as Error).message}`);
}
},
});

View File

@@ -0,0 +1,103 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { PDFDocument, StandardFonts } from 'pdf-lib';
export const textToPdf = createAction({
name: 'textToPdf',
displayName: 'Text to PDF',
description: 'Convert text to PDF',
props: {
text: Property.LongText({
displayName: 'text',
description: 'Enter text to convert',
required: true,
}),
},
errorHandlingOptions: {
continueOnFailure: {
defaultValue: false,
},
retryOnFailure: {
hide: true,
},
},
async run(context) {
const text = context.propsValue.text;
const pageSize: [number, number] = [595, 842]; // Standard A4 size
const margin = 50;
const topMargin = 70;
const fontSize = 12;
const lineSpacing = 5;
const paragraphSpacing = 8;
const fontType: StandardFonts = StandardFonts.Helvetica;
try {
const pdfDoc = await PDFDocument.create();
let page = pdfDoc.addPage(pageSize);
const { width, height } = page.getSize();
const font = await pdfDoc.embedFont(fontType);
const lineHeight = font.heightAtSize(fontSize) + lineSpacing;
const maxWidth = width - margin * 2;
const paragraphs = text.split('\n');
let yPosition = height - topMargin;
paragraphs.forEach((paragraph) => {
const words = paragraph.split(' ');
let line = '';
words.forEach((word) => {
const testLine = line + word + ' ';
const testLineWidth = font.widthOfTextAtSize(testLine, fontSize);
if (testLineWidth > maxWidth) {
page.drawText(line.trim(), {
x: margin,
y: yPosition,
size: fontSize,
font,
});
line = word + ' ';
yPosition -= lineHeight;
if (yPosition < margin + lineHeight) {
page = pdfDoc.addPage(pageSize);
yPosition = height - topMargin;
}
} else {
line = testLine;
}
});
if (line.trim()) {
page.drawText(line.trim(), {
x: margin,
y: yPosition,
size: fontSize,
font,
});
yPosition -= lineHeight;
}
yPosition -= paragraphSpacing;
if (yPosition < margin + lineHeight) {
page = pdfDoc.addPage(pageSize);
yPosition = height - topMargin;
}
});
const pdfBytes = await pdfDoc.save();
const base64Pdf = Buffer.from(pdfBytes).toString('base64');
return context.files.write({
data: Buffer.from(base64Pdf, 'base64'),
fileName: 'text.pdf',
});
} catch (error) {
throw new Error(`Failed to convert text to PDF: ${(error as Error).message}`);
}
},
});