bare-x-to-pdf 0.4.0 → 0.5.1

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.
package/CMakeLists.txt CHANGED
@@ -9,7 +9,11 @@ include(cmake/rust.cmake)
9
9
 
10
10
  bare_target(target)
11
11
 
12
- add_bare_module(simple_converter NAME bare-x-to-pdf-${target})
12
+ if(target STREQUAL "wasi-wasm32")
13
+ add_bare_module(simple_converter)
14
+ else()
15
+ add_bare_module(simple_converter NAME bare-x-to-pdf-${target})
16
+ endif()
13
17
 
14
18
  target_sources(
15
19
  ${simple_converter}
@@ -29,10 +33,26 @@ target_link_libraries(
29
33
  simple_converter_core
30
34
  )
31
35
 
36
+ # Bound the linear memory a hostile document can claim, so it traps instead of
37
+ # growing to the 4 GiB limit of wasm32, and give the recursive readers and
38
+ # Typst the 8 MiB stack they get on native threads rather than the 64 KiB
39
+ # default of wasm-ld. The default cap leaves room for the 256 MB images and
40
+ # 128 MB parts that core/src/limits.rs lets through.
41
+ set(SIMPLE_CONVERTER_WASM_MAX_MEMORY 1073741824 CACHE STRING "Linear memory limit of the WebAssembly addon in bytes, a multiple of 65536")
42
+
43
+ if(target MATCHES "^wasi-")
44
+ target_link_options(
45
+ ${simple_converter}_module
46
+ PRIVATE
47
+ -Wl,--max-memory=${SIMPLE_CONVERTER_WASM_MAX_MEMORY}
48
+ -Wl,-z,stack-size=8388608
49
+ )
50
+ endif()
51
+
32
52
  if(CMAKE_STRIP AND NOT WIN32)
33
53
  add_custom_command(
34
54
  TARGET ${simple_converter}_module
35
55
  POST_BUILD
36
- COMMAND ${CMAKE_STRIP} $<IF:$<PLATFORM_ID:Darwin,iOS>,-x,--strip-unneeded> $<TARGET_FILE:${simple_converter}_module>
56
+ COMMAND ${CMAKE_STRIP} $<IF:$<PLATFORM_ID:Darwin,iOS>,-x,$<IF:$<PLATFORM_ID:WASI>,--strip-all,--strip-unneeded>> $<TARGET_FILE:${simple_converter}_module>
37
57
  )
38
58
  endif()
package/README.md CHANGED
@@ -42,6 +42,39 @@ npm install --os=android --cpu=arm64
42
42
  npm install --os=ios --cpu=arm64
43
43
  ```
44
44
 
45
+ ### WebAssembly
46
+
47
+ On Bare 1.36 and later the converter can also run as a WebAssembly addon, sandboxed through
48
+ WASI. The `.wasm` prebuild ships in the main package, so there is nothing extra to install.
49
+ Import with the `wasi-wasm32` host and a WASI provider. The attributes must be written
50
+ inline in the `require` call. The addon needs a random source and read access to the fonts:
51
+
52
+ ```js
53
+ const converter = require('bare-x-to-pdf', {
54
+ with: { host: 'wasi-wasm32', wasi: './wasi.js' }
55
+ })
56
+ ```
57
+
58
+ ```js
59
+ // wasi.js
60
+ const crypto = require('bare-crypto')
61
+ const { DirectorySync } = require('bare-directory')
62
+ const { HostDirectory } = require('bare-wasi/host')
63
+
64
+ const fonts = require.resolve('bare-x-to-pdf/package').replace(/package\.json$/, 'fonts')
65
+
66
+ module.exports = (url) => ({
67
+ version: 'preview1',
68
+ random: (b) => crypto.randomFillSync(b),
69
+ preopens: { [fonts]: new HostDirectory(DirectorySync.open(fonts)) }
70
+ })
71
+ ```
72
+
73
+ The WebAssembly addon has only `convertSync`. `convert()` falls back to it, so it blocks the
74
+ calling thread; run conversions in a [`bare-thread`](https://github.com/holepunchto/bare-thread).
75
+ A hostile document can crash the addon with a `RuntimeError` without taking down the process,
76
+ but the addon stays unusable in that thread afterwards, so replace the thread.
77
+
45
78
  ## Usage
46
79
 
47
80
  ```js
@@ -90,7 +123,7 @@ Return every supported pair as `{ from, to }`.
90
123
 
91
124
  ### `FONTS_DIR`
92
125
 
93
- Path to the bundled fonts directory.
126
+ Path to the bundled fonts directory, resolved with `require.asset`.
94
127
 
95
128
  ## Limits
96
129
 
package/binding.c CHANGED
@@ -1,12 +1,15 @@
1
1
  #include <assert.h>
2
- #include <bare.h>
2
+ #include <bare/module.h>
3
3
  #include <js.h>
4
4
  #include <stdbool.h>
5
5
  #include <stdint.h>
6
6
  #include <stdlib.h>
7
7
  #include <string.h>
8
8
  #include <utf.h>
9
+
10
+ #ifndef __wasm__
9
11
  #include <uv.h>
12
+ #endif
10
13
 
11
14
  #include "simple_converter.h"
12
15
 
@@ -22,6 +25,10 @@ typedef struct {
22
25
  int status;
23
26
  } simple_converter_job_t;
24
27
 
28
+ // WebAssembly addons are single threaded and have no event loop, so they
29
+ // export only convertSync() and leave running it off the JavaScript thread to
30
+ // the embedder.
31
+ #ifndef __wasm__
25
32
  typedef struct {
26
33
  uv_work_t work;
27
34
  js_env_t *env;
@@ -30,6 +37,7 @@ typedef struct {
30
37
  bool exiting;
31
38
  simple_converter_job_t job;
32
39
  } simple_converter_req_t;
40
+ #endif
33
41
 
34
42
  static bool
35
43
  simple_converter__string(js_env_t *env, js_value_t *value, char **result) {
@@ -218,6 +226,7 @@ simple_converter_convert_sync(js_env_t *env, js_callback_info_t *info) {
218
226
  return result;
219
227
  }
220
228
 
229
+ #ifndef __wasm__
221
230
  static void
222
231
  simple_converter__on_work(uv_work_t *work) {
223
232
  simple_converter_req_t *req = (simple_converter_req_t *) work;
@@ -300,6 +309,7 @@ simple_converter_convert(js_env_t *env, js_callback_info_t *info) {
300
309
 
301
310
  return promise;
302
311
  }
312
+ #endif
303
313
 
304
314
  static js_value_t *
305
315
  simple_converter_exports(js_env_t *env, js_value_t *exports) {
@@ -314,7 +324,9 @@ simple_converter_exports(js_env_t *env, js_value_t *exports) {
314
324
  assert(err == 0); \
315
325
  }
316
326
 
327
+ #ifndef __wasm__
317
328
  V("convert", simple_converter_convert)
329
+ #endif
318
330
  V("convertSync", simple_converter_convert_sync)
319
331
  #undef V
320
332
 
package/cmake/rust.cmake CHANGED
@@ -43,6 +43,8 @@ elseif(_sys STREQUAL "win32")
43
43
  else()
44
44
  set(_triple x86_64-pc-windows-msvc)
45
45
  endif()
46
+ elseif(_sys STREQUAL "wasi")
47
+ set(_triple wasm32-wasip1)
46
48
  else()
47
49
  message(FATAL_ERROR "simple-converter: no Rust target for '${_sys}/${_arch}'")
48
50
  endif()
@@ -56,3 +58,11 @@ corrosion_import_crate(
56
58
  CRATE_TYPES staticlib
57
59
  PROFILE release
58
60
  )
61
+
62
+ # Corrosion 0.6.1 adds the Command Line Tools SDK as a link directory on macOS.
63
+ # The linker searches it before CMAKE_OSX_SYSROOT, so -lSystem resolves against
64
+ # the wrong SDK and fails when the two differ (corrosion-rs/corrosion#686, fixed
65
+ # upstream after 0.6.1). Drop this once the pin moves past that fix.
66
+ if(APPLE)
67
+ set_property(TARGET simple_converter_core-static PROPERTY INTERFACE_LINK_DIRECTORIES "")
68
+ endif()
package/index.js CHANGED
@@ -1,7 +1,6 @@
1
- const path = require('bare-path')
2
1
  const { binding } = require('./binding')
3
2
 
4
- const FONTS_DIR = path.join(__dirname, 'fonts')
3
+ const FONTS_DIR = require.asset('./fonts')
5
4
 
6
5
  const CONVERSIONS = {
7
6
  docx: ['pdf'],
@@ -188,7 +187,11 @@ function optional(value) {
188
187
  }
189
188
 
190
189
  async function convert(input, opts = {}) {
191
- return Buffer.from(await binding.convert(...prepare(input, opts)))
190
+ const args = prepare(input, opts)
191
+ // The WebAssembly addon has no thread pool, so it converts on the calling
192
+ // thread; run it in a worker to keep the JavaScript thread free.
193
+ if (binding.convert === undefined) return Buffer.from(binding.convertSync(...args))
194
+ return Buffer.from(await binding.convert(...args))
192
195
  }
193
196
 
194
197
  function convertSync(input, opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-x-to-pdf",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Convert Word, PowerPoint, Excel and OpenDocument files to PDF for Bare: a Rust engine on Typst",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -8,6 +8,10 @@
8
8
  ".": {
9
9
  "types": "./index.d.ts",
10
10
  "default": "./index.js"
11
+ },
12
+ "./types": {
13
+ "types": "./types.d.ts",
14
+ "default": "./types.js"
11
15
  }
12
16
  },
13
17
  "types": "./index.d.ts",
@@ -17,8 +21,12 @@
17
21
  "files": [
18
22
  "index.js",
19
23
  "index.d.ts",
24
+ "types.js",
25
+ "types.d.ts",
20
26
  "binding.c",
21
27
  "binding.js",
28
+ "wasi.js",
29
+ "prebuilds/wasi-wasm32",
22
30
  "CMakeLists.txt",
23
31
  "cmake",
24
32
  "core/Cargo.toml",
@@ -64,14 +72,14 @@
64
72
  "publishConfig": {
65
73
  "access": "public"
66
74
  },
67
- "dependencies": {
68
- "bare-path": "^3.0.0",
69
- "bare-url": "^2.4.1"
70
- },
71
75
  "devDependencies": {
76
+ "bare-crypto": "^1.15.4",
72
77
  "bare-fs": "^4.0.0",
78
+ "bare-path": "^3.0.0",
79
+ "bare-wasi": "^0.1.1",
80
+ "bare-wasm-abi": "^0.1.1",
73
81
  "brittle": "^4.1.0",
74
- "cmake-bare": "^1.8.3",
82
+ "cmake-bare": "^1.10.1",
75
83
  "cmake-fetch": "^1.5.1",
76
84
  "lunte": "^1.8.4",
77
85
  "prettier": "^3.9.6",
@@ -79,6 +87,9 @@
79
87
  },
80
88
  "imports": {
81
89
  "#binding": {
90
+ "wasi": {
91
+ "wasm32": "./wasi.js"
92
+ },
82
93
  "android": {
83
94
  "arm": "bare-x-to-pdf-android-arm",
84
95
  "arm64": "bare-x-to-pdf-android-arm64",
@@ -107,16 +118,16 @@
107
118
  }
108
119
  },
109
120
  "optionalDependencies": {
110
- "bare-x-to-pdf-android-arm": "0.4.0",
111
- "bare-x-to-pdf-android-arm64": "0.4.0",
112
- "bare-x-to-pdf-android-x64": "0.4.0",
113
- "bare-x-to-pdf-darwin-arm64": "0.4.0",
114
- "bare-x-to-pdf-darwin-x64": "0.4.0",
115
- "bare-x-to-pdf-ios-arm64": "0.4.0",
116
- "bare-x-to-pdf-ios-arm64-simulator": "0.4.0",
117
- "bare-x-to-pdf-ios-x64-simulator": "0.4.0",
118
- "bare-x-to-pdf-linux-arm64": "0.4.0",
119
- "bare-x-to-pdf-linux-x64": "0.4.0",
120
- "bare-x-to-pdf-win32-x64": "0.4.0"
121
+ "bare-x-to-pdf-android-arm": "0.5.1",
122
+ "bare-x-to-pdf-android-arm64": "0.5.1",
123
+ "bare-x-to-pdf-android-x64": "0.5.1",
124
+ "bare-x-to-pdf-darwin-arm64": "0.5.1",
125
+ "bare-x-to-pdf-darwin-x64": "0.5.1",
126
+ "bare-x-to-pdf-ios-arm64": "0.5.1",
127
+ "bare-x-to-pdf-ios-arm64-simulator": "0.5.1",
128
+ "bare-x-to-pdf-ios-x64-simulator": "0.5.1",
129
+ "bare-x-to-pdf-linux-arm64": "0.5.1",
130
+ "bare-x-to-pdf-linux-x64": "0.5.1",
131
+ "bare-x-to-pdf-win32-x64": "0.5.1"
121
132
  }
122
133
  }
package/types.d.ts ADDED
@@ -0,0 +1 @@
1
+ export function isMimeTypeSupported(mimetype: string): boolean
package/types.js ADDED
@@ -0,0 +1,19 @@
1
+ const supportedDocumentMimetypes = [
2
+ 'application/msword',
3
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
4
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
5
+ 'application/vnd.ms-word.document.macroenabled.12',
6
+ 'application/vnd.ms-word.template.macroenabled.12',
7
+ 'application/vnd.ms-excel',
8
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
9
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
10
+ 'application/vnd.ms-excel.sheet.macroenabled.12',
11
+ 'application/vnd.ms-excel.template.macroenabled.12',
12
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
13
+ ]
14
+
15
+ function isMimeTypeSupported(mimetype) {
16
+ return supportedDocumentMimetypes.includes(mimetype)
17
+ }
18
+
19
+ exports.isMimeTypeSupported = isMimeTypeSupported
package/wasi.js ADDED
@@ -0,0 +1 @@
1
+ exports.binding = require.addon()