@capgo/capacitor-pdf-generator 7.0.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.
@@ -0,0 +1,17 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapgoCapacitorPdfGenerator'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '14.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Capgo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/Package.swift ADDED
@@ -0,0 +1,28 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "CapgoCapacitorPdfGenerator",
6
+ platforms: [.iOS(.v14)],
7
+ products: [
8
+ .library(
9
+ name: "CapgoCapacitorPdfGenerator",
10
+ targets: ["PdfGeneratorPlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
14
+ ],
15
+ targets: [
16
+ .target(
17
+ name: "PdfGeneratorPlugin",
18
+ dependencies: [
19
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
20
+ .product(name: "Cordova", package: "capacitor-swift-pm")
21
+ ],
22
+ path: "ios/Sources/PdfGeneratorPlugin"),
23
+ .testTarget(
24
+ name: "PdfGeneratorPluginTests",
25
+ dependencies: ["PdfGeneratorPlugin"],
26
+ path: "ios/Tests/PdfGeneratorPluginTests")
27
+ ]
28
+ )
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # @capgo/capacitor-pdf-generator
2
+ <a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
3
+
4
+ <div align="center">
5
+ <h2><a href="https://capgo.app/?ref=plugin"> ➡️ Get Instant updates for your App with Capgo</a></h2>
6
+ <h2><a href="https://capgo.app/consulting/?ref=plugin"> Missing a feature? We’ll build the plugin for you 💪</a></h2>
7
+ </div>
8
+
9
+
10
+ Generate PDF files from HTML strings or remote URLs.
11
+
12
+ Port of the Cordova [pdf-generator](https://github.com/feedhenry-staff/pdf-generator) plugin for Capacitor with a modernized native implementation.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @capgo/capacitor-pdf-generator
18
+ npx cap sync
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```ts
24
+ import { PdfGenerator } from '@capgo/capacitor-pdf-generator';
25
+
26
+ const result = await PdfGenerator.fromData({
27
+ data: '<html><body><h1>Hello Capgo</h1></body></html>',
28
+ documentSize: 'A4',
29
+ orientation: 'portrait',
30
+ type: 'base64',
31
+ fileName: 'example.pdf',
32
+ });
33
+
34
+ if (result.type === 'base64') {
35
+ console.log(result.base64);
36
+ }
37
+ ```
38
+
39
+ ## API
40
+
41
+ <docgen-index>
42
+
43
+ * [`fromURL(...)`](#fromurl)
44
+ * [`fromData(...)`](#fromdata)
45
+ * [Interfaces](#interfaces)
46
+ * [Type Aliases](#type-aliases)
47
+
48
+ </docgen-index>
49
+
50
+ <docgen-api>
51
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
52
+
53
+ ### fromURL(...)
54
+
55
+ ```typescript
56
+ fromURL(options: PdfGeneratorFromUrlOptions) => Promise<PdfGeneratorResult>
57
+ ```
58
+
59
+ Generates a PDF from the provided URL.
60
+
61
+ | Param | Type |
62
+ | ------------- | --------------------------------------------------------------------------------- |
63
+ | **`options`** | <code><a href="#pdfgeneratorfromurloptions">PdfGeneratorFromUrlOptions</a></code> |
64
+
65
+ **Returns:** <code>Promise&lt;<a href="#pdfgeneratorresult">PdfGeneratorResult</a>&gt;</code>
66
+
67
+ --------------------
68
+
69
+
70
+ ### fromData(...)
71
+
72
+ ```typescript
73
+ fromData(options: PdfGeneratorFromDataOptions) => Promise<PdfGeneratorResult>
74
+ ```
75
+
76
+ Generates a PDF from a raw HTML string.
77
+
78
+ | Param | Type |
79
+ | ------------- | ----------------------------------------------------------------------------------- |
80
+ | **`options`** | <code><a href="#pdfgeneratorfromdataoptions">PdfGeneratorFromDataOptions</a></code> |
81
+
82
+ **Returns:** <code>Promise&lt;<a href="#pdfgeneratorresult">PdfGeneratorResult</a>&gt;</code>
83
+
84
+ --------------------
85
+
86
+
87
+ ### Interfaces
88
+
89
+
90
+ #### PdfGeneratorFromUrlOptions
91
+
92
+ | Prop | Type |
93
+ | --------- | ------------------- |
94
+ | **`url`** | <code>string</code> |
95
+
96
+
97
+ #### PdfGeneratorFromDataOptions
98
+
99
+ | Prop | Type | Description |
100
+ | ------------- | ------------------- | -------------------------------------------------------------------------------------------------------------- |
101
+ | **`data`** | <code>string</code> | HTML document to render. |
102
+ | **`baseUrl`** | <code>string</code> | Base URL to use when resolving relative resources inside the HTML string. When omitted, `about:blank` is used. |
103
+
104
+
105
+ ### Type Aliases
106
+
107
+
108
+ #### PdfGeneratorResult
109
+
110
+ <code>{ type: 'base64'; base64: string; } | { type: 'share'; completed: boolean; }</code>
111
+
112
+ </docgen-api>
@@ -0,0 +1,57 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
6
+ }
7
+
8
+ buildscript {
9
+ repositories {
10
+ google()
11
+ mavenCentral()
12
+ }
13
+ dependencies {
14
+ classpath 'com.android.tools.build:gradle:8.7.2'
15
+ }
16
+ }
17
+
18
+ apply plugin: 'com.android.library'
19
+
20
+ android {
21
+ namespace "app.capgo.pdfgenerator"
22
+ compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
23
+ defaultConfig {
24
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
25
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
26
+ versionCode 1
27
+ versionName "1.0"
28
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
29
+ }
30
+ buildTypes {
31
+ release {
32
+ minifyEnabled false
33
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
34
+ }
35
+ }
36
+ lintOptions {
37
+ abortOnError false
38
+ }
39
+ compileOptions {
40
+ sourceCompatibility JavaVersion.VERSION_21
41
+ targetCompatibility JavaVersion.VERSION_21
42
+ }
43
+ }
44
+
45
+ repositories {
46
+ google()
47
+ mavenCentral()
48
+ }
49
+
50
+ dependencies {
51
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
52
+ implementation project(':capacitor-android')
53
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
54
+ testImplementation "junit:junit:$junitVersion"
55
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
56
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
57
+ }
@@ -0,0 +1,13 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <application>
3
+ <provider
4
+ android:name="androidx.core.content.FileProvider"
5
+ android:authorities="${applicationId}.capgo.pdfgenerator.fileprovider"
6
+ android:exported="false"
7
+ android:grantUriPermissions="true">
8
+ <meta-data
9
+ android:name="android.support.FILE_PROVIDER_PATHS"
10
+ android:resource="@xml/capgo_pdf_generator_paths" />
11
+ </provider>
12
+ </application>
13
+ </manifest>
@@ -0,0 +1,210 @@
1
+ package android.print;
2
+
3
+ import android.content.Context;
4
+ import android.os.CancellationSignal;
5
+ import android.os.ParcelFileDescriptor;
6
+ import android.util.Base64;
7
+ import androidx.annotation.NonNull;
8
+ import java.io.ByteArrayOutputStream;
9
+ import java.io.File;
10
+ import java.io.FileInputStream;
11
+
12
+ /**
13
+ * Internal helpers to generate PDF output from a PrintDocumentAdapter without relying on
14
+ * platform print dialogs. Located inside the {@code android.print} package so we can access
15
+ * the package-private constructors of the framework callbacks.
16
+ */
17
+ public final class CapgoPdfPrintUtils {
18
+
19
+ private CapgoPdfPrintUtils() {}
20
+
21
+ public interface Base64Callback {
22
+ void onSuccess(@NonNull String base64);
23
+ void onError(@NonNull String message);
24
+ }
25
+
26
+ public interface FileCallback {
27
+ void onSuccess(@NonNull File file);
28
+ void onError(@NonNull String message);
29
+ }
30
+
31
+ public static void createBase64(
32
+ Context context,
33
+ PrintDocumentAdapter adapter,
34
+ PrintAttributes attributes,
35
+ Base64Callback callback
36
+ ) {
37
+ Writer writer = new Writer(adapter, attributes);
38
+ writer.writeToTempFile(
39
+ context,
40
+ new Writer.FileResultCallback() {
41
+ @Override
42
+ public void onSuccess(@NonNull File file, @NonNull ParcelFileDescriptor descriptor) {
43
+ new Thread(
44
+ () -> {
45
+ try {
46
+ String base64 = PdfIoUtils.readBase64(file);
47
+ callback.onSuccess(base64);
48
+ } catch (Exception ex) {
49
+ callback.onError("Failed to convert PDF to base64.");
50
+ } finally {
51
+ PdfIoUtils.closeQuietly(descriptor);
52
+ // best-effort cleanup
53
+ //noinspection ResultOfMethodCallIgnored
54
+ file.delete();
55
+ }
56
+ }
57
+ )
58
+ .start();
59
+ }
60
+
61
+ @Override
62
+ public void onError(@NonNull String message) {
63
+ callback.onError(message);
64
+ }
65
+ }
66
+ );
67
+ }
68
+
69
+ public static void writeToFile(
70
+ Context context,
71
+ PrintDocumentAdapter adapter,
72
+ PrintAttributes attributes,
73
+ File target,
74
+ FileCallback callback
75
+ ) {
76
+ Writer writer = new Writer(adapter, attributes);
77
+ writer.writeToFile(
78
+ context,
79
+ target,
80
+ new Writer.FileResultCallback() {
81
+ @Override
82
+ public void onSuccess(@NonNull File file, @NonNull ParcelFileDescriptor descriptor) {
83
+ PdfIoUtils.closeQuietly(descriptor);
84
+ callback.onSuccess(file);
85
+ }
86
+
87
+ @Override
88
+ public void onError(@NonNull String message) {
89
+ callback.onError(message);
90
+ }
91
+ }
92
+ );
93
+ }
94
+
95
+ private static final class Writer {
96
+
97
+ interface FileResultCallback {
98
+ void onSuccess(@NonNull File file, @NonNull ParcelFileDescriptor descriptor);
99
+ void onError(@NonNull String message);
100
+ }
101
+
102
+ private static final PageRange[] ALL_PAGES = new PageRange[] { PageRange.ALL_PAGES };
103
+
104
+ private final PrintDocumentAdapter adapter;
105
+ private final PrintAttributes attributes;
106
+
107
+ Writer(PrintDocumentAdapter adapter, PrintAttributes attributes) {
108
+ this.adapter = adapter;
109
+ this.attributes = attributes;
110
+ }
111
+
112
+ void writeToTempFile(Context context, FileResultCallback callback) {
113
+ try {
114
+ File tempFile = File.createTempFile("capgo_pdf_generator", ".pdf", context.getCacheDir());
115
+ writeToDescriptor(tempFile, callback);
116
+ } catch (Exception ex) {
117
+ callback.onError("Failed to create temporary file for PDF.");
118
+ }
119
+ }
120
+
121
+ void writeToFile(Context context, File file, FileResultCallback callback) {
122
+ try {
123
+ if (file.exists() && !file.delete()) {
124
+ callback.onError("Failed to override existing PDF file.");
125
+ return;
126
+ }
127
+ File parent = file.getParentFile();
128
+ if (parent != null && !parent.exists() && !parent.mkdirs()) {
129
+ callback.onError("Failed to prepare output directory for PDF.");
130
+ return;
131
+ }
132
+ writeToDescriptor(file, callback);
133
+ } catch (Exception ex) {
134
+ callback.onError("Failed to prepare PDF output file.");
135
+ }
136
+ }
137
+
138
+ private void writeToDescriptor(File file, FileResultCallback callback) {
139
+ try {
140
+ ParcelFileDescriptor descriptor = ParcelFileDescriptor.open(
141
+ file,
142
+ ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_TRUNCATE
143
+ );
144
+ CancellationSignal cancellationSignal = new CancellationSignal();
145
+ adapter.onLayout(
146
+ null,
147
+ attributes,
148
+ cancellationSignal,
149
+ new PrintDocumentAdapter.LayoutResultCallback() {
150
+ @Override
151
+ public void onLayoutFailed(CharSequence error) {
152
+ callback.onError("PDF layout failed: " + (error == null ? "" : error));
153
+ }
154
+
155
+ @Override
156
+ public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
157
+ adapter.onWrite(
158
+ ALL_PAGES,
159
+ descriptor,
160
+ cancellationSignal,
161
+ new PrintDocumentAdapter.WriteResultCallback() {
162
+ @Override
163
+ public void onWriteFinished(PageRange[] pages) {
164
+ callback.onSuccess(file, descriptor);
165
+ }
166
+
167
+ @Override
168
+ public void onWriteFailed(CharSequence error) {
169
+ callback.onError("PDF write failed: " + (error == null ? "" : error));
170
+ }
171
+ }
172
+ );
173
+ }
174
+ },
175
+ null
176
+ );
177
+ } catch (Exception ex) {
178
+ callback.onError("Failed to create PDF output.");
179
+ }
180
+ }
181
+ }
182
+
183
+ private static final class PdfIoUtils {
184
+
185
+ private PdfIoUtils() {}
186
+
187
+ static String readBase64(File file) throws Exception {
188
+ FileInputStream inputStream = new FileInputStream(file);
189
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
190
+ byte[] buffer = new byte[8192];
191
+ int read;
192
+ while ((read = inputStream.read(buffer)) != -1) {
193
+ outputStream.write(buffer, 0, read);
194
+ }
195
+ return Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP);
196
+ } finally {
197
+ inputStream.close();
198
+ }
199
+ }
200
+
201
+ static void closeQuietly(ParcelFileDescriptor descriptor) {
202
+ if (descriptor == null) {
203
+ return;
204
+ }
205
+ try {
206
+ descriptor.close();
207
+ } catch (Exception ignored) {}
208
+ }
209
+ }
210
+ }