@crosscopy/clipboard 0.2.6 → 0.3.3

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,54 +1,210 @@
1
1
  # Clipboard
2
2
 
3
+ [![NPM Version](https://img.shields.io/npm/v/@crosscopy/clipboard)](https://www.npmjs.com/package/@crosscopy/clipboard)
4
+ [![CI](https://github.com/CrossCopy/clipboard/actions/workflows/CI.yml/badge.svg)](https://github.com/CrossCopy/clipboard/actions/workflows/CI.yml)
5
+
3
6
  **NPM Package**: https://www.npmjs.com/package/@crosscopy/clipboard
4
7
 
5
8
  **GitHub**: https://github.com/crosscopy/clipboard
6
9
 
7
- > This is a clipboard API npm package that allows you to copy and paste data to and from the clipboard.
8
- > There doesn't seem to be a good clipboard package for node.js (that supports data format beyond text), so I decided to make one.
9
- > Data Format Supported
10
- >
11
- > - Text
12
- > - Image
13
- > - Rich Text Format
14
- > - Files
15
- > - HTML
10
+ Cross-platform native clipboard for Node.js. Read, write, and watch the system clipboard with support for multiple data formats.
16
11
 
17
- ## Acknowledgements
12
+ ### Supported Formats
13
+
14
+ - Text
15
+ - HTML
16
+ - Rich Text (RTF)
17
+ - Images (PNG binary / base64)
18
+ - Files
19
+ - Arbitrary binary buffers (custom format strings)
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm install @crosscopy/clipboard
25
+ # or
26
+ yarn add @crosscopy/clipboard
27
+ ```
18
28
 
19
- - [ChurchTao/clipboard-rs](https://github.com/ChurchTao/clipboard-rs) is written in rust, which is used to provide the native clipboard support for this package across Linux, Windows and MacOS. This package is basically a wrapper around this rust package.
20
- - https://crates.io/crates/clipboard-rs
21
- - [napi.rs](https://napi.rs/) was used to create the node.js addon for this package, so that API calls written in rust can be called from node.js.
29
+ ## Quick Start
30
+
31
+ ```typescript
32
+ import {
33
+ getText, setText,
34
+ hasText, hasImage,
35
+ getImageBase64,
36
+ startWatch,
37
+ } from '@crosscopy/clipboard'
38
+
39
+ // Read & write text
40
+ await setText('hello world')
41
+ console.log(await getText()) // "hello world"
42
+
43
+ // Check what's on the clipboard
44
+ console.log(hasText()) // true
45
+ console.log(hasImage()) // false
46
+
47
+ // Watch for changes
48
+ const watcher = startWatch(() => {
49
+ console.log('clipboard changed!')
50
+ })
51
+ // ... later
52
+ watcher.stop()
53
+ ```
22
54
 
23
55
  ## API
24
56
 
25
- Detailed API function declarations can be found in the [index.d.ts](./index.d.ts).
57
+ Full type declarations are in [`index.d.ts`](./index.d.ts).
58
+
59
+ ### Text
60
+
61
+ | Function | Signature | Description |
62
+ |---|---|---|
63
+ | `hasText` | `() => boolean` | Check if clipboard contains text |
64
+ | `getText` | `() => Promise<string>` | Read text from clipboard |
65
+ | `setText` | `(text: string) => Promise<void>` | Write text to clipboard |
66
+
67
+ ```typescript
68
+ import { hasText, getText, setText } from '@crosscopy/clipboard'
69
+
70
+ await setText('copied!')
71
+ if (hasText()) {
72
+ console.log(await getText())
73
+ }
74
+ ```
75
+
76
+ ### HTML
77
+
78
+ | Function | Signature | Description |
79
+ |---|---|---|
80
+ | `hasHtml` | `() => boolean` | Check if clipboard contains HTML |
81
+ | `getHtml` | `() => Promise<string>` | Read HTML string from clipboard |
82
+ | `setHtml` | `(html: string) => Promise<void>` | Write HTML string to clipboard |
83
+
84
+ ```typescript
85
+ import { setHtml, getHtml } from '@crosscopy/clipboard'
86
+
87
+ await setHtml('<b>bold</b>')
88
+ console.log(await getHtml())
89
+ ```
90
+
91
+ ### Rich Text (RTF)
92
+
93
+ | Function | Signature | Description |
94
+ |---|---|---|
95
+ | `hasRtf` | `() => boolean` | Check if clipboard contains RTF |
96
+ | `getRtf` | `() => Promise<string>` | Read RTF string from clipboard |
97
+ | `setRtf` | `(rtf: string) => Promise<void>` | Write RTF string to clipboard |
98
+
99
+ ### Image
100
+
101
+ | Function | Signature | Description |
102
+ |---|---|---|
103
+ | `hasImage` | `() => boolean` | Check if clipboard contains an image |
104
+ | `getImageBinary` | `() => Promise<Array<number>>` | Read image as PNG bytes |
105
+ | `getImageBase64` | `() => Promise<string>` | Read image as base64-encoded PNG |
106
+ | `setImageBinary` | `(imageBytes: Array<number>) => Promise<void>` | Write PNG bytes to clipboard |
107
+ | `setImageBase64` | `(base64Str: string) => Promise<void>` | Write base64-encoded PNG to clipboard |
108
+
109
+ ```typescript
110
+ import { hasImage, getImageBase64, setImageBinary } from '@crosscopy/clipboard'
111
+ import { readFileSync } from 'fs'
26
112
 
27
- Or you can refer to the source code in [src/lib.rs](./src/lib.rs).
113
+ // Write a PNG file to clipboard
114
+ const png = readFileSync('screenshot.png')
115
+ await setImageBinary(Array.from(png))
28
116
 
29
- ## Sample
117
+ // Read as base64
118
+ if (hasImage()) {
119
+ const b64 = await getImageBase64()
120
+ console.log(`data:image/png;base64,${b64}`)
121
+ }
122
+ ```
30
123
 
31
- ```javascript
32
- import Clipboard from "@crosscopy/clipboard";
124
+ ### Files
33
125
 
34
- console.log(await Clipboard.getText());
126
+ | Function | Signature | Description |
127
+ |---|---|---|
128
+ | `hasFiles` | `() => boolean` | Check if clipboard contains file references |
129
+ | `getFiles` | `() => Promise<Array<string>>` | Read file paths from clipboard |
130
+ | `setFiles` | `(files: Array<string>) => Promise<void>` | Write file paths to clipboard |
35
131
 
36
- console.log(await Clipboard.getHtml());
132
+ ```typescript
133
+ import { hasFiles, getFiles } from '@crosscopy/clipboard'
37
134
 
38
- if (await Clipboard.hasImage()) {
39
- console.log(await Clipboard.getImageBase64());
40
- } else {
41
- console.log("No Image");
135
+ if (hasFiles()) {
136
+ const paths = await getFiles()
137
+ console.log(paths) // ["/Users/you/file.txt", ...]
42
138
  }
43
139
  ```
44
140
 
45
- ## Plan
141
+ ### Buffer (Custom Formats)
142
+
143
+ | Function | Signature | Description |
144
+ |---|---|---|
145
+ | `getBuffer` | `(format: string) => Promise<Array<number>>` | Read raw bytes for a given format |
146
+ | `setBuffer` | `(format: string, buffer: Array<number>) => Promise<void>` | Write raw bytes for a given format |
147
+
148
+ ```typescript
149
+ import { setBuffer, getBuffer } from '@crosscopy/clipboard'
150
+
151
+ await setBuffer('com.myapp.custom', [0x01, 0x02, 0x03])
152
+ const data = await getBuffer('com.myapp.custom')
153
+ ```
154
+
155
+ ### Utilities
156
+
157
+ | Function | Signature | Description |
158
+ |---|---|---|
159
+ | `availableFormats` | `() => Array<string>` | List all format types currently on the clipboard |
160
+ | `clear` | `() => Promise<void>` | Clear the clipboard |
161
+
162
+ ### Clipboard Watcher
163
+
164
+ Monitor clipboard changes using OS-native notifications.
165
+
166
+ | Function / Method | Signature | Description |
167
+ |---|---|---|
168
+ | `startWatch` | `(callback: () => void) => ClipboardWatcherJs` | Start watching; returns a handle |
169
+ | `watcher.stop()` | `() => void` | Stop the watcher |
170
+ | `watcher.isRunning` | `boolean` (getter) | Whether the watcher is active |
171
+
172
+ ```typescript
173
+ import { startWatch, getText } from '@crosscopy/clipboard'
46
174
 
47
- A clipboard listener will be added soon for monitoring clipboard changes and get notified when the clipboard content changes.
175
+ const watcher = startWatch(async () => {
176
+ console.log('changed:', await getText())
177
+ })
178
+
179
+ console.log(watcher.isRunning) // true
180
+
181
+ // Stop when done
182
+ watcher.stop()
183
+ console.log(watcher.isRunning) // false
184
+ ```
185
+
186
+ The watcher runs on a background thread using native clipboard change events — there is no polling from JavaScript. Call `stop()` to clean up.
187
+
188
+ ## Platform Support
189
+
190
+ | Platform | Architectures |
191
+ |---|---|
192
+ | macOS | x64, arm64 (Apple Silicon), universal |
193
+ | Windows | x64, arm64 |
194
+ | Linux | x64 (glibc) |
195
+
196
+ ## Acknowledgements
197
+
198
+ - [ChurchTao/clipboard-rs](https://github.com/ChurchTao/clipboard-rs) provides the native clipboard support across Linux, Windows, and macOS.
199
+ - [napi.rs](https://napi.rs/) bridges the Rust implementation to Node.js.
48
200
 
49
201
  ## Publish
50
202
 
51
- Everything is done with GitHub Action.
203
+ Everything is done with GitHub Actions.
52
204
 
53
- Run `npm version patch` to bump the version.
54
- Then `git push --follow-tags` to push the changes and tags to GitHub. GitHub Action will automatically build and publish.
205
+ Run `npm version patch` to bump the version, then `git push --follow-tags`. GitHub Actions will build and publish automatically.
206
+
207
+ ```bash
208
+ npm version patch
209
+ git push --follow-tags
210
+ ```
@@ -0,0 +1,205 @@
1
+ # Clipboard
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/@crosscopy/clipboard)](https://www.npmjs.com/package/@crosscopy/clipboard)
4
+ [![CI](https://github.com/CrossCopy/clipboard/actions/workflows/CI.yml/badge.svg)](https://github.com/CrossCopy/clipboard/actions/workflows/CI.yml)
5
+
6
+ **NPM Package**: https://www.npmjs.com/package/@crosscopy/clipboard
7
+
8
+ **GitHub**: https://github.com/crosscopy/clipboard
9
+
10
+ 跨平台原生剪贴板库,适用于 Node.js。支持读取、写入和监听系统剪贴板,兼容多种数据格式。
11
+
12
+ ### 支持的格式
13
+
14
+ - 纯文本
15
+ - HTML
16
+ - 富文本 (RTF)
17
+ - 图片 (PNG 二进制 / base64)
18
+ - 文件
19
+ - 任意二进制数据 (自定义格式字符串)
20
+
21
+ ## 安装
22
+
23
+ ```bash
24
+ npm install @crosscopy/clipboard
25
+ # 或
26
+ yarn add @crosscopy/clipboard
27
+ ```
28
+
29
+ ## 快速开始
30
+
31
+ ```typescript
32
+ import {
33
+ getText, setText,
34
+ hasText, hasImage,
35
+ getImageBase64,
36
+ startWatch,
37
+ } from '@crosscopy/clipboard'
38
+
39
+ // 读写文本
40
+ await setText('hello world')
41
+ console.log(await getText()) // "hello world"
42
+
43
+ // 检查剪贴板内容类型
44
+ console.log(hasText()) // true
45
+ console.log(hasImage()) // false
46
+
47
+ // 监听剪贴板变化
48
+ const watcher = startWatch(() => {
49
+ console.log('剪贴板内容已变化!')
50
+ })
51
+ // ... 之后停止监听
52
+ watcher.stop()
53
+ ```
54
+
55
+ ## API
56
+
57
+ 完整的类型声明请参阅 [`index.d.ts`](./index.d.ts)。
58
+
59
+ ### 纯文本
60
+
61
+ | 函数 | 签名 | 说明 |
62
+ |---|---|---|
63
+ | `hasText` | `() => boolean` | 检查剪贴板是否包含文本 |
64
+ | `getText` | `() => Promise<string>` | 从剪贴板读取文本 |
65
+ | `setText` | `(text: string) => Promise<void>` | 将文本写入剪贴板 |
66
+
67
+ ```typescript
68
+ import { hasText, getText, setText } from '@crosscopy/clipboard'
69
+
70
+ await setText('已复制!')
71
+ if (hasText()) {
72
+ console.log(await getText())
73
+ }
74
+ ```
75
+
76
+ ### HTML
77
+
78
+ | 函数 | 签名 | 说明 |
79
+ |---|---|---|
80
+ | `hasHtml` | `() => boolean` | 检查剪贴板是否包含 HTML |
81
+ | `getHtml` | `() => Promise<string>` | 从剪贴板读取 HTML 字符串 |
82
+ | `setHtml` | `(html: string) => Promise<void>` | 将 HTML 字符串写入剪贴板 |
83
+
84
+ ```typescript
85
+ import { setHtml, getHtml } from '@crosscopy/clipboard'
86
+
87
+ await setHtml('<b>粗体</b>')
88
+ console.log(await getHtml())
89
+ ```
90
+
91
+ ### 富文本 (RTF)
92
+
93
+ | 函数 | 签名 | 说明 |
94
+ |---|---|---|
95
+ | `hasRtf` | `() => boolean` | 检查剪贴板是否包含 RTF |
96
+ | `getRtf` | `() => Promise<string>` | 从剪贴板读取 RTF 字符串 |
97
+ | `setRtf` | `(rtf: string) => Promise<void>` | 将 RTF 字符串写入剪贴板 |
98
+
99
+ ### 图片
100
+
101
+ | 函数 | 签名 | 说明 |
102
+ |---|---|---|
103
+ | `hasImage` | `() => boolean` | 检查剪贴板是否包含图片 |
104
+ | `getImageBinary` | `() => Promise<Array<number>>` | 以 PNG 字节数组形式读取图片 |
105
+ | `getImageBase64` | `() => Promise<string>` | 以 base64 编码的 PNG 形式读取图片 |
106
+ | `setImageBinary` | `(imageBytes: Array<number>) => Promise<void>` | 将 PNG 字节数组写入剪贴板 |
107
+ | `setImageBase64` | `(base64Str: string) => Promise<void>` | 将 base64 编码的 PNG 写入剪贴板 |
108
+
109
+ ```typescript
110
+ import { hasImage, getImageBase64, setImageBinary } from '@crosscopy/clipboard'
111
+ import { readFileSync } from 'fs'
112
+
113
+ // 将 PNG 文件写入剪贴板
114
+ const png = readFileSync('screenshot.png')
115
+ await setImageBinary(Array.from(png))
116
+
117
+ // 以 base64 形式读取
118
+ if (hasImage()) {
119
+ const b64 = await getImageBase64()
120
+ console.log(`data:image/png;base64,${b64}`)
121
+ }
122
+ ```
123
+
124
+ ### 文件
125
+
126
+ | 函数 | 签名 | 说明 |
127
+ |---|---|---|
128
+ | `hasFiles` | `() => boolean` | 检查剪贴板是否包含文件引用 |
129
+ | `getFiles` | `() => Promise<Array<string>>` | 从剪贴板读取文件路径列表 |
130
+ | `setFiles` | `(files: Array<string>) => Promise<void>` | 将文件路径列表写入剪贴板 |
131
+
132
+ ```typescript
133
+ import { hasFiles, getFiles } from '@crosscopy/clipboard'
134
+
135
+ if (hasFiles()) {
136
+ const paths = await getFiles()
137
+ console.log(paths) // ["/Users/you/file.txt", ...]
138
+ }
139
+ ```
140
+
141
+ ### Buffer (自定义格式)
142
+
143
+ | 函数 | 签名 | 说明 |
144
+ |---|---|---|
145
+ | `getBuffer` | `(format: string) => Promise<Array<number>>` | 按指定格式读取原始字节 |
146
+ | `setBuffer` | `(format: string, buffer: Array<number>) => Promise<void>` | 按指定格式写入原始字节 |
147
+
148
+ ```typescript
149
+ import { setBuffer, getBuffer } from '@crosscopy/clipboard'
150
+
151
+ await setBuffer('com.myapp.custom', [0x01, 0x02, 0x03])
152
+ const data = await getBuffer('com.myapp.custom')
153
+ ```
154
+
155
+ ### 工具函数
156
+
157
+ | 函数 | 签名 | 说明 |
158
+ |---|---|---|
159
+ | `availableFormats` | `() => Array<string>` | 列出剪贴板中当前所有的数据格式 |
160
+ | `clear` | `() => Promise<void>` | 清空剪贴板 |
161
+
162
+ ### 剪贴板监听
163
+
164
+ 使用操作系统原生通知机制监听剪贴板变化。
165
+
166
+ | 函数 / 方法 | 签名 | 说明 |
167
+ |---|---|---|
168
+ | `startWatch` | `(callback: () => void) => ClipboardWatcherJs` | 开始监听,返回监听句柄 |
169
+ | `watcher.stop()` | `() => void` | 停止监听 |
170
+ | `watcher.isRunning` | `boolean` (getter) | 监听器是否正在运行 |
171
+
172
+ ```typescript
173
+ import { startWatch, getText } from '@crosscopy/clipboard'
174
+
175
+ const watcher = startWatch(async () => {
176
+ console.log('剪贴板已变化:', await getText())
177
+ })
178
+
179
+ console.log(watcher.isRunning) // true
180
+
181
+ // 不再需要时停止监听
182
+ watcher.stop()
183
+ console.log(watcher.isRunning) // false
184
+ ```
185
+
186
+ 监听器在后台线程中运行,使用操作系统原生的剪贴板变化事件,JavaScript 侧无需轮询。使用完毕后调用 `stop()` 释放资源。
187
+
188
+ ## 平台支持
189
+
190
+ | 平台 | 架构 |
191
+ |---|---|
192
+ | macOS | x64, arm64 (Apple Silicon), universal |
193
+ | Windows | x64, arm64 |
194
+ | Linux | x64 (glibc) |
195
+
196
+ ## 致谢
197
+
198
+ - [ChurchTao/clipboard-rs](https://github.com/ChurchTao/clipboard-rs) 提供了跨 Linux、Windows 和 macOS 的原生剪贴板支持。
199
+ - [napi.rs](https://napi.rs/) 将 Rust 实现桥接到 Node.js。
200
+
201
+ ## 发布
202
+
203
+ 所有构建和发布流程由 GitHub Actions 完成。
204
+
205
+ 执行 `npm version patch` 升级版本号,然后 `git push --follow-tags` 推送到 GitHub,GitHub Actions 会自动构建并发布。
package/index.d.ts CHANGED
@@ -1,23 +1,55 @@
1
- /* tslint:disable */
1
+ /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
+ export declare class ClipboardWatcherJs {
4
+ stop(): void
5
+ get isRunning(): boolean
6
+ }
3
7
 
4
- /* auto-generated by NAPI-RS */
8
+ export declare function availableFormats(): Array<string>
9
+
10
+ export declare function clear(): Promise<void>
11
+
12
+ export declare function getBuffer(format: string): Promise<Array<number>>
13
+
14
+ export declare function getFiles(): Promise<Array<string>>
15
+
16
+ export declare function getHtml(): Promise<string>
17
+
18
+ export declare function getImageBase64(): Promise<string>
19
+
20
+ export declare function getImageBinary(): Promise<Array<number>>
21
+
22
+ export declare function getRtf(): Promise<string>
23
+
24
+ export declare function getText(): Promise<string>
25
+
26
+ export declare function hasFiles(): boolean
27
+
28
+ export declare function hasHtml(): boolean
29
+
30
+ export declare function hasImage(): boolean
31
+
32
+ export declare function hasRtf(): boolean
33
+
34
+ export declare function hasText(): boolean
35
+
36
+ export declare function setBuffer(format: string, buffer: Array<number>): Promise<void>
37
+
38
+ export declare function setFiles(files: Array<string>): Promise<void>
39
+
40
+ export declare function setHtml(html: string): Promise<void>
41
+
42
+ export declare function setImageBase64(base64Str: string): Promise<void>
43
+
44
+ export declare function setImageBinary(imageBytes: Array<number>): Promise<void>
45
+
46
+ export declare function setRtf(rtf: string): Promise<void>
47
+
48
+ export declare function setText(text: string): Promise<void>
5
49
 
6
- export function availableFormats(): Array<string>
7
- export function getText(): Promise<string>
8
- export function setText(text: string): Promise<void>
9
- export function hasText(): boolean
10
- export function getImageBinary(): Promise<Array<number>>
11
- export function getImageBase64(): Promise<string>
12
- export function setImageBinary(imageBytes: Array<number>): Promise<void>
13
- export function setImageBase64(base64Str: string): Promise<void>
14
- export function hasImage(): boolean
15
- export function getHtml(): Promise<string>
16
- export function setHtml(html: string): Promise<void>
17
- export function hasHtml(): boolean
18
- export function getRtf(): Promise<string>
19
- export function setRtf(rtf: string): Promise<void>
20
- export function hasRtf(): boolean
21
- export function clear(): Promise<void>
22
- export function watch(): void
23
- export function callThreadsafeFunction(callback: (...args: any[]) => any): void
50
+ /**
51
+ * Start watching the clipboard for changes.
52
+ * The callback is invoked whenever the clipboard content changes.
53
+ * Returns a `ClipboardWatcherJs` handle that can stop the watcher.
54
+ */
55
+ export declare function startWatch(callback: () => void): ClipboardWatcherJs