Skip to content

Commit 0ca416c

Browse files
authored
server : (UI) fix copy to clipboard function (#10916)
1 parent 21ae3b9 commit 0ca416c

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

examples/server/public/index.html.gz

428 Bytes
Binary file not shown.

examples/server/webui/src/main.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import hljs from './highlight-config';
1313
import daisyuiThemes from 'daisyui/src/theming/themes';
1414

1515
// ponyfill for missing ReadableStream asyncIterator on Safari
16-
import { asyncIterator } from "@sec-ant/readable-stream/ponyfill/asyncIterator";
16+
import { asyncIterator } from '@sec-ant/readable-stream/ponyfill/asyncIterator';
1717

1818
const isDev = import.meta.env.MODE === 'development';
1919

@@ -22,7 +22,22 @@ const isString = (x) => !!x.toLowerCase;
2222
const isBoolean = (x) => x === true || x === false;
2323
const isNumeric = (n) => !isString(n) && !isNaN(n) && !isBoolean(n);
2424
const escapeAttr = (str) => str.replace(/>/g, '>').replace(/"/g, '"');
25-
const copyStr = (str) => navigator.clipboard.writeText(str);
25+
const copyStr = (textToCopy) => {
26+
// Navigator clipboard api needs a secure context (https)
27+
if (navigator.clipboard && window.isSecureContext) {
28+
navigator.clipboard.writeText(textToCopy);
29+
} else {
30+
// Use the 'out of viewport hidden text area' trick
31+
const textArea = document.createElement('textarea');
32+
textArea.value = textToCopy;
33+
// Move textarea out of the viewport so it's not visible
34+
textArea.style.position = 'absolute';
35+
textArea.style.left = '-999999px';
36+
document.body.prepend(textArea);
37+
textArea.select();
38+
document.execCommand('copy');
39+
}
40+
};
2641

2742
// constants
2843
const BASE_URL = isDev
@@ -130,9 +145,9 @@ const VueMarkdown = defineComponent(
130145
};
131146
window.copyStr = copyStr;
132147
const content = computed(() => md.value.render(props.source));
133-
return () => h("div", { innerHTML: content.value });
148+
return () => h('div', { innerHTML: content.value });
134149
},
135-
{ props: ["source"] }
150+
{ props: ['source'] }
136151
);
137152

138153
// input field to be used by settings modal

0 commit comments

Comments
 (0)