@lexmata/micropdf 0.4.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.
Files changed (170) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +985 -0
  3. package/binding.gyp +73 -0
  4. package/dist/annot.d.ts +458 -0
  5. package/dist/annot.d.ts.map +1 -0
  6. package/dist/annot.js +697 -0
  7. package/dist/annot.js.map +1 -0
  8. package/dist/archive.d.ts +128 -0
  9. package/dist/archive.d.ts.map +1 -0
  10. package/dist/archive.js +268 -0
  11. package/dist/archive.js.map +1 -0
  12. package/dist/buffer.d.ts +572 -0
  13. package/dist/buffer.d.ts.map +1 -0
  14. package/dist/buffer.js +971 -0
  15. package/dist/buffer.js.map +1 -0
  16. package/dist/colorspace.d.ts +287 -0
  17. package/dist/colorspace.d.ts.map +1 -0
  18. package/dist/colorspace.js +542 -0
  19. package/dist/colorspace.js.map +1 -0
  20. package/dist/context.d.ts +184 -0
  21. package/dist/context.d.ts.map +1 -0
  22. package/dist/context.js +320 -0
  23. package/dist/context.js.map +1 -0
  24. package/dist/cookie.d.ts +164 -0
  25. package/dist/cookie.d.ts.map +1 -0
  26. package/dist/cookie.js +306 -0
  27. package/dist/cookie.js.map +1 -0
  28. package/dist/device.d.ts +169 -0
  29. package/dist/device.d.ts.map +1 -0
  30. package/dist/device.js +350 -0
  31. package/dist/device.js.map +1 -0
  32. package/dist/display-list.d.ts +202 -0
  33. package/dist/display-list.d.ts.map +1 -0
  34. package/dist/display-list.js +410 -0
  35. package/dist/display-list.js.map +1 -0
  36. package/dist/document.d.ts +637 -0
  37. package/dist/document.d.ts.map +1 -0
  38. package/dist/document.js +902 -0
  39. package/dist/document.js.map +1 -0
  40. package/dist/easy.d.ts +423 -0
  41. package/dist/easy.d.ts.map +1 -0
  42. package/dist/easy.js +644 -0
  43. package/dist/easy.js.map +1 -0
  44. package/dist/enhanced.d.ts +226 -0
  45. package/dist/enhanced.d.ts.map +1 -0
  46. package/dist/enhanced.js +368 -0
  47. package/dist/enhanced.js.map +1 -0
  48. package/dist/filter.d.ts +51 -0
  49. package/dist/filter.d.ts.map +1 -0
  50. package/dist/filter.js +381 -0
  51. package/dist/filter.js.map +1 -0
  52. package/dist/font.d.ts +222 -0
  53. package/dist/font.d.ts.map +1 -0
  54. package/dist/font.js +381 -0
  55. package/dist/font.js.map +1 -0
  56. package/dist/form.d.ts +214 -0
  57. package/dist/form.d.ts.map +1 -0
  58. package/dist/form.js +497 -0
  59. package/dist/form.js.map +1 -0
  60. package/dist/geometry.d.ts +469 -0
  61. package/dist/geometry.d.ts.map +1 -0
  62. package/dist/geometry.js +780 -0
  63. package/dist/geometry.js.map +1 -0
  64. package/dist/image.d.ts +172 -0
  65. package/dist/image.d.ts.map +1 -0
  66. package/dist/image.js +348 -0
  67. package/dist/image.js.map +1 -0
  68. package/dist/index.d.ts +171 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +339 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/link.d.ts +168 -0
  73. package/dist/link.d.ts.map +1 -0
  74. package/dist/link.js +343 -0
  75. package/dist/link.js.map +1 -0
  76. package/dist/micropdf.d.ts +40 -0
  77. package/dist/micropdf.d.ts.map +1 -0
  78. package/dist/micropdf.js +45 -0
  79. package/dist/micropdf.js.map +1 -0
  80. package/dist/nanopdf.d.ts +40 -0
  81. package/dist/nanopdf.d.ts.map +1 -0
  82. package/dist/nanopdf.js +45 -0
  83. package/dist/nanopdf.js.map +1 -0
  84. package/dist/native.d.ts +242 -0
  85. package/dist/native.d.ts.map +1 -0
  86. package/dist/native.js +509 -0
  87. package/dist/native.js.map +1 -0
  88. package/dist/output.d.ts +166 -0
  89. package/dist/output.d.ts.map +1 -0
  90. package/dist/output.js +365 -0
  91. package/dist/output.js.map +1 -0
  92. package/dist/path.d.ts +420 -0
  93. package/dist/path.d.ts.map +1 -0
  94. package/dist/path.js +687 -0
  95. package/dist/path.js.map +1 -0
  96. package/dist/pdf/object.d.ts +489 -0
  97. package/dist/pdf/object.d.ts.map +1 -0
  98. package/dist/pdf/object.js +1045 -0
  99. package/dist/pdf/object.js.map +1 -0
  100. package/dist/pixmap.d.ts +315 -0
  101. package/dist/pixmap.d.ts.map +1 -0
  102. package/dist/pixmap.js +590 -0
  103. package/dist/pixmap.js.map +1 -0
  104. package/dist/profiler.d.ts +159 -0
  105. package/dist/profiler.d.ts.map +1 -0
  106. package/dist/profiler.js +380 -0
  107. package/dist/profiler.js.map +1 -0
  108. package/dist/render-options.d.ts +227 -0
  109. package/dist/render-options.d.ts.map +1 -0
  110. package/dist/render-options.js +130 -0
  111. package/dist/render-options.js.map +1 -0
  112. package/dist/resource-tracking.d.ts +332 -0
  113. package/dist/resource-tracking.d.ts.map +1 -0
  114. package/dist/resource-tracking.js +653 -0
  115. package/dist/resource-tracking.js.map +1 -0
  116. package/dist/simple.d.ts +276 -0
  117. package/dist/simple.d.ts.map +1 -0
  118. package/dist/simple.js +343 -0
  119. package/dist/simple.js.map +1 -0
  120. package/dist/stext.d.ts +290 -0
  121. package/dist/stext.d.ts.map +1 -0
  122. package/dist/stext.js +312 -0
  123. package/dist/stext.js.map +1 -0
  124. package/dist/stream.d.ts +174 -0
  125. package/dist/stream.d.ts.map +1 -0
  126. package/dist/stream.js +476 -0
  127. package/dist/stream.js.map +1 -0
  128. package/dist/text.d.ts +337 -0
  129. package/dist/text.d.ts.map +1 -0
  130. package/dist/text.js +454 -0
  131. package/dist/text.js.map +1 -0
  132. package/dist/typed-arrays.d.ts +127 -0
  133. package/dist/typed-arrays.d.ts.map +1 -0
  134. package/dist/typed-arrays.js +410 -0
  135. package/dist/typed-arrays.js.map +1 -0
  136. package/dist/types.d.ts +358 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +216 -0
  139. package/dist/types.js.map +1 -0
  140. package/native/annot.cc +557 -0
  141. package/native/buffer.cc +204 -0
  142. package/native/colorspace.cc +166 -0
  143. package/native/context.cc +84 -0
  144. package/native/cookie.cc +179 -0
  145. package/native/device.cc +179 -0
  146. package/native/display_list.cc +179 -0
  147. package/native/document.cc +268 -0
  148. package/native/enhanced.cc +70 -0
  149. package/native/font.cc +282 -0
  150. package/native/form.cc +523 -0
  151. package/native/geometry.cc +255 -0
  152. package/native/image.cc +216 -0
  153. package/native/include/micropdf/enhanced.h +38 -0
  154. package/native/include/micropdf/types.h +36 -0
  155. package/native/include/micropdf.h +106 -0
  156. package/native/include/mupdf-ffi.h +39 -0
  157. package/native/include/mupdf.h +11 -0
  158. package/native/include/mupdf_minimal.h +381 -0
  159. package/native/lib/linux-x64/libmicropdf.a +0 -0
  160. package/native/link.cc +234 -0
  161. package/native/micropdf.cc +71 -0
  162. package/native/output.cc +229 -0
  163. package/native/page.cc +572 -0
  164. package/native/path.cc +259 -0
  165. package/native/pixmap.cc +240 -0
  166. package/native/stext.cc +610 -0
  167. package/native/stream.cc +239 -0
  168. package/package.json +120 -0
  169. package/scripts/build-from-rust.js +97 -0
  170. package/scripts/install.js +184 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * MicroPDF Buffer Bindings
3
+ *
4
+ * Node.js bindings for MicroPDF buffer operations.
5
+ */
6
+
7
+ #include <napi.h>
8
+ #include "include/micropdf.h"
9
+
10
+ /**
11
+ * Buffer class wrapper
12
+ */
13
+ class Buffer : public Napi::ObjectWrap<Buffer> {
14
+ public:
15
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
16
+ Buffer(const Napi::CallbackInfo& info);
17
+ ~Buffer();
18
+
19
+ private:
20
+ static Napi::FunctionReference constructor;
21
+ micropdf_buffer_t* buffer_;
22
+
23
+ // Methods
24
+ Napi::Value GetLength(const Napi::CallbackInfo& info);
25
+ Napi::Value GetData(const Napi::CallbackInfo& info);
26
+ Napi::Value Append(const Napi::CallbackInfo& info);
27
+ Napi::Value ToNodeBuffer(const Napi::CallbackInfo& info);
28
+
29
+ // Static methods
30
+ static Napi::Value FromNodeBuffer(const Napi::CallbackInfo& info);
31
+ static Napi::Value FromString(const Napi::CallbackInfo& info);
32
+ };
33
+
34
+ Napi::FunctionReference Buffer::constructor;
35
+
36
+ Napi::Object Buffer::Init(Napi::Env env, Napi::Object exports) {
37
+ Napi::HandleScope scope(env);
38
+
39
+ Napi::Function func = DefineClass(env, "Buffer", {
40
+ InstanceMethod("length", &Buffer::GetLength),
41
+ InstanceMethod("getData", &Buffer::GetData),
42
+ InstanceMethod("append", &Buffer::Append),
43
+ InstanceMethod("toBuffer", &Buffer::ToNodeBuffer),
44
+ StaticMethod("fromBuffer", &Buffer::FromNodeBuffer),
45
+ StaticMethod("fromString", &Buffer::FromString),
46
+ });
47
+
48
+ constructor = Napi::Persistent(func);
49
+ constructor.SuppressDestruct();
50
+
51
+ exports.Set("Buffer", func);
52
+ return exports;
53
+ }
54
+
55
+ Buffer::Buffer(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Buffer>(info) {
56
+ Napi::Env env = info.Env();
57
+
58
+ if (info.Length() > 0 && info[0].IsNumber()) {
59
+ size_t capacity = info[0].As<Napi::Number>().Uint32Value();
60
+ buffer_ = micropdf_buffer_new(capacity);
61
+ } else {
62
+ buffer_ = micropdf_buffer_new(0);
63
+ }
64
+
65
+ if (buffer_ == nullptr) {
66
+ Napi::Error::New(env, "Failed to create buffer").ThrowAsJavaScriptException();
67
+ }
68
+ }
69
+
70
+ Buffer::~Buffer() {
71
+ if (buffer_ != nullptr) {
72
+ micropdf_buffer_free(buffer_);
73
+ buffer_ = nullptr;
74
+ }
75
+ }
76
+
77
+ Napi::Value Buffer::GetLength(const Napi::CallbackInfo& info) {
78
+ Napi::Env env = info.Env();
79
+ if (buffer_ == nullptr) {
80
+ return Napi::Number::New(env, 0);
81
+ }
82
+ return Napi::Number::New(env, static_cast<double>(micropdf_buffer_len(buffer_)));
83
+ }
84
+
85
+ Napi::Value Buffer::GetData(const Napi::CallbackInfo& info) {
86
+ Napi::Env env = info.Env();
87
+ if (buffer_ == nullptr) {
88
+ return env.Null();
89
+ }
90
+
91
+ size_t len = micropdf_buffer_len(buffer_);
92
+ const uint8_t* data = micropdf_buffer_data(buffer_);
93
+
94
+ if (data == nullptr || len == 0) {
95
+ return Napi::Buffer<uint8_t>::New(env, 0);
96
+ }
97
+
98
+ // Copy data to a new Node.js Buffer
99
+ return Napi::Buffer<uint8_t>::Copy(env, data, len);
100
+ }
101
+
102
+ Napi::Value Buffer::Append(const Napi::CallbackInfo& info) {
103
+ Napi::Env env = info.Env();
104
+
105
+ if (info.Length() < 1) {
106
+ Napi::TypeError::New(env, "Expected Buffer or Uint8Array").ThrowAsJavaScriptException();
107
+ return env.Undefined();
108
+ }
109
+
110
+ if (buffer_ == nullptr) {
111
+ Napi::Error::New(env, "Buffer is null").ThrowAsJavaScriptException();
112
+ return env.Undefined();
113
+ }
114
+
115
+ if (info[0].IsBuffer()) {
116
+ Napi::Buffer<uint8_t> buf = info[0].As<Napi::Buffer<uint8_t>>();
117
+ micropdf_error_t err = micropdf_buffer_append(buffer_, buf.Data(), buf.Length());
118
+ if (err != MICROPDF_OK) {
119
+ Napi::Error::New(env, "Failed to append data").ThrowAsJavaScriptException();
120
+ }
121
+ } else if (info[0].IsTypedArray()) {
122
+ Napi::TypedArray arr = info[0].As<Napi::TypedArray>();
123
+ if (arr.TypedArrayType() == napi_uint8_array) {
124
+ Napi::Uint8Array u8arr = arr.As<Napi::Uint8Array>();
125
+ micropdf_error_t err = micropdf_buffer_append(buffer_, u8arr.Data(), u8arr.ElementLength());
126
+ if (err != MICROPDF_OK) {
127
+ Napi::Error::New(env, "Failed to append data").ThrowAsJavaScriptException();
128
+ }
129
+ }
130
+ } else {
131
+ Napi::TypeError::New(env, "Expected Buffer or Uint8Array").ThrowAsJavaScriptException();
132
+ }
133
+
134
+ return info.This();
135
+ }
136
+
137
+ Napi::Value Buffer::ToNodeBuffer(const Napi::CallbackInfo& info) {
138
+ return GetData(info);
139
+ }
140
+
141
+ Napi::Value Buffer::FromNodeBuffer(const Napi::CallbackInfo& info) {
142
+ Napi::Env env = info.Env();
143
+
144
+ if (info.Length() < 1 || !info[0].IsBuffer()) {
145
+ Napi::TypeError::New(env, "Expected Buffer").ThrowAsJavaScriptException();
146
+ return env.Undefined();
147
+ }
148
+
149
+ Napi::Buffer<uint8_t> nodeBuf = info[0].As<Napi::Buffer<uint8_t>>();
150
+ micropdf_buffer_t* buf = micropdf_buffer_from_data(nodeBuf.Data(), nodeBuf.Length());
151
+
152
+ if (buf == nullptr) {
153
+ Napi::Error::New(env, "Failed to create buffer from data").ThrowAsJavaScriptException();
154
+ return env.Undefined();
155
+ }
156
+
157
+ // Create a new Buffer instance
158
+ Napi::Object obj = constructor.New({});
159
+ Buffer* wrapper = Napi::ObjectWrap<Buffer>::Unwrap(obj);
160
+
161
+ // Free the old buffer and set the new one
162
+ if (wrapper->buffer_ != nullptr) {
163
+ micropdf_buffer_free(wrapper->buffer_);
164
+ }
165
+ wrapper->buffer_ = buf;
166
+
167
+ return obj;
168
+ }
169
+
170
+ Napi::Value Buffer::FromString(const Napi::CallbackInfo& info) {
171
+ Napi::Env env = info.Env();
172
+
173
+ if (info.Length() < 1 || !info[0].IsString()) {
174
+ Napi::TypeError::New(env, "Expected string").ThrowAsJavaScriptException();
175
+ return env.Undefined();
176
+ }
177
+
178
+ std::string str = info[0].As<Napi::String>().Utf8Value();
179
+ micropdf_buffer_t* buf = micropdf_buffer_from_data(
180
+ reinterpret_cast<const uint8_t*>(str.data()),
181
+ str.length()
182
+ );
183
+
184
+ if (buf == nullptr) {
185
+ Napi::Error::New(env, "Failed to create buffer from string").ThrowAsJavaScriptException();
186
+ return env.Undefined();
187
+ }
188
+
189
+ Napi::Object obj = constructor.New({});
190
+ Buffer* wrapper = Napi::ObjectWrap<Buffer>::Unwrap(obj);
191
+
192
+ if (wrapper->buffer_ != nullptr) {
193
+ micropdf_buffer_free(wrapper->buffer_);
194
+ }
195
+ wrapper->buffer_ = buf;
196
+
197
+ return obj;
198
+ }
199
+
200
+ // Export initialization function
201
+ Napi::Object InitBuffer(Napi::Env env, Napi::Object exports) {
202
+ return Buffer::Init(env, exports);
203
+ }
204
+
@@ -0,0 +1,166 @@
1
+ /**
2
+ * MicroPDF Colorspace Bindings
3
+ *
4
+ * N-API bindings for colorspace operations.
5
+ * Colorspaces define color interpretation for images and graphics.
6
+ */
7
+
8
+ #include <napi.h>
9
+ #include "include/mupdf_minimal.h"
10
+
11
+ /**
12
+ * Get device gray colorspace handle
13
+ *
14
+ * @param ctx - Context handle
15
+ * @returns Colorspace handle (1)
16
+ */
17
+ Napi::BigInt DeviceGray(const Napi::CallbackInfo& info) {
18
+ Napi::Env env = info.Env();
19
+
20
+ if (info.Length() < 1) {
21
+ Napi::TypeError::New(env, "Expected 1 argument: ctx")
22
+ .ThrowAsJavaScriptException();
23
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
24
+ }
25
+
26
+ bool lossless;
27
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
28
+
29
+ uint64_t cs_handle = fz_device_gray(ctx_handle);
30
+
31
+ return Napi::BigInt::New(env, cs_handle);
32
+ }
33
+
34
+ /**
35
+ * Get device RGB colorspace handle
36
+ *
37
+ * @param ctx - Context handle
38
+ * @returns Colorspace handle (2)
39
+ */
40
+ Napi::BigInt DeviceRGB(const Napi::CallbackInfo& info) {
41
+ Napi::Env env = info.Env();
42
+
43
+ if (info.Length() < 1) {
44
+ Napi::TypeError::New(env, "Expected 1 argument: ctx")
45
+ .ThrowAsJavaScriptException();
46
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
47
+ }
48
+
49
+ bool lossless;
50
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
51
+
52
+ uint64_t cs_handle = fz_device_rgb(ctx_handle);
53
+
54
+ return Napi::BigInt::New(env, cs_handle);
55
+ }
56
+
57
+ /**
58
+ * Get device BGR colorspace handle
59
+ *
60
+ * @param ctx - Context handle
61
+ * @returns Colorspace handle (3)
62
+ */
63
+ Napi::BigInt DeviceBGR(const Napi::CallbackInfo& info) {
64
+ Napi::Env env = info.Env();
65
+
66
+ if (info.Length() < 1) {
67
+ Napi::TypeError::New(env, "Expected 1 argument: ctx")
68
+ .ThrowAsJavaScriptException();
69
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
70
+ }
71
+
72
+ bool lossless;
73
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
74
+
75
+ uint64_t cs_handle = fz_device_bgr(ctx_handle);
76
+
77
+ return Napi::BigInt::New(env, cs_handle);
78
+ }
79
+
80
+ /**
81
+ * Get device CMYK colorspace handle
82
+ *
83
+ * @param ctx - Context handle
84
+ * @returns Colorspace handle (4)
85
+ */
86
+ Napi::BigInt DeviceCMYK(const Napi::CallbackInfo& info) {
87
+ Napi::Env env = info.Env();
88
+
89
+ if (info.Length() < 1) {
90
+ Napi::TypeError::New(env, "Expected 1 argument: ctx")
91
+ .ThrowAsJavaScriptException();
92
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
93
+ }
94
+
95
+ bool lossless;
96
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
97
+
98
+ uint64_t cs_handle = fz_device_cmyk(ctx_handle);
99
+
100
+ return Napi::BigInt::New(env, cs_handle);
101
+ }
102
+
103
+ /**
104
+ * Get number of components in colorspace
105
+ *
106
+ * @param ctx - Context handle
107
+ * @param cs - Colorspace handle
108
+ * @returns Number of components (1 for Gray, 3 for RGB, 4 for CMYK)
109
+ */
110
+ Napi::Number ColorspaceN(const Napi::CallbackInfo& info) {
111
+ Napi::Env env = info.Env();
112
+
113
+ if (info.Length() < 2) {
114
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cs")
115
+ .ThrowAsJavaScriptException();
116
+ return Napi::Number::New(env, 0);
117
+ }
118
+
119
+ bool lossless;
120
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
121
+ uint64_t cs_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
122
+
123
+ int32_t n = fz_colorspace_n(ctx_handle, cs_handle);
124
+
125
+ return Napi::Number::New(env, n);
126
+ }
127
+
128
+ /**
129
+ * Get colorspace name
130
+ *
131
+ * @param ctx - Context handle
132
+ * @param cs - Colorspace handle
133
+ * @returns Colorspace name string
134
+ */
135
+ Napi::String ColorspaceName(const Napi::CallbackInfo& info) {
136
+ Napi::Env env = info.Env();
137
+
138
+ if (info.Length() < 2) {
139
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cs")
140
+ .ThrowAsJavaScriptException();
141
+ return Napi::String::New(env, "");
142
+ }
143
+
144
+ bool lossless;
145
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
146
+ uint64_t cs_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
147
+
148
+ const char* name = fz_colorspace_name(ctx_handle, cs_handle);
149
+
150
+ return Napi::String::New(env, name ? name : "");
151
+ }
152
+
153
+ /**
154
+ * Initialize Colorspace module exports
155
+ */
156
+ Napi::Object InitColorspace(Napi::Env env, Napi::Object exports) {
157
+ exports.Set("deviceGray", Napi::Function::New(env, DeviceGray));
158
+ exports.Set("deviceRGB", Napi::Function::New(env, DeviceRGB));
159
+ exports.Set("deviceBGR", Napi::Function::New(env, DeviceBGR));
160
+ exports.Set("deviceCMYK", Napi::Function::New(env, DeviceCMYK));
161
+ exports.Set("colorspaceN", Napi::Function::New(env, ColorspaceN));
162
+ exports.Set("colorspaceName", Napi::Function::New(env, ColorspaceName));
163
+
164
+ return exports;
165
+ }
166
+
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Context FFI Bindings
3
+ *
4
+ * Implements N-API bindings for MuPDF context functions (fz_context).
5
+ * Context manages memory allocation, error handling, and resource tracking.
6
+ */
7
+
8
+ #include <napi.h>
9
+ #include "include/mupdf_minimal.h"
10
+
11
+ /**
12
+ * Create a new context
13
+ * JavaScript: createContext(): NativeContext
14
+ */
15
+ Napi::Value CreateContext(const Napi::CallbackInfo& info) {
16
+ Napi::Env env = info.Env();
17
+
18
+ fz_context ctx = fz_new_context(nullptr, nullptr, FZ_STORE_DEFAULT);
19
+ if (ctx == 0) {
20
+ Napi::Error::New(env, "Failed to create context").ThrowAsJavaScriptException();
21
+ return env.Null();
22
+ }
23
+
24
+ Napi::Object obj = Napi::Object::New(env);
25
+ obj.Set("_handle", Napi::Number::New(env, ctx));
26
+ return obj;
27
+ }
28
+
29
+ /**
30
+ * Drop/free a context
31
+ * JavaScript: dropContext(ctx: NativeContext): void
32
+ */
33
+ Napi::Value DropContext(const Napi::CallbackInfo& info) {
34
+ Napi::Env env = info.Env();
35
+
36
+ if (info.Length() < 1 || !info[0].IsObject()) {
37
+ Napi::TypeError::New(env, "Expected context object").ThrowAsJavaScriptException();
38
+ return env.Undefined();
39
+ }
40
+
41
+ Napi::Object ctxObj = info[0].As<Napi::Object>();
42
+ if (!ctxObj.Has("_handle")) {
43
+ Napi::TypeError::New(env, "Invalid context object").ThrowAsJavaScriptException();
44
+ return env.Undefined();
45
+ }
46
+
47
+ fz_context ctx = ctxObj.Get("_handle").As<Napi::Number>().Int32Value();
48
+ fz_drop_context(ctx);
49
+
50
+ return env.Undefined();
51
+ }
52
+
53
+ /**
54
+ * Clone a context (create a reference)
55
+ * JavaScript: cloneContext(ctx: NativeContext): NativeContext
56
+ */
57
+ Napi::Value CloneContext(const Napi::CallbackInfo& info) {
58
+ Napi::Env env = info.Env();
59
+
60
+ if (info.Length() < 1 || !info[0].IsObject()) {
61
+ Napi::TypeError::New(env, "Expected context object").ThrowAsJavaScriptException();
62
+ return env.Null();
63
+ }
64
+
65
+ Napi::Object ctxObj = info[0].As<Napi::Object>();
66
+ fz_context ctx = ctxObj.Get("_handle").As<Napi::Number>().Int32Value();
67
+
68
+ fz_context newCtx = fz_clone_context(ctx);
69
+
70
+ Napi::Object obj = Napi::Object::New(env);
71
+ obj.Set("_handle", Napi::Number::New(env, newCtx));
72
+ return obj;
73
+ }
74
+
75
+ /**
76
+ * Initialize context exports
77
+ */
78
+ Napi::Object InitContext(Napi::Env env, Napi::Object exports) {
79
+ exports.Set("createContext", Napi::Function::New(env, CreateContext));
80
+ exports.Set("dropContext", Napi::Function::New(env, DropContext));
81
+ exports.Set("cloneContext", Napi::Function::New(env, CloneContext));
82
+ return exports;
83
+ }
84
+
@@ -0,0 +1,179 @@
1
+ /**
2
+ * MicroPDF Cookie Bindings
3
+ *
4
+ * N-API bindings for cookie operations.
5
+ * Cookies provide progress tracking and cancellation for long-running operations.
6
+ */
7
+
8
+ #include <napi.h>
9
+ #include "include/mupdf_minimal.h"
10
+
11
+ /**
12
+ * Create a new cookie
13
+ *
14
+ * @param ctx - Context handle
15
+ * @returns Cookie handle
16
+ */
17
+ Napi::BigInt NewCookie(const Napi::CallbackInfo& info) {
18
+ Napi::Env env = info.Env();
19
+
20
+ if (info.Length() < 1) {
21
+ Napi::TypeError::New(env, "Expected 1 argument: ctx")
22
+ .ThrowAsJavaScriptException();
23
+ return Napi::BigInt::New(env, static_cast<uint64_t>(0));
24
+ }
25
+
26
+ bool lossless;
27
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
28
+
29
+ uint64_t cookie_handle = fz_new_cookie(ctx_handle);
30
+
31
+ return Napi::BigInt::New(env, cookie_handle);
32
+ }
33
+
34
+ /**
35
+ * Drop cookie handle
36
+ *
37
+ * @param ctx - Context handle
38
+ * @param cookie - Cookie handle
39
+ */
40
+ Napi::Value DropCookie(const Napi::CallbackInfo& info) {
41
+ Napi::Env env = info.Env();
42
+
43
+ if (info.Length() < 2) {
44
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cookie")
45
+ .ThrowAsJavaScriptException();
46
+ return env.Undefined();
47
+ }
48
+
49
+ bool lossless;
50
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
51
+ uint64_t cookie_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
52
+
53
+ fz_drop_cookie(ctx_handle, cookie_handle);
54
+
55
+ return env.Undefined();
56
+ }
57
+
58
+ /**
59
+ * Abort operation via cookie
60
+ *
61
+ * @param ctx - Context handle
62
+ * @param cookie - Cookie handle
63
+ */
64
+ Napi::Value AbortCookie(const Napi::CallbackInfo& info) {
65
+ Napi::Env env = info.Env();
66
+
67
+ if (info.Length() < 2) {
68
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cookie")
69
+ .ThrowAsJavaScriptException();
70
+ return env.Undefined();
71
+ }
72
+
73
+ bool lossless;
74
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
75
+ uint64_t cookie_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
76
+
77
+ fz_abort_cookie(ctx_handle, cookie_handle);
78
+
79
+ return env.Undefined();
80
+ }
81
+
82
+ /**
83
+ * Get cookie progress
84
+ *
85
+ * @param ctx - Context handle
86
+ * @param cookie - Cookie handle
87
+ * @returns Object {progress, progressMax, errors}
88
+ */
89
+ Napi::Object GetCookieProgress(const Napi::CallbackInfo& info) {
90
+ Napi::Env env = info.Env();
91
+ Napi::Object result = Napi::Object::New(env);
92
+
93
+ if (info.Length() < 2) {
94
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cookie")
95
+ .ThrowAsJavaScriptException();
96
+ return result;
97
+ }
98
+
99
+ bool lossless;
100
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
101
+ uint64_t cookie_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
102
+
103
+ int32_t progress = 0;
104
+ int32_t progress_max = 0;
105
+ int32_t errors = 0;
106
+
107
+ fz_cookie_progress(ctx_handle, cookie_handle, &progress, &progress_max, &errors);
108
+
109
+ result.Set("progress", Napi::Number::New(env, progress));
110
+ result.Set("progressMax", Napi::Number::New(env, progress_max));
111
+ result.Set("errors", Napi::Number::New(env, errors));
112
+
113
+ return result;
114
+ }
115
+
116
+ /**
117
+ * Check if cookie has been aborted
118
+ *
119
+ * @param ctx - Context handle
120
+ * @param cookie - Cookie handle
121
+ * @returns Boolean
122
+ */
123
+ Napi::Boolean IsCookieAborted(const Napi::CallbackInfo& info) {
124
+ Napi::Env env = info.Env();
125
+
126
+ if (info.Length() < 2) {
127
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cookie")
128
+ .ThrowAsJavaScriptException();
129
+ return Napi::Boolean::New(env, false);
130
+ }
131
+
132
+ bool lossless;
133
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
134
+ uint64_t cookie_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
135
+
136
+ int32_t is_aborted = fz_cookie_is_aborted(ctx_handle, cookie_handle);
137
+
138
+ return Napi::Boolean::New(env, is_aborted != 0);
139
+ }
140
+
141
+ /**
142
+ * Reset cookie state
143
+ *
144
+ * @param ctx - Context handle
145
+ * @param cookie - Cookie handle
146
+ */
147
+ Napi::Value ResetCookie(const Napi::CallbackInfo& info) {
148
+ Napi::Env env = info.Env();
149
+
150
+ if (info.Length() < 2) {
151
+ Napi::TypeError::New(env, "Expected 2 arguments: ctx, cookie")
152
+ .ThrowAsJavaScriptException();
153
+ return env.Undefined();
154
+ }
155
+
156
+ bool lossless;
157
+ uint64_t ctx_handle = info[0].As<Napi::BigInt>().Uint64Value(&lossless);
158
+ uint64_t cookie_handle = info[1].As<Napi::BigInt>().Uint64Value(&lossless);
159
+
160
+ fz_reset_cookie(ctx_handle, cookie_handle);
161
+
162
+ return env.Undefined();
163
+ }
164
+
165
+ /**
166
+ * Initialize Cookie module exports
167
+ */
168
+ Napi::Object InitCookie(Napi::Env env, Napi::Object exports) {
169
+ exports.Set("newCookie", Napi::Function::New(env, NewCookie));
170
+ exports.Set("dropCookie", Napi::Function::New(env, DropCookie));
171
+ exports.Set("abortCookie", Napi::Function::New(env, AbortCookie));
172
+ exports.Set("getCookieProgress", Napi::Function::New(env, GetCookieProgress));
173
+ exports.Set("isCookieAborted", Napi::Function::New(env, IsCookieAborted));
174
+ exports.Set("resetCookie", Napi::Function::New(env, ResetCookie));
175
+
176
+ return exports;
177
+ }
178
+
179
+