diff --git a/.changes/clipboard-html.md b/.changes/clipboard-html.md
new file mode 100644
index 00000000..df19abfd
--- /dev/null
+++ b/.changes/clipboard-html.md
@@ -0,0 +1,6 @@
+---
+"clipboard-manager": patch
+"clipboard-manager-js": patch
+---
+
+Add support for writing HTML content to the clipboard.
\ No newline at end of file
diff --git a/plugins/clipboard-manager/README.md b/plugins/clipboard-manager/README.md
index 02b26b3c..cd7f5216 100644
--- a/plugins/clipboard-manager/README.md
+++ b/plugins/clipboard-manager/README.md
@@ -60,7 +60,7 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { writeText, readText } from "@tauri-apps/plugin-clipboard-manager";
+import { writeText, readText, writeHtml, readHtml, clear } from "@tauri-apps/plugin-clipboard-manager";
await writeText("Tauri is awesome!");
assert(await readText(), "Tauri is awesome!");
```
diff --git a/plugins/clipboard-manager/guest-js/index.ts b/plugins/clipboard-manager/guest-js/index.ts
index 4a9d10a0..c812ad53 100644
--- a/plugins/clipboard-manager/guest-js/index.ts
+++ b/plugins/clipboard-manager/guest-js/index.ts
@@ -53,4 +53,43 @@ async function readText(): Promise {
return kind.plainText.text;
}
-export { writeText, readText };
+/**
+ * Writes HTML or fallbacks to write provided plain text to the clipboard.
+ * @example
+ * ```typescript
+ * import { writeHtml, readHtml } from '@tauri-apps/plugin-clipboard-manager';
+ * await writeHtml('Tauri is awesome!
', 'plaintext');
+ * await writeHtml('Tauri is awesome!
', 'Tauri is awesome
'); // Will write "Tauri is awesome
" as plain text
+ * assert(await readText(), 'Tauri is awesome!
');
+ * ```
+ *
+ * @returns A promise indicating the success or failure of the operation.
+ *
+ * @since 2.0.0
+ */
+async function writeHtml(html: string, altHtml?: string): Promise {
+ return invoke("plugin:clipboard-manager|write_html", {
+ data: {
+ html: {
+ html,
+ altHtml,
+ },
+ },
+ });
+}
+
+/**
+ * Clears the clipboard.
+ * @example
+ * ```typescript
+ * import { clear } from '@tauri-apps/plugin-clipboard-manager';
+ * await clear();
+ * ```
+ * @since 2.0.0
+ */
+async function clear(): Promise {
+ await invoke("plugin:clipboard-manager|clear");
+ return;
+}
+
+export { writeText, readText, writeHtml, clear };
diff --git a/plugins/clipboard-manager/src/api-iife.js b/plugins/clipboard-manager/src/api-iife.js
index 8dc51655..bbf9cff6 100644
--- a/plugins/clipboard-manager/src/api-iife.js
+++ b/plugins/clipboard-manager/src/api-iife.js
@@ -1 +1 @@
-if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARDMANAGER__=function(e){"use strict";async function n(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}return"function"==typeof SuppressedError&&SuppressedError,e.readText=async function(){return(await n("plugin:clipboard-manager|read")).plainText.text},e.writeText=async function(e,r){return n("plugin:clipboard-manager|write",{data:{plainText:{label:r?.label,text:e}}})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARDMANAGER__})}
+if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARDMANAGER__=function(n){"use strict";async function r(n,r={},a){return window.__TAURI_INTERNALS__.invoke(n,r,a)}return"function"==typeof SuppressedError&&SuppressedError,n.clear=async function(){await r("plugin:clipboard-manager|clear")},n.readText=async function(){return(await r("plugin:clipboard-manager|read")).plainText.text},n.writeHtml=async function(n,a){return r("plugin:clipboard-manager|write_html",{data:{html:{html:n,altHtml:a}}})},n.writeText=async function(n,a){return r("plugin:clipboard-manager|write",{data:{plainText:{label:a?.label,text:n}}})},n}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARDMANAGER__})}
diff --git a/plugins/clipboard-manager/src/commands.rs b/plugins/clipboard-manager/src/commands.rs
index eec868a8..d7fb0688 100644
--- a/plugins/clipboard-manager/src/commands.rs
+++ b/plugins/clipboard-manager/src/commands.rs
@@ -22,3 +22,20 @@ pub(crate) async fn read(
) -> Result {
clipboard.read()
}
+
+#[command]
+pub(crate) async fn write_html(
+ _app: AppHandle,
+ clipboard: State<'_, Clipboard>,
+ data: ClipKind,
+) -> Result<()> {
+ clipboard.write_html(data)
+}
+
+#[command]
+pub(crate) async fn clear(
+ _app: AppHandle,
+ clipboard: State<'_, Clipboard>,
+) -> Result<()> {
+ clipboard.clear()
+}
diff --git a/plugins/clipboard-manager/src/desktop.rs b/plugins/clipboard-manager/src/desktop.rs
index 555321dc..acf63c80 100644
--- a/plugins/clipboard-manager/src/desktop.rs
+++ b/plugins/clipboard-manager/src/desktop.rs
@@ -28,10 +28,12 @@ pub struct Clipboard {
impl Clipboard {
pub fn write(&self, kind: ClipKind) -> crate::Result<()> {
- let ClipKind::PlainText { text, .. } = kind;
- match &self.clipboard {
- Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
- Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ match kind {
+ ClipKind::PlainText { text, .. } => match &self.clipboard {
+ Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ },
+ _ => Err(crate::Error::Clipboard("Invalid clip kind!".to_string())),
}
}
@@ -44,4 +46,25 @@ impl Clipboard {
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
+
+ pub fn write_html(&self, kind: ClipKind) -> crate::Result<()> {
+ match kind {
+ ClipKind::Html { html, alt_html, .. } => match &self.clipboard {
+ Ok(clipboard) => clipboard
+ .lock()
+ .unwrap()
+ .set_html(html, alt_html)
+ .map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ },
+ _ => Err(crate::Error::Clipboard("Invalid clip kind!".to_string())),
+ }
+ }
+
+ pub fn clear(&self) -> crate::Result<()> {
+ match &self.clipboard {
+ Ok(clipboard) => clipboard.lock().unwrap().clear().map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ }
+ }
}
diff --git a/plugins/clipboard-manager/src/error.rs b/plugins/clipboard-manager/src/error.rs
index bf71802f..03da585b 100644
--- a/plugins/clipboard-manager/src/error.rs
+++ b/plugins/clipboard-manager/src/error.rs
@@ -11,7 +11,6 @@ pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
- #[cfg(desktop)]
#[error("{0}")]
Clipboard(String),
}
diff --git a/plugins/clipboard-manager/src/lib.rs b/plugins/clipboard-manager/src/lib.rs
index 2b7934ab..bbfe5918 100644
--- a/plugins/clipboard-manager/src/lib.rs
+++ b/plugins/clipboard-manager/src/lib.rs
@@ -49,7 +49,14 @@ impl> crate::ClipboardExt for T {
pub fn init() -> TauriPlugin {
Builder::new("clipboard-manager")
.js_init_script(include_str!("api-iife.js").to_string())
- .invoke_handler(tauri::generate_handler![commands::write, commands::read])
+ .invoke_handler(tauri::generate_handler![
+ commands::write,
+ commands::read,
+ #[cfg(desktop)]
+ commands::write_html,
+ #[cfg(desktop)]
+ commands::clear
+ ])
.setup(|app, api| {
#[cfg(mobile)]
let clipboard = mobile::init(app, api)?;
diff --git a/plugins/clipboard-manager/src/mobile.rs b/plugins/clipboard-manager/src/mobile.rs
index 07964711..8ba8c809 100644
--- a/plugins/clipboard-manager/src/mobile.rs
+++ b/plugins/clipboard-manager/src/mobile.rs
@@ -39,4 +39,17 @@ impl Clipboard {
pub fn read(&self) -> crate::Result {
self.0.run_mobile_plugin("read", ()).map_err(Into::into)
}
+
+ // Treat HTML as unsupported on mobile until tested
+ pub fn write_html(&self, _kind: ClipKind) -> crate::Result<()> {
+ Err(crate::Error::Clipboard(
+ "Unsupported on this platform".to_string(),
+ ))
+ }
+
+ pub fn clear(&self) -> crate::Result<()> {
+ Err(crate::Error::Clipboard(
+ "Unsupported on this platform".to_string(),
+ ))
+ }
}
diff --git a/plugins/clipboard-manager/src/models.rs b/plugins/clipboard-manager/src/models.rs
index a223a679..bb8c9b54 100644
--- a/plugins/clipboard-manager/src/models.rs
+++ b/plugins/clipboard-manager/src/models.rs
@@ -7,7 +7,14 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ClipKind {
- PlainText { label: Option, text: String },
+ PlainText {
+ label: Option,
+ text: String,
+ },
+ Html {
+ html: String,
+ alt_html: Option,
+ },
}
#[derive(Debug, Serialize, Deserialize)]