jit-viewer 1.1.4 → 1.2.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.
package/README.md CHANGED
@@ -1,40 +1,39 @@
1
1
  # jit-viewer
2
2
 
3
- Document preview SDK for Vue, React, and vanilla JavaScript. Supports PDF, DOCX, XLSX/XLS, PPTX/PPT, OFD, TXT, Markdown, HTML, images, and built-in watermark rendering.
3
+ Document preview SDK for Vue 3, React, and vanilla JavaScript.
4
+
5
+ Supports PDF, DOCX, XLSX/XLS, CSV/TSV, PPTX/PPT, OFD, TXT, Markdown, HTML, images, video, built-in watermark rendering, and runtime-friendly request adapters.
4
6
 
5
7
  Chinese docs:
6
8
  - [README.zh-CN.md](./README.zh-CN.md)
7
- - [View on GitHub](https://github.com/jitOffice/jit-viewer-sdk/blob/main/packages/core/README.zh-CN.md)
9
+ - [CHANGELOG.md](./CHANGELOG.md)
10
+
11
+ ## What's New
8
12
 
9
- ## Changelog
13
+ ### 1.2.0 - 2026-04-02
10
14
 
11
- ### 1.1.4 - 2026-03-31
15
+ - Added CSV / TSV preview with delimiter detection and table rendering
16
+ - Added native video preview for `mp4`, `webm`, `ogg`, `ogv`, and `mov`
17
+ - Improved HTML, image, and file-type routing in the viewer runtime
18
+ - Fixed CSV layout overflow so the preview stays inside the viewer container
19
+ - Fixed video loading flow for local upload and remote preview cases
20
+ - Hardened branding protection so CSS hiding can trigger warning and self-recovery more reliably
12
21
 
13
- - Improved HTML preview rendering for local files and remote HTML content, with responsive injected styles instead of a raw browser iframe appearance
14
- - Added explicit `html` and `image` preview branches to the viewer runtime, including more stable file type propagation when replacing files dynamically
15
- - Moved the branding footer to the bottom of the viewer with dedicated footer styles so the copyright area remains visible and consistent
16
- - Updated the vanilla HTML demo to load SDK assets more robustly and to support direct `.html` / `.htm` file uploads in the file picker
22
+ See the full history in [CHANGELOG.md](./CHANGELOG.md).
17
23
 
18
24
  ## Features
19
25
 
20
- - Multi-format preview: PDF, Office, OFD, Markdown, HTML, images
26
+ - Multi-format preview: PDF, Office, OFD, Markdown, HTML, images, video, CSV
21
27
  - Cross-framework usage: Vue 3, React, vanilla HTML/JS
22
28
  - Built-in toolbar: zoom, rotate, print, download, pagination
23
- - Theme and locale support: light / dark, zh-CN / en
29
+ - Theme and locale support: light / dark, `zh-CN` / `en`
24
30
  - Watermark support: text watermark, image watermark, opacity, rotation, tiling gap, top/bottom layer
25
- - Supports local files, remote URLs, Blob, ArrayBuffer, proxy URL, and custom request adapters
31
+ - File source support: local file, remote URL, Blob, ArrayBuffer, proxy URL, custom request adapter
26
32
 
27
33
  ## Installation
28
34
 
29
35
  ```bash
30
- # npm
31
36
  npm install jit-viewer
32
-
33
- # yarn
34
- yarn add jit-viewer
35
-
36
- # pnpm
37
- pnpm add jit-viewer
38
37
  ```
39
38
 
40
39
  ## Quick Start
@@ -57,10 +56,8 @@ let viewer: ReturnType<typeof createViewer> | null = null
57
56
  onMounted(() => {
58
57
  viewer = createViewer({
59
58
  target: containerRef.value!,
60
- file: '/demo/test.pdf',
59
+ file: '/demo/test.csv',
61
60
  toolbar: true,
62
- theme: 'light',
63
- locale: 'en',
64
61
  width: '100%',
65
62
  height: 640
66
63
  })
@@ -93,11 +90,12 @@ export default function App() {
93
90
  const viewerRef = useRef<ViewerInstance | null>(null)
94
91
 
95
92
  useEffect(() => {
96
- if (!containerRef.current) return
93
+ if (!containerRef.current)
94
+ return
97
95
 
98
96
  viewerRef.current = createViewer({
99
97
  target: containerRef.current,
100
- file: '/demo/test.pdf',
98
+ file: '/demo/test.mp4',
101
99
  toolbar: true,
102
100
  height: 640
103
101
  })
@@ -120,19 +118,17 @@ export default function App() {
120
118
  <meta charset="UTF-8" />
121
119
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
122
120
  <title>JitViewer Demo</title>
123
- <link rel="stylesheet" href="https://unpkg.com/jit-viewer/dist/iife/jit-viewer.min.css" />
121
+ <link rel="stylesheet" href="https://unpkg.com/jit-viewer@1.2.0/dist/iife/jit-viewer.min.css" />
124
122
  </head>
125
123
  <body>
126
124
  <div id="viewer" style="width:100%;height:640px;"></div>
127
125
 
128
- <script src="https://unpkg.com/jit-viewer/dist/iife/jit-viewer.min.js"></script>
126
+ <script src="https://unpkg.com/jit-viewer@1.2.0/dist/iife/jit-viewer.min.js"></script>
129
127
  <script>
130
128
  const viewer = JitViewer.createViewer({
131
129
  target: '#viewer',
132
130
  file: '/demo/test.pdf',
133
131
  toolbar: true,
134
- theme: 'light',
135
- locale: 'en',
136
132
  width: '100%',
137
133
  height: 640
138
134
  })
@@ -143,474 +139,54 @@ export default function App() {
143
139
  </html>
144
140
  ```
145
141
 
146
- ## Watermark
147
-
148
- Watermarks are configured via `ViewerOptions.watermark`. They affect only the preview layer and do not modify the source file.
149
-
150
- ### Text Watermark
151
-
152
- ```ts
153
- import { createViewer } from 'jit-viewer'
154
- import 'jit-viewer/style.css'
155
-
156
- const viewer = createViewer({
157
- target: '#viewer',
158
- file: '/demo/confidential.pdf',
159
- toolbar: true,
160
- watermark: {
161
- type: 'text',
162
- content: 'CONFIDENTIAL',
163
- fontSize: 20,
164
- color: '#bfbfbf',
165
- opacity: 0.22,
166
- rotate: -25,
167
- gapX: 140,
168
- gapY: 90,
169
- position: 'top'
170
- }
171
- })
172
-
173
- viewer.mount()
174
- ```
175
-
176
- ### Image Watermark
177
-
178
- ```ts
179
- import { createViewer } from 'jit-viewer'
180
- import 'jit-viewer/style.css'
181
-
182
- const viewer = createViewer({
183
- target: '#viewer',
184
- file: '/demo/report.pdf',
185
- watermark: {
186
- type: 'image',
187
- image: '/assets/company-logo.png',
188
- imageWidth: 96,
189
- imageHeight: 96,
190
- opacity: 0.16,
191
- rotate: -20,
192
- gapX: 180,
193
- gapY: 120,
194
- position: 'bottom'
195
- }
196
- })
197
-
198
- viewer.mount()
199
- ```
200
-
201
- ### Vue Component Example
202
-
203
- ```vue
204
- <template>
205
- <Viewer
206
- :file="file"
207
- :toolbar="true"
208
- :theme="'light'"
209
- :locale="'en'"
210
- :watermark="watermark"
211
- width="100%"
212
- height="640px"
213
- />
214
- </template>
215
-
216
- <script setup lang="ts">
217
- import { ref } from 'vue'
218
- import { Viewer } from 'jit-viewer'
219
- import 'jit-viewer/style.css'
220
-
221
- const file = ref('/demo/test.pdf')
222
-
223
- const watermark = ref({
224
- type: 'text' as const,
225
- content: 'JitViewer Demo',
226
- fontSize: 18,
227
- color: '#9aa5b1',
228
- opacity: 0.18,
229
- rotate: -30,
230
- gapX: 120,
231
- gapY: 80,
232
- position: 'top' as const
233
- })
234
- </script>
235
- ```
236
-
237
- ### Re-render With Different Watermarks
238
-
239
- ```ts
240
- import { createViewer, type ViewerInstance, type ViewerOptions } from 'jit-viewer'
241
-
242
- let viewer: ViewerInstance | null = null
243
-
244
- const baseOptions: ViewerOptions = {
245
- target: '#viewer',
246
- file: '/demo/test.pdf',
247
- toolbar: true,
248
- width: '100%',
249
- height: 640
250
- }
251
-
252
- function renderWithWatermark(watermark: ViewerOptions['watermark']) {
253
- viewer?.destroy()
254
-
255
- viewer = createViewer({
256
- ...baseOptions,
257
- watermark
258
- })
259
-
260
- viewer.mount()
261
- }
262
-
263
- renderWithWatermark({
264
- type: 'text',
265
- content: 'First Review',
266
- opacity: 0.2,
267
- rotate: -20,
268
- gapX: 140,
269
- gapY: 90
270
- })
271
-
272
- document.querySelector('#switchImage')?.addEventListener('click', () => {
273
- renderWithWatermark({
274
- type: 'image',
275
- image: '/assets/logo.png',
276
- imageWidth: 88,
277
- imageHeight: 88,
278
- opacity: 0.14,
279
- rotate: -18,
280
- gapX: 170,
281
- gapY: 110
282
- })
283
- })
284
-
285
- document.querySelector('#clearWatermark')?.addEventListener('click', () => {
286
- renderWithWatermark(null)
287
- })
288
- ```
289
-
290
- ## Detailed Examples
291
-
292
- ### Example 1: Contract Preview With Top-Level Confidential Watermark
293
-
294
- ```ts
295
- createViewer({
296
- target: '#viewer',
297
- file: '/contracts/nda.pdf',
298
- filename: 'nda.pdf',
299
- toolbar: true,
300
- pdfRender: 'inset',
301
- watermark: {
302
- type: 'text',
303
- content: 'CONFIDENTIAL',
304
- fontSize: 24,
305
- color: '#d4380d',
306
- opacity: 0.18,
307
- rotate: -32,
308
- gapX: 130,
309
- gapY: 85,
310
- position: 'top'
311
- }
312
- }).mount()
313
- ```
314
-
315
- ### Example 2: Handbook Preview With Brand Logo Watermark
316
-
317
- ```ts
318
- createViewer({
319
- target: '#viewer',
320
- file: '/manuals/employee-handbook.docx',
321
- toolbar: true,
322
- watermark: {
323
- type: 'image',
324
- image: '/assets/brand-watermark.svg',
325
- imageWidth: 72,
326
- imageHeight: 72,
327
- opacity: 0.1,
328
- rotate: -15,
329
- gapX: 210,
330
- gapY: 140,
331
- position: 'bottom'
332
- }
333
- }).mount()
334
- ```
335
-
336
- ### Example 3: Remote File With Auth Headers and Watermark
337
-
338
- ```ts
339
- createViewer({
340
- target: '#viewer',
341
- file: {
342
- url: 'https://api.example.com/files/statement.pdf',
343
- headers: {
344
- Authorization: 'Bearer your-token'
345
- }
346
- },
347
- requestAdapter: async (url, options) => {
348
- const response = await fetch(url, {
349
- method: options?.method || 'GET',
350
- headers: options?.headers
351
- })
352
-
353
- if (!response.ok) {
354
- throw new Error(`Request failed: ${response.status}`)
355
- }
356
-
357
- return response.arrayBuffer()
358
- },
359
- watermark: {
360
- type: 'text',
361
- content: 'Review Copy',
362
- fontSize: 16,
363
- color: '#7d8b99',
364
- opacity: 0.16,
365
- rotate: -28,
366
- gapX: 150,
367
- gapY: 100
368
- }
369
- }).mount()
370
- ```
371
-
372
- ## API
142
+ ## Core API
373
143
 
374
144
  ### `createViewer(options)`
375
145
 
376
- Creates a viewer instance and returns `ViewerInstance`.
377
-
378
- ### `ViewerOptions`
379
-
380
- | Option | Type | Default | Description |
381
- |------|------|--------|------|
382
- | `target` | `HTMLElement \| string` | - | Mount target |
383
- | `file` | `FileSource` | - | File source: URL, File, Blob, ArrayBuffer, or request object |
384
- | `type` | `FileType` | auto | Explicit file type |
385
- | `filename` | `string` | - | Display and download filename |
386
- | `toolbar` | `boolean \| ToolbarConfig` | `true` | Toolbar config |
387
- | `theme` | `'light' \| 'dark' \| ThemeConfig` | `'light'` | Theme |
388
- | `locale` | `'zh-CN' \| 'en' \| LocaleConfig` | `'zh-CN'` | Locale |
389
- | `width` | `string \| number` | `'100%'` | Viewer width |
390
- | `height` | `string \| number` | `'100%'` | Viewer height |
391
- | `className` | `string` | - | Custom class name |
392
- | `style` | `Record<string, string>` | - | Custom inline style |
393
- | `pdfRender` | `'native' \| 'inset'` | `'inset'` | PDF rendering mode |
394
- | `watermark` | `WatermarkConfig \| null` | `null` | Watermark config |
395
- | `proxyUrl` | `string` | - | Proxy URL |
396
- | `requestAdapter` | `RequestAdapter` | - | Custom fetch adapter |
397
- | `renderOptions` | `object` | - | Initial render options such as zoom, rotate, page |
398
- | `onReady` | `() => void` | - | Ready callback |
399
- | `onLoad` | `() => void` | - | Load callback |
400
- | `onError` | `(error: Error) => void` | - | Error callback |
401
- | `onDestroy` | `() => void` | - | Destroy callback |
402
-
403
- ### `WatermarkConfig`
146
+ Creates a viewer instance.
147
+
148
+ Key `ViewerOptions`:
404
149
 
405
150
  | Option | Type | Description |
406
- |------|------|------|
407
- | `type` | `'text' \| 'image'` | Watermark type |
408
- | `content` | `string` | Text content for `type: 'text'` |
409
- | `image` | `string` | Image URL for `type: 'image'` |
410
- | `fontSize` | `number` | Text font size in px |
411
- | `color` | `string` | Text color |
412
- | `fontFamily` | `string` | Font family |
413
- | `fontWeight` | `string \| number` | Font weight |
414
- | `imageWidth` | `number` | Image width in px |
415
- | `imageHeight` | `number` | Image height in px |
416
- | `opacity` | `number` | Opacity, usually between `0` and `1` |
417
- | `rotate` | `number` | Rotation angle in deg |
418
- | `gapX` | `number` | Horizontal gap |
419
- | `gapY` | `number` | Vertical gap |
420
- | `position` | `'top' \| 'bottom'` | Overlay above or below document content |
421
- | `width` | `string \| number` | Watermark container width |
422
- | `height` | `string \| number` | Watermark container height |
151
+ | --- | --- | --- |
152
+ | `target` | `HTMLElement \| string` | Mount target |
153
+ | `file` | `FileSource` | File source |
154
+ | `type` | `FileType` | Explicit file type when auto detection is not enough |
155
+ | `filename` | `string` | Display and download filename |
156
+ | `toolbar` | `ToolbarConfig \| boolean` | Toolbar config |
157
+ | `theme` | `Theme` | `light`, `dark`, or custom theme |
158
+ | `locale` | `Locale` | `zh-CN`, `en`, or custom locale |
159
+ | `watermark` | `WatermarkConfig \| null` | Preview watermark config |
160
+ | `proxyUrl` | `string` | Custom proxy endpoint |
161
+ | `requestAdapter` | `RequestAdapter` | Custom fetch adapter |
162
+ | `renderOptions` | `{ zoom?: number; rotate?: number; page?: number }` | Initial render state |
423
163
 
424
164
  ### `ViewerInstance`
425
165
 
426
166
  | Method | Description |
427
- |------|------|
428
- | `mount(target?)` | Mount viewer |
429
- | `destroy()` | Destroy viewer |
430
- | `setFile(file, filename?)` | Replace current file |
167
+ | --- | --- |
168
+ | `mount(target?)` | Mount the viewer |
169
+ | `destroy()` | Destroy the viewer |
170
+ | `setFile(file, filename?)` | Replace the current file |
171
+ | `setOptions(options)` | Update file, theme, toolbar, watermark, and runtime options |
431
172
  | `getFile()` | Get current file info |
432
173
  | `zoom(scale)` | Set zoom |
433
- | `rotate(degree)` | Set rotation |
434
- | `reset()` | Reset zoom and rotation |
174
+ | `rotate(degree)` | Rotate content |
175
+ | `reset()` | Reset zoom and rotate |
435
176
  | `fullscreen(enable?)` | Toggle fullscreen |
436
- | `prevPage()` | Previous page |
437
- | `nextPage()` | Next page |
438
- | `gotoPage(page)` | Go to page |
439
- | `getPageInfo()` | Get page info |
440
- | `print()` | Print current document |
441
- | `download()` | Download current document |
442
- | `setTheme(theme)` | Set theme |
443
- | `setLocale(locale)` | Set locale |
444
- | `setToolbar(config)` | Set toolbar |
445
- | `on(event, handler)` | Register event |
446
- | `off(event, handler)` | Remove event |
447
- | `getState()` | Get current state |
448
-
449
- ## Supported File Types
450
-
451
- | Format | Extensions | Description |
452
- |------|--------|------|
453
- | PDF | `.pdf` | PDF files |
454
- | Word | `.docx` | Microsoft Word |
455
- | Excel | `.xlsx`, `.xls` | Microsoft Excel |
456
- | PowerPoint | `.pptx`, `.ppt` | Microsoft PowerPoint |
457
- | OFD | `.ofd` | Open Fixed-layout Document |
458
- | Text | `.txt` | Plain text |
459
- | Markdown | `.md`, `.markdown` | Markdown files |
460
- | HTML | `.html`, `.htm` | HTML files or web content |
461
- | Images | `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.svg`, `.bmp`, `.tiff`, `.tif`, `.ico` | Image preview |
462
-
463
- ## Browser Support
464
-
465
- - Chrome >= 80
466
- - Firefox >= 75
467
- - Safari >= 13
468
- - Edge >= 80
469
-
470
- ## License
471
-
472
- [Apache-2.0](./LICENSE)
473
-
474
- ## Links
475
-
476
- - [GitHub](https://github.com/jitOffice/jit-viewer-sdk)
477
- - [Homepage](https://jitword.com/jit-viewer.html)
478
- - [Issues](https://github.com/jitOffice/jit-viewer-sdk/issues)
479
-
480
- ---
481
-
482
- ## 中文文档
483
-
484
- 跨框架文档预览 SDK,支持 PDF、DOCX、XLSX/XLS、PPTX/PPT、OFD、TXT、Markdown、HTML、图片等多种格式,并内置文档水印能力。
485
-
486
- [Back to English](#jit-viewer)
487
-
488
- ## 特性
489
-
490
- - 多格式预览:PDF、Office、OFD、Markdown、HTML、图片
491
- - 跨框架使用:Vue 3、React、原生 HTML/JS
492
- - 内置工具栏:缩放、旋转、打印、下载、分页
493
- - 主题与国际化:浅色 / 深色,中文 / 英文
494
- - 水印能力:文本水印、图片水印、透明度、旋转、平铺间距、顶层/底层显示
495
- - 支持本地文件、远程 URL、Blob、ArrayBuffer、自定义请求适配器
496
-
497
- ## 安装
498
-
499
- ```bash
500
- # npm
501
- npm install jit-viewer
502
-
503
- # yarn
504
- yarn add jit-viewer
505
-
506
- # pnpm
507
- pnpm add jit-viewer
508
- ```
509
-
510
- ## 快速开始
511
-
512
- ### Vue 3
513
-
514
- ```vue
515
- <template>
516
- <div ref="containerRef" class="viewer-container"></div>
517
- </template>
518
-
519
- <script setup lang="ts">
520
- import { onMounted, onUnmounted, ref } from 'vue'
521
- import { createViewer } from 'jit-viewer'
522
- import 'jit-viewer/style.css'
523
-
524
- const containerRef = ref<HTMLElement | null>(null)
525
- let viewer: ReturnType<typeof createViewer> | null = null
526
-
527
- onMounted(() => {
528
- viewer = createViewer({
529
- target: containerRef.value!,
530
- file: '/demo/test.pdf',
531
- toolbar: true,
532
- theme: 'light',
533
- locale: 'zh-CN',
534
- width: '100%',
535
- height: 640
536
- })
537
-
538
- viewer.mount()
539
- })
177
+ | `prevPage()` / `nextPage()` / `gotoPage(page)` | Pagination controls |
178
+ | `getPageInfo()` | Get page state |
179
+ | `print()` | Print current view |
180
+ | `download()` | Download current file |
181
+ | `setTheme(theme)` | Update theme |
182
+ | `setLocale(locale)` | Update locale |
183
+ | `setToolbar(config)` | Update toolbar |
184
+ | `on(event, handler)` / `off(event, handler)` | Event subscription |
185
+ | `getState()` | Get runtime state |
540
186
 
541
- onUnmounted(() => {
542
- viewer?.destroy()
543
- })
544
- </script>
545
- ```
546
-
547
- ### React
548
-
549
- ```tsx
550
- import { useEffect, useRef } from 'react'
551
- import { createViewer, type ViewerInstance } from 'jit-viewer'
552
- import 'jit-viewer/style.css'
553
-
554
- export default function App() {
555
- const containerRef = useRef<HTMLDivElement | null>(null)
556
- const viewerRef = useRef<ViewerInstance | null>(null)
557
-
558
- useEffect(() => {
559
- if (!containerRef.current) return
560
-
561
- viewerRef.current = createViewer({
562
- target: containerRef.current,
563
- file: '/demo/test.pdf',
564
- toolbar: true,
565
- height: 640
566
- })
567
-
568
- viewerRef.current.mount()
569
-
570
- return () => viewerRef.current?.destroy()
571
- }, [])
572
-
573
- return <div ref={containerRef} style={{ width: '100%', height: 640 }} />
574
- }
575
- ```
576
-
577
- ### 原生 HTML / JS
578
-
579
- ```html
580
- <!DOCTYPE html>
581
- <html lang="zh-CN">
582
- <head>
583
- <meta charset="UTF-8" />
584
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
585
- <title>JitViewer Demo</title>
586
- <link rel="stylesheet" href="https://unpkg.com/jit-viewer/dist/iife/jit-viewer.min.css" />
587
- </head>
588
- <body>
589
- <div id="viewer" style="width:100%;height:640px;"></div>
590
-
591
- <script src="https://unpkg.com/jit-viewer/dist/iife/jit-viewer.min.js"></script>
592
- <script>
593
- const viewer = JitViewer.createViewer({
594
- target: '#viewer',
595
- file: '/demo/test.pdf',
596
- toolbar: true,
597
- theme: 'light',
598
- locale: 'zh-CN',
599
- width: '100%',
600
- height: 640
601
- })
602
-
603
- viewer.mount()
604
- </script>
605
- </body>
606
- </html>
607
- ```
608
-
609
- ## 水印使用
610
-
611
- 水印通过 `ViewerOptions.watermark` 配置,支持文本水印和图片水印。水印只作用于预览层,不会修改原始文件内容。
187
+ ## Watermark
612
188
 
613
- ### 文本水印
189
+ Watermarks are configured with `ViewerOptions.watermark`. They apply only to the preview layer and do not modify the original file.
614
190
 
615
191
  ```ts
616
192
  import { createViewer } from 'jit-viewer'
@@ -618,15 +194,12 @@ import 'jit-viewer/style.css'
618
194
 
619
195
  const viewer = createViewer({
620
196
  target: '#viewer',
621
- file: '/demo/confidential.pdf',
622
- toolbar: true,
197
+ file: '/demo/report.pdf',
623
198
  watermark: {
624
199
  type: 'text',
625
- content: '内部资料 严禁外传',
626
- fontSize: 20,
627
- color: '#bfbfbf',
628
- opacity: 0.22,
629
- rotate: -25,
200
+ content: 'CONFIDENTIAL',
201
+ opacity: 0.18,
202
+ rotate: -24,
630
203
  gapX: 140,
631
204
  gapY: 90,
632
205
  position: 'top'
@@ -636,306 +209,25 @@ const viewer = createViewer({
636
209
  viewer.mount()
637
210
  ```
638
211
 
639
- ### 图片水印
640
-
641
- ```ts
642
- import { createViewer } from 'jit-viewer'
643
- import 'jit-viewer/style.css'
644
-
645
- const viewer = createViewer({
646
- target: '#viewer',
647
- file: '/demo/report.pdf',
648
- watermark: {
649
- type: 'image',
650
- image: '/assets/company-logo.png',
651
- imageWidth: 96,
652
- imageHeight: 96,
653
- opacity: 0.16,
654
- rotate: -20,
655
- gapX: 180,
656
- gapY: 120,
657
- position: 'bottom'
658
- }
659
- })
660
-
661
- viewer.mount()
662
- ```
663
-
664
- ### Vue 组件方式
665
-
666
- ```vue
667
- <template>
668
- <Viewer
669
- :file="file"
670
- :toolbar="true"
671
- :theme="'light'"
672
- :locale="'zh-CN'"
673
- :watermark="watermark"
674
- width="100%"
675
- height="640px"
676
- />
677
- </template>
678
-
679
- <script setup lang="ts">
680
- import { ref } from 'vue'
681
- import { Viewer } from 'jit-viewer'
682
- import 'jit-viewer/style.css'
683
-
684
- const file = ref('/demo/test.pdf')
685
-
686
- const watermark = ref({
687
- type: 'text' as const,
688
- content: 'JitViewer Demo',
689
- fontSize: 18,
690
- color: '#9aa5b1',
691
- opacity: 0.18,
692
- rotate: -30,
693
- gapX: 120,
694
- gapY: 80,
695
- position: 'top' as const
696
- })
697
- </script>
698
- ```
699
-
700
- ### 动态切换不同水印
701
-
702
- ```ts
703
- import { createViewer, type ViewerInstance, type ViewerOptions } from 'jit-viewer'
704
-
705
- let viewer: ViewerInstance | null = null
706
-
707
- const baseOptions: ViewerOptions = {
708
- target: '#viewer',
709
- file: '/demo/test.pdf',
710
- toolbar: true,
711
- width: '100%',
712
- height: 640
713
- }
714
-
715
- function renderWithWatermark(watermark: ViewerOptions['watermark']) {
716
- viewer?.destroy()
717
-
718
- viewer = createViewer({
719
- ...baseOptions,
720
- watermark
721
- })
722
-
723
- viewer.mount()
724
- }
725
-
726
- renderWithWatermark({
727
- type: 'text',
728
- content: '首次预览',
729
- opacity: 0.2,
730
- rotate: -20,
731
- gapX: 140,
732
- gapY: 90
733
- })
734
-
735
- document.querySelector('#switchImage')?.addEventListener('click', () => {
736
- renderWithWatermark({
737
- type: 'image',
738
- image: '/assets/logo.png',
739
- imageWidth: 88,
740
- imageHeight: 88,
741
- opacity: 0.14,
742
- rotate: -18,
743
- gapX: 170,
744
- gapY: 110
745
- })
746
- })
747
-
748
- document.querySelector('#clearWatermark')?.addEventListener('click', () => {
749
- renderWithWatermark(null)
750
- })
751
- ```
752
-
753
- ## 详细示例
754
-
755
- ### 示例 1:合同预览 + 顶层保密文本水印
756
-
757
- ```ts
758
- createViewer({
759
- target: '#viewer',
760
- file: '/contracts/nda.pdf',
761
- filename: 'nda.pdf',
762
- toolbar: true,
763
- pdfRender: 'inset',
764
- watermark: {
765
- type: 'text',
766
- content: 'CONFIDENTIAL',
767
- fontSize: 24,
768
- color: '#d4380d',
769
- opacity: 0.18,
770
- rotate: -32,
771
- gapX: 130,
772
- gapY: 85,
773
- position: 'top'
774
- }
775
- }).mount()
776
- ```
777
-
778
- ### 示例 2:员工手册预览 + 底层品牌 Logo 水印
779
-
780
- ```ts
781
- createViewer({
782
- target: '#viewer',
783
- file: '/manuals/employee-handbook.docx',
784
- toolbar: true,
785
- watermark: {
786
- type: 'image',
787
- image: '/assets/brand-watermark.svg',
788
- imageWidth: 72,
789
- imageHeight: 72,
790
- opacity: 0.1,
791
- rotate: -15,
792
- gapX: 210,
793
- gapY: 140,
794
- position: 'bottom'
795
- }
796
- }).mount()
797
- ```
798
-
799
- ### 示例 3:自定义请求头 + 水印
800
-
801
- ```ts
802
- createViewer({
803
- target: '#viewer',
804
- file: {
805
- url: 'https://api.example.com/files/statement.pdf',
806
- headers: {
807
- Authorization: 'Bearer your-token'
808
- }
809
- },
810
- requestAdapter: async (url, options) => {
811
- const response = await fetch(url, {
812
- method: options?.method || 'GET',
813
- headers: options?.headers
814
- })
212
+ ## Supported Formats
815
213
 
816
- if (!response.ok) {
817
- throw new Error(`Request failed: ${response.status}`)
818
- }
214
+ | Type | Extensions |
215
+ | --- | --- |
216
+ | PDF | `.pdf` |
217
+ | Word | `.docx` |
218
+ | Excel | `.xlsx`, `.xls` |
219
+ | CSV | `.csv`, `.tsv` |
220
+ | PowerPoint | `.pptx`, `.ppt` |
221
+ | OFD | `.ofd` |
222
+ | Text | `.txt` |
223
+ | Markdown | `.md`, `.markdown` |
224
+ | HTML | `.html`, `.htm` |
225
+ | Images | `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.svg`, `.bmp`, `.tiff`, `.tif`, `.ico` |
226
+ | Video | `.mp4`, `.webm`, `.ogg`, `.ogv`, `.mov` |
819
227
 
820
- return response.arrayBuffer()
821
- },
822
- watermark: {
823
- type: 'text',
824
- content: '审阅版',
825
- fontSize: 16,
826
- color: '#7d8b99',
827
- opacity: 0.16,
828
- rotate: -28,
829
- gapX: 150,
830
- gapY: 100
831
- }
832
- }).mount()
833
- ```
834
-
835
- ## API
836
-
837
- ### `createViewer(options)`
838
-
839
- 创建预览器实例,返回 `ViewerInstance`。
840
-
841
- ### `ViewerOptions`
842
-
843
- | 参数 | 类型 | 默认值 | 说明 |
844
- |------|------|--------|------|
845
- | `target` | `HTMLElement \| string` | - | 挂载目标元素 |
846
- | `file` | `FileSource` | - | 文件源,支持 URL、File、Blob、ArrayBuffer、带请求参数对象 |
847
- | `type` | `FileType` | 自动识别 | 手动指定文件类型 |
848
- | `filename` | `string` | - | 文件名,用于显示和下载 |
849
- | `toolbar` | `boolean \| ToolbarConfig` | `true` | 工具栏配置 |
850
- | `theme` | `'light' \| 'dark' \| ThemeConfig` | `'light'` | 主题配置 |
851
- | `locale` | `'zh-CN' \| 'en' \| LocaleConfig` | `'zh-CN'` | 语言配置 |
852
- | `width` | `string \| number` | `'100%'` | 预览器宽度 |
853
- | `height` | `string \| number` | `'100%'` | 预览器高度 |
854
- | `className` | `string` | - | 自定义类名 |
855
- | `style` | `Record<string, string>` | - | 自定义样式 |
856
- | `pdfRender` | `'native' \| 'inset'` | `'inset'` | PDF 预览方式 |
857
- | `watermark` | `WatermarkConfig \| null` | `null` | 文档水印配置 |
858
- | `proxyUrl` | `string` | - | 自定义代理地址 |
859
- | `requestAdapter` | `RequestAdapter` | - | 自定义请求适配器 |
860
- | `renderOptions` | `object` | - | 初始缩放、旋转、页码等渲染配置 |
861
- | `onReady` | `() => void` | - | 预览器就绪回调 |
862
- | `onLoad` | `() => void` | - | 文件加载完成回调 |
863
- | `onError` | `(error: Error) => void` | - | 错误回调 |
864
- | `onDestroy` | `() => void` | - | 销毁回调 |
865
-
866
- ### `WatermarkConfig`
867
-
868
- | 参数 | 类型 | 说明 |
869
- |------|------|------|
870
- | `type` | `'text' \| 'image'` | 水印类型 |
871
- | `content` | `string` | 文本水印内容,`type: 'text'` 时使用 |
872
- | `image` | `string` | 图片地址,`type: 'image'` 时使用 |
873
- | `fontSize` | `number` | 文字字号,单位 `px` |
874
- | `color` | `string` | 文字颜色 |
875
- | `fontFamily` | `string` | 文字字体 |
876
- | `fontWeight` | `string \| number` | 字重 |
877
- | `imageWidth` | `number` | 图片水印宽度,单位 `px` |
878
- | `imageHeight` | `number` | 图片水印高度,单位 `px` |
879
- | `opacity` | `number` | 透明度,范围建议 `0 ~ 1` |
880
- | `rotate` | `number` | 旋转角度,单位 `deg` |
881
- | `gapX` | `number` | 水平平铺间距 |
882
- | `gapY` | `number` | 垂直平铺间距 |
883
- | `position` | `'top' \| 'bottom'` | 显示在文档上方或下方 |
884
- | `width` | `string \| number` | 水印容器宽度 |
885
- | `height` | `string \| number` | 水印容器高度 |
886
-
887
- ### `ViewerInstance`
888
-
889
- | 方法 | 说明 |
890
- |------|------|
891
- | `mount(target?)` | 挂载到目标容器 |
892
- | `destroy()` | 销毁实例 |
893
- | `setFile(file, filename?)` | 动态切换文件 |
894
- | `getFile()` | 获取当前文件信息 |
895
- | `zoom(scale)` | 设置缩放比例 |
896
- | `rotate(degree)` | 设置旋转角度 |
897
- | `reset()` | 重置缩放和旋转 |
898
- | `fullscreen(enable?)` | 切换全屏 |
899
- | `prevPage()` | 上一页 |
900
- | `nextPage()` | 下一页 |
901
- | `gotoPage(page)` | 跳转到指定页 |
902
- | `getPageInfo()` | 获取页码信息 |
903
- | `print()` | 打印当前文档 |
904
- | `download()` | 下载当前文档 |
905
- | `setTheme(theme)` | 设置主题 |
906
- | `setLocale(locale)` | 设置语言 |
907
- | `setToolbar(config)` | 设置工具栏 |
908
- | `on(event, handler)` | 监听事件 |
909
- | `off(event, handler)` | 取消监听事件 |
910
- | `getState()` | 获取当前状态 |
911
-
912
- ## 支持的文件格式
913
-
914
- | 格式 | 扩展名 | 说明 |
915
- |------|--------|------|
916
- | PDF | `.pdf` | PDF 文档 |
917
- | Word | `.docx` | Microsoft Word 文档 |
918
- | Excel | `.xlsx`, `.xls` | Microsoft Excel 表格 |
919
- | PowerPoint | `.pptx`, `.ppt` | Microsoft PowerPoint 演示文稿 |
920
- | OFD | `.ofd` | 电子公文格式 |
921
- | 文本 | `.txt` | 纯文本文件 |
922
- | Markdown | `.md`, `.markdown` | Markdown 文档 |
923
- | HTML | `.html`, `.htm` | HTML 文件或网页内容 |
924
- | 图片 | `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.svg`, `.bmp`, `.tiff`, `.tif`, `.ico` | 图片预览 |
925
-
926
- ## 浏览器支持
927
-
928
- - Chrome >= 80
929
- - Firefox >= 75
930
- - Safari >= 13
931
- - Edge >= 80
932
-
933
- ## 许可证
934
-
935
- [Apache-2.0](./LICENSE)
936
-
937
- ## 链接
228
+ ## Links
938
229
 
230
+ - [Chinese README](./README.zh-CN.md)
231
+ - [Changelog](./CHANGELOG.md)
939
232
  - [GitHub](https://github.com/jitOffice/jit-viewer-sdk)
940
- - [主页](https://jitword.com/jit-viewer.html)
941
- - [问题反馈](https://github.com/jitOffice/jit-viewer-sdk/issues)
233
+ - [Homepage](https://jitword.com/jit-viewer.html)