@@ -127,7 +127,7 @@ const translations = {
127127 </button >
128128 </div >
129129
130- <span class =" copy-page-feedback sr-only" aria-live =" polite" aria-atomic =" true" ></span >
130+ <span class =" copy-page-feedback sr-only" role = " status " aria-live =" polite" aria-atomic =" true" ></span >
131131</div >
132132
133133<script is:inline define:vars ={ { translations , editUrl: editUrl ?.toString () ?? ' ' }} >
@@ -157,6 +157,8 @@ const translations = {
157157
158158 // Copy page as markdown
159159 document.querySelectorAll('.copy-markdown').forEach((btn) => {
160+ let resetTimer
161+
160162 btn.addEventListener('click', async (e) => {
161163 e.preventDefault()
162164 e.stopPropagation()
@@ -172,6 +174,44 @@ const translations = {
172174 const container = btn.closest('.copy-page-container')
173175 const feedback = container?.querySelector('.copy-page-feedback')
174176
177+ function updateFeedback(message) {
178+ if (feedback instanceof HTMLElement) {
179+ feedback.textContent = message
180+ }
181+ }
182+
183+ function resetFeedback() {
184+ if (resetTimer) {
185+ window.clearTimeout(resetTimer)
186+ }
187+
188+ resetTimer = window.setTimeout(() => {
189+ if (title) {
190+ title.textContent = originalText || translations.copyPage
191+ }
192+ updateFeedback('')
193+ }, 2000)
194+ }
195+
196+ function fallbackCopy(value) {
197+ const textarea = document.createElement('textarea')
198+ textarea.value = value
199+ textarea.style.position = 'fixed'
200+ textarea.style.opacity = '0'
201+ document.body.appendChild(textarea)
202+ textarea.focus()
203+ textarea.select()
204+
205+ const legacyCopy = Reflect.get(document, 'execCommand')
206+ const copied = typeof legacyCopy === 'function' ? legacyCopy.call(document, 'copy') : false
207+
208+ document.body.removeChild(textarea)
209+
210+ if (!copied) {
211+ throw new Error('Fallback copy method also failed')
212+ }
213+ }
214+
175215 try {
176216 // Disable button during operation
177217 btn.disabled = true
@@ -205,49 +245,31 @@ const translations = {
205245 throw new Error('Failed to fetch markdown from any source')
206246 }
207247
208- // Copy to clipboard using the most reliable method
209- try {
210- await navigator.clipboard.writeText(content)
211- console.log('Copied to clipboard successfully')
212- } catch (clipboardError) {
213- console.error('Clipboard API failed, trying fallback:', clipboardError)
214-
215- // Fallback method using textarea
216- const textarea = document.createElement('textarea')
217- textarea.value = content
218- textarea.style.position = 'fixed'
219- textarea.style.opacity = '0'
220- document.body.appendChild(textarea)
221- textarea.focus()
222- textarea.select()
223- // @ts-expect-error execCommand is deprecated but used as fallback for older browsers
224- const success = document.execCommand('copy')
225- document.body.removeChild(textarea)
226-
227- if (!success) {
228- throw new Error('Fallback copy method also failed')
248+ if (!navigator.clipboard?.writeText) {
249+ fallbackCopy(content)
250+ } else {
251+ try {
252+ await navigator.clipboard.writeText(content)
253+ } catch (clipboardError) {
254+ console.error('Clipboard API failed, trying fallback:', clipboardError)
255+ fallbackCopy(content)
229256 }
230257 }
258+ console.log('Copied to clipboard successfully')
231259
232260 // Show success feedback
261+ updateFeedback(translations.copied)
233262 if (title) {
234263 title.textContent = translations.copied
235- if (feedback) feedback.textContent = translations.copied
236- setTimeout(() => {
237- title.textContent = originalText || translations.copyPage
238- if (feedback) feedback.textContent = ''
239- }, 2000)
240264 }
265+ resetFeedback()
241266 } catch (error) {
242267 console.error('Failed to copy:', error)
268+ updateFeedback(translations.failedToCopy)
243269 if (title) {
244270 title.textContent = translations.failedToCopy
245- if (feedback) feedback.textContent = translations.failedToCopy
246- setTimeout(() => {
247- title.textContent = originalText || translations.copyPage
248- if (feedback) feedback.textContent = ''
249- }, 2000)
250271 }
272+ resetFeedback()
251273 } finally {
252274 btn.disabled = false
253275 }
0 commit comments