Skip to content

Commit a027807

Browse files
committed
revert(ghoulscript): remove useCDN option
Not work as espect
1 parent c00b95d commit a027807

File tree

9 files changed

+240
-88
lines changed

9 files changed

+240
-88
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
# ghoulscript
1+
# Ghoulscript
2+
> PDF Utillities using Ghostscript WASM, work on Browser and NodeJS
3+
4+
## Documentation
5+
6+
[Read documentation here](./packages/ghoulscript/README.md)
27

38
## License
49

packages/ghostscript/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,13 @@
3232
"@types/emscripten": "^1.39.13",
3333
"vitest": "^1.6.0"
3434
},
35-
"license": "AGPL-3.0-only"
35+
"license": "AGPL-3.0-only",
36+
"publishConfig": {
37+
"access": "public"
38+
},
39+
"repository": {
40+
"type": "git",
41+
"url": "https://github.com/privy-open-source/ghoulscript",
42+
"directory": "packages/ghostscript"
43+
}
3644
}

packages/ghoulscript/README.md

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,187 @@
1-
# ghoulscript
1+
# @privyid/ghoulscript
2+
> Compress, merge, split, and render pages to image using Ghostscript
3+
4+
## Installation
5+
6+
```bash
7+
yarn add @privyid/ghoulscript
8+
```
9+
10+
## How to Use
11+
12+
### Using with Browser (Vite)
13+
14+
```ts
15+
import { optimizePDF } from '@privyid/ghoulscript'
16+
17+
const input = document.querySelector('input[type="file"]')
18+
19+
input.addEventListener('change', async () => {
20+
if (input.files) {
21+
const file = input.files[0]
22+
const buffer = await file.arrayBuffer()
23+
const output = await optimizePDF(new Uint8Array(buffer))
24+
25+
window.open(URL.createObjectURL(new Blob([output], { type: 'application/pdf' })), '_blank')
26+
}
27+
})
28+
```
29+
30+
### Using with NodeJS
31+
```ts
32+
import fs from 'node:fs/promises'
33+
import { resolve } from 'node:path'
34+
import { optimizePDF } from '@privyid/ghoulscript'
35+
36+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
37+
const output = await optimizePDF(buffer)
38+
39+
await fs.writeFile(resolve(__dirname, './sample.compressed.pdf'), output)
40+
```
41+
42+
## Utilities
43+
44+
### optimizePDF (file: Buffer, options?: CompressOptions)
45+
46+
Compress and optimize PDF for Web Viewer.
47+
48+
```ts
49+
import { optimizePDF } from '@privyid/ghoulscript'
50+
51+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
52+
const output = await optimizePDF(buffer, { password: '******' })
53+
54+
await fs.writeFile(resolve(__dirname, './sample.compressed.pdf'), output)
55+
```
56+
57+
#### CompressOptions
58+
59+
| Options | Type | Default | Description |
60+
|---------------------------|:---------:|:--------:|------------------------------------------------------------------------------------|
61+
| `password` | `String` | - | Document protection password |
62+
| `pdfSettings` | `String` | `screen` | Preset setting, valid value is `screen`, `ebook`, `printer`, `prepress`, `default` |
63+
| `fastWebView` | `Boolean` | `true` | Enable Linearization |
64+
| `compatibilityLevel` | `String` | `1.4` | Compability version |
65+
| `colorConversionStrategy` | `String` | `RGB` | Color conversion strategy, valid value is `RGB`, `CMYK` |
66+
| `noTransparency` | `Boolean` | `true` | Remove transparency |
67+
| `keepPassword` | `Boolean` | `true` | Keep document password if document have a password protection |
68+
| `userPassword` | `String` | - | Set User Password to document |
69+
| `ownerPassword` | `String` | - | Set Owner Password to document |
70+
71+
### combinePDF (files: Buffer[], options?: CompressOptions)
72+
73+
Combine multiple PDF files into single PDF
74+
75+
```ts
76+
import { combinePDF } from '@privyid/ghoulscript'
77+
78+
const bufferA = await fs.readFile(resolve(__dirname, './sample-1.pdf'))
79+
const bufferB = await fs.readFile(resolve(__dirname, './sample-2.pdf'))
80+
const output = await combinePDF([bufferA, bufferB])
81+
82+
await fs.writeFile(resolve(__dirname, './sample.combine.pdf'), output)
83+
```
84+
85+
### splitPdf (file: Buffer, pageList: PageList[], options?: CompressOptions)
86+
87+
Split single PDF into multiple files
88+
89+
```ts
90+
import { splitPdf } from '@privyid/ghoulscript'
91+
92+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
93+
const outputs = await splitPdf(buffer, ['1-5', '5-12'])
94+
95+
await fs.writeFile(resolve(__dirname, './sample.part1.pdf'), outputs[0])
96+
await fs.writeFile(resolve(__dirname, './sample.part2.pdf'), outputs[1])
97+
```
98+
99+
### addPassword (file: Buffer, userPassword: string, ownerPassword?: string)
100+
101+
Set new User Password and Owner Password
102+
103+
```ts
104+
import { addPassword } from '@privyid/ghoulscript'
105+
106+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
107+
const output = await addPassword(buffer, '123456', '112233')
108+
109+
await fs.writeFile(resolve(__dirname, './sample.protected.pdf'), output)
110+
```
111+
112+
It equivalent with compressPDF's `userPassword` and `ownerPassword` options
113+
114+
### removePassword (file: Buffer, oldPassword: string)
115+
116+
Remove existing encrypted PDF
117+
118+
```ts
119+
import { removePassword } from '@privyid/ghoulscript'
120+
121+
const buffer = await fs.readFile(resolve(__dirname, './sample.protected.pdf'))
122+
const output = await removePassword(buffer, '123456')
123+
124+
await fs.writeFile(resolve(__dirname, './sample.unprotected.pdf'), output)
125+
```
126+
127+
It equivalent with compressPDF's `keepPassword: false`
128+
129+
### renderPageAsImage (file: Buffer, page: number = 1, options?: RenderOptions)
130+
131+
Convert specific page to image
132+
133+
```ts
134+
import { renderPageAsImage } from '@privyid/ghoulscript'
135+
136+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
137+
const output = await renderPageAsImage(buffer, 5, { format: 'jpg' })
138+
139+
await fs.writeFile(resolve(__dirname, './sample.jpg'), output)
140+
```
141+
142+
#### RenderOptions
143+
144+
| Options | Type | Default | Description |
145+
|---------------------|:--------:|:-------:|----------------------------------------------|
146+
| `resolution` | `Number` | `96` | Render resolution |
147+
| `textAlphaBits` | `Number` | `4` | Text alpha bits, valid value is `1`-`4` |
148+
| `graphicsAlphaBits` | `Number` | `4` | Graphic alpha bits, valid value is `1`-`4` |
149+
| `format` | `String` | `jpg` | Render format, valid value is `jpg` or `png` |
150+
151+
## getInfo (file: Buffer, options?: { password: string })
152+
153+
Extract pages info
154+
155+
```ts
156+
import { getInfo } from '@privyid/ghoulscript'
157+
158+
const buffer = await fs.readFile(resolve(__dirname, './sample.pdf'))
159+
const info = await getInfo(buffer)
160+
161+
console.log(info)
162+
/*
163+
{
164+
numPages: 5,
165+
pages: [
166+
{
167+
page: 1,
168+
width: 612,
169+
height: 792,
170+
},
171+
{
172+
page: 2,
173+
width: 612,
174+
height: 792,
175+
},
176+
{
177+
page: 3,
178+
width: 612,
179+
height: 792,
180+
},
181+
]
182+
}
183+
*/
184+
```
2185

3186
## License
4187

packages/ghoulscript/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,13 @@
3131
"defu": "^6.1.4",
3232
"ufo": "^1.5.3"
3333
},
34-
"license": "AGPL-3.0-only"
34+
"license": "AGPL-3.0-only",
35+
"publishConfig": {
36+
"access": "public"
37+
},
38+
"repository": {
39+
"type": "git",
40+
"url": "https://github.com/privy-open-source/ghoulscript",
41+
"directory": "packages/ghoulscript"
42+
}
3543
}

packages/ghoulscript/src/config.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,19 @@
11
import { defu } from 'defu'
2-
import { withBase } from 'ufo'
3-
import meta from '@privyid/ghostscript/meta'
4-
import { name, version } from '../package.json'
52

63
export interface Config {
74
/**
85
* Enable worker
96
* @default true
107
*/
118
useWorker: boolean,
12-
/**
13-
* Enable CDN
14-
* @default true
15-
*/
16-
useCDN: boolean,
17-
/**
18-
* CDN BaseURL
19-
* @default 'https://unpkg.com/'
20-
*/
21-
cdnURL: string,
229
}
2310

24-
let config: Config = {
25-
useWorker: typeof window !== 'undefined',
26-
useCDN : true,
27-
cdnURL : 'https://unpkg.com/',
28-
}
11+
const config: Config = { useWorker: typeof window !== 'undefined' }
2912

3013
export function useConfig () {
3114
return config
3215
}
3316

3417
export function configureGS (config_: Partial<Config>) {
35-
config = defu(config_, config)
36-
}
37-
38-
export function getWorkerURL () {
39-
return withBase(`${name as string}@${version as string}/dist/rpc.worker.mjs`, config.cdnURL)
40-
}
41-
42-
export function getFileURL (url: string) {
43-
return withBase(`${meta.name}@${meta.version}/dist/${url}`, config.cdnURL)
18+
Object.assign(config, defu(config_, config))
4419
}

packages/ghoulscript/src/core.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import type { GSModule } from '@privyid/ghostscript'
2-
import initGS from '@privyid/ghostscript'
1+
import useGS from '@privyid/ghostscript'
32
import { defu } from 'defu'
4-
import { getFileURL, useConfig } from './config'
5-
import { joinRelativeURL } from 'ufo'
63

74
interface PageRange {
85
start: number,
@@ -66,17 +63,6 @@ export interface CompressOptions {
6663
pageList?: PageList,
6764
}
6865

69-
async function useGS (moduleOverrides?: Partial<GSModule>) {
70-
return await initGS(defu<Partial<GSModule>, [Partial<GSModule>]>(moduleOverrides, {
71-
locateFile (url: string, dir: string) {
72-
if ((typeof window !== 'undefined' || typeof importScripts === 'function') && useConfig().useCDN)
73-
return getFileURL(url)
74-
75-
return joinRelativeURL(dir, url)
76-
},
77-
}))
78-
}
79-
8066
async function createPDF (inputs: ArrayBufferView[], options: Partial<CompressOptions> = {}): Promise<Uint8Array> {
8167
const gs = await useGS()
8268
const opts = defu<CompressOptions, [CompressOptions]>(options, {
@@ -229,7 +215,7 @@ export interface RenderOptions {
229215
graphicsAlphaBits: 1 | 2 | 3 | 4,
230216
/**
231217
* Output format
232-
* @default 'jpeg'
218+
* @default 'jpg'
233219
*/
234220
format: 'jpg' | 'png',
235221
}

packages/ghoulscript/src/rpc.ts

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { Config } from './config'
2-
import { getWorkerURL, useConfig } from './config'
31
import * as core from './core'
42

53
export type Core = typeof core
@@ -10,13 +8,10 @@ export type CommandArgs<C extends Commands> = Parameters<Core[C]>
108

119
export type CommandResult<C extends Commands> = ReturnType<Core[C]>
1210

13-
type PromiseFN = (...args: any[]) => Promise<any>
14-
1511
export interface RPC <C extends Commands = any> {
1612
id: number,
1713
name: C,
1814
args: CommandArgs<C>,
19-
config: Config,
2015
}
2116

2217
export interface RPCResult<C extends Commands = any> {
@@ -27,14 +22,9 @@ export interface RPCResult<C extends Commands = any> {
2722

2823
let worker: Worker
2924

30-
export function useWorkerRPC () {
31-
if (!worker) {
32-
const url = useConfig().useCDN
33-
? getWorkerURL()
34-
: new URL('rpc.worker.mjs', import.meta.url)
35-
36-
worker = new Worker(url, { type: 'module' })
37-
}
25+
export async function useWorkerRPC () {
26+
if (!worker)
27+
worker = new Worker(new URL('rpc.worker.mjs', import.meta.url))
3828

3929
return worker
4030
}
@@ -44,10 +34,10 @@ export function setWorkerRPC (worker_: Worker) {
4434
}
4535

4636
export async function callWorkerRPC<C extends Commands, A extends CommandArgs<C>> (name: C, args: A) {
47-
return await new Promise<CommandResult<C>>((resolve, reject) => {
48-
const id = Date.now()
49-
const worker = useWorkerRPC()
37+
const id = Date.now()
38+
const worker = await useWorkerRPC()
5039

40+
return await new Promise<CommandResult<C>>((resolve, reject) => {
5141
const onMessage = (event: MessageEvent<RPCResult<C>>) => {
5242
if (event.data.id === id) {
5343
cleanUp()
@@ -73,14 +63,13 @@ export async function callWorkerRPC<C extends Commands, A extends CommandArgs<C>
7363
worker.addEventListener('error', onError)
7464

7565
worker.postMessage({
76-
id : id,
77-
name : name,
78-
args : args,
79-
config: useConfig(),
66+
id : id,
67+
name: name,
68+
args: args,
8069
})
8170
})
8271
}
8372

8473
export async function callRPC<C extends Commands> (name: C, args: CommandArgs<C>): Promise<CommandResult<C>> {
85-
return await (core[name] as PromiseFN)(...args)
74+
return await (core[name] as (...args: any[]) => Promise<any>)(...args)
8675
}

0 commit comments

Comments
 (0)