mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 14:31:02 +00:00 
			
		
		
		
	Replace clipboard.js with async clipboard api (#15899)
Use async clipboard api [1] over this dependency, saving around 10kB bundle size before minify while delivering the same functionality. The issue comment button works but does not have a popup indication. We could add some toast-style notifications in the future to fix that but I think it's out of scope of this PR. [1] https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
This commit is contained in:
		
					parent
					
						
							
								36dce0e457
							
						
					
				
			
			
				commit
				
					
						37205039fc
					
				
			
		
					 5 changed files with 38 additions and 90 deletions
				
			
		
							
								
								
									
										67
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										67
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -9,7 +9,6 @@ | ||||||
|         "@claviska/jquery-minicolors": "2.3.5", |         "@claviska/jquery-minicolors": "2.3.5", | ||||||
|         "@primer/octicons": "13.0.0", |         "@primer/octicons": "13.0.0", | ||||||
|         "add-asset-webpack-plugin": "2.0.1", |         "add-asset-webpack-plugin": "2.0.1", | ||||||
|         "clipboard": "2.0.8", |  | ||||||
|         "codemirror": "5.61.0", |         "codemirror": "5.61.0", | ||||||
|         "css-loader": "5.2.4", |         "css-loader": "5.2.4", | ||||||
|         "dropzone": "5.9.2", |         "dropzone": "5.9.2", | ||||||
|  | @ -2649,16 +2648,6 @@ | ||||||
|         "node": ">=4" |         "node": ">=4" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/clipboard": { |  | ||||||
|       "version": "2.0.8", |  | ||||||
|       "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz", |  | ||||||
|       "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==", |  | ||||||
|       "dependencies": { |  | ||||||
|         "good-listener": "^1.2.2", |  | ||||||
|         "select": "^1.1.2", |  | ||||||
|         "tiny-emitter": "^2.0.0" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "node_modules/cliui": { |     "node_modules/cliui": { | ||||||
|       "version": "6.0.0", |       "version": "6.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", |       "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", | ||||||
|  | @ -3481,11 +3470,6 @@ | ||||||
|         "node": ">=0.4.0" |         "node": ">=0.4.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/delegate": { |  | ||||||
|       "version": "3.2.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", |  | ||||||
|       "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" |  | ||||||
|     }, |  | ||||||
|     "node_modules/detect-newline": { |     "node_modules/detect-newline": { | ||||||
|       "version": "3.1.0", |       "version": "3.1.0", | ||||||
|       "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", |       "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", | ||||||
|  | @ -5567,14 +5551,6 @@ | ||||||
|         "node": ">=0.6.0" |         "node": ">=0.6.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/good-listener": { |  | ||||||
|       "version": "1.2.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", |  | ||||||
|       "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", |  | ||||||
|       "dependencies": { |  | ||||||
|         "delegate": "^3.1.2" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "node_modules/graceful-fs": { |     "node_modules/graceful-fs": { | ||||||
|       "version": "4.2.6", |       "version": "4.2.6", | ||||||
|       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", |       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", | ||||||
|  | @ -10856,11 +10832,6 @@ | ||||||
|         "url": "https://opencollective.com/webpack" |         "url": "https://opencollective.com/webpack" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/select": { |  | ||||||
|       "version": "1.1.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", |  | ||||||
|       "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" |  | ||||||
|     }, |  | ||||||
|     "node_modules/semver": { |     "node_modules/semver": { | ||||||
|       "version": "7.3.5", |       "version": "7.3.5", | ||||||
|       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", |       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", | ||||||
|  | @ -12256,11 +12227,6 @@ | ||||||
|       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", |       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "node_modules/tiny-emitter": { |  | ||||||
|       "version": "2.1.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", |  | ||||||
|       "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" |  | ||||||
|     }, |  | ||||||
|     "node_modules/tmpl": { |     "node_modules/tmpl": { | ||||||
|       "version": "1.0.4", |       "version": "1.0.4", | ||||||
|       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", |       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", | ||||||
|  | @ -15708,16 +15674,6 @@ | ||||||
|         "escape-string-regexp": "^1.0.5" |         "escape-string-regexp": "^1.0.5" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "clipboard": { |  | ||||||
|       "version": "2.0.8", |  | ||||||
|       "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz", |  | ||||||
|       "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==", |  | ||||||
|       "requires": { |  | ||||||
|         "good-listener": "^1.2.2", |  | ||||||
|         "select": "^1.1.2", |  | ||||||
|         "tiny-emitter": "^2.0.0" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "cliui": { |     "cliui": { | ||||||
|       "version": "6.0.0", |       "version": "6.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", |       "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", | ||||||
|  | @ -16412,11 +16368,6 @@ | ||||||
|       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", |       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "delegate": { |  | ||||||
|       "version": "3.2.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", |  | ||||||
|       "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" |  | ||||||
|     }, |  | ||||||
|     "detect-newline": { |     "detect-newline": { | ||||||
|       "version": "3.1.0", |       "version": "3.1.0", | ||||||
|       "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", |       "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", | ||||||
|  | @ -18044,14 +17995,6 @@ | ||||||
|         "minimist": "^1.2.5" |         "minimist": "^1.2.5" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "good-listener": { |  | ||||||
|       "version": "1.2.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", |  | ||||||
|       "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", |  | ||||||
|       "requires": { |  | ||||||
|         "delegate": "^3.1.2" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "graceful-fs": { |     "graceful-fs": { | ||||||
|       "version": "4.2.6", |       "version": "4.2.6", | ||||||
|       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", |       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", | ||||||
|  | @ -22064,11 +22007,6 @@ | ||||||
|         "ajv-keywords": "^3.5.2" |         "ajv-keywords": "^3.5.2" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "select": { |  | ||||||
|       "version": "1.1.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", |  | ||||||
|       "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" |  | ||||||
|     }, |  | ||||||
|     "semver": { |     "semver": { | ||||||
|       "version": "7.3.5", |       "version": "7.3.5", | ||||||
|       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", |       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", | ||||||
|  | @ -23188,11 +23126,6 @@ | ||||||
|       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", |       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "tiny-emitter": { |  | ||||||
|       "version": "2.1.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", |  | ||||||
|       "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" |  | ||||||
|     }, |  | ||||||
|     "tmpl": { |     "tmpl": { | ||||||
|       "version": "1.0.4", |       "version": "1.0.4", | ||||||
|       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", |       "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ | ||||||
|     "@claviska/jquery-minicolors": "2.3.5", |     "@claviska/jquery-minicolors": "2.3.5", | ||||||
|     "@primer/octicons": "13.0.0", |     "@primer/octicons": "13.0.0", | ||||||
|     "add-asset-webpack-plugin": "2.0.1", |     "add-asset-webpack-plugin": "2.0.1", | ||||||
|     "clipboard": "2.0.8", |  | ||||||
|     "codemirror": "5.61.0", |     "codemirror": "5.61.0", | ||||||
|     "css-loader": "5.2.4", |     "css-loader": "5.2.4", | ||||||
|     "dropzone": "5.9.2", |     "dropzone": "5.9.2", | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
| 	<input id="repo-clone-url" value="{{if $.PageIsWiki}}{{$.WikiCloneLink.SSH}}{{else}}{{$.CloneLink.SSH}}{{end}}" readonly> | 	<input id="repo-clone-url" value="{{if $.PageIsWiki}}{{$.WikiCloneLink.SSH}}{{else}}{{$.CloneLink.SSH}}{{end}}" readonly> | ||||||
| {{end}} | {{end}} | ||||||
| {{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}} | {{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}} | ||||||
| 	<button class="ui basic icon button poping up clipboard" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url"> | 	<button class="ui basic icon button poping up" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url"> | ||||||
| 		{{svg "octicon-clippy"}} | 		{{svg "octicon-clippy"}} | ||||||
| 	</button> | 	</button> | ||||||
| {{end}} | {{end}} | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| 		{{ else }} | 		{{ else }} | ||||||
| 			{{ $referenceUrl = Printf "%s%s/pulls/%d/files#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag }} | 			{{ $referenceUrl = Printf "%s%s/pulls/%d/files#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag }} | ||||||
| 		{{ end }} | 		{{ end }} | ||||||
| 		<div class="item context clipboard" data-clipboard-text="{{$referenceUrl}}">{{.ctx.i18n.Tr "repo.issues.context.copy_link"}}</div> | 		<div class="item context" data-clipboard-text="{{$referenceUrl}}">{{.ctx.i18n.Tr "repo.issues.context.copy_link"}}</div> | ||||||
| 		<div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.ID}}">{{.ctx.i18n.Tr "repo.issues.context.quote_reply"}}</div> | 		<div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.ID}}">{{.ctx.i18n.Tr "repo.issues.context.quote_reply"}}</div> | ||||||
| 		{{if not .ctx.UnitIssuesGlobalDisabled}} | 		{{if not .ctx.UnitIssuesGlobalDisabled}} | ||||||
| 			<div class="item context reference-issue" data-target="{{.item.ID}}" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-reference="{{$referenceUrl}}">{{.ctx.i18n.Tr "repo.issues.context.reference_issue"}}</div> | 			<div class="item context reference-issue" data-target="{{.item.ID}}" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-reference="{{$referenceUrl}}">{{.ctx.i18n.Tr "repo.issues.context.reference_issue"}}</div> | ||||||
|  |  | ||||||
|  | @ -1,22 +1,38 @@ | ||||||
| export default async function initClipboard() { | const selector = '[data-clipboard-target], [data-clipboard-text]'; | ||||||
|   const els = document.querySelectorAll('.clipboard'); |  | ||||||
|   if (!els || !els.length) return; |  | ||||||
| 
 | 
 | ||||||
|   const {default: ClipboardJS} = await import(/* webpackChunkName: "clipboard" */'clipboard'); | // TODO: replace these with toast-style notifications
 | ||||||
| 
 | function onSuccess(btn) { | ||||||
|   const clipboard = new ClipboardJS(els); |   if (!btn.dataset.content) return; | ||||||
|   clipboard.on('success', (e) => { |   $(btn).popup('destroy'); | ||||||
|     e.clearSelection(); |   btn.dataset.content = btn.dataset.success; | ||||||
|     $(e.trigger).popup('destroy'); |   $(btn).popup('show'); | ||||||
|     e.trigger.dataset.content = e.trigger.dataset.success; |   btn.dataset.content = btn.dataset.original; | ||||||
|     $(e.trigger).popup('show'); | } | ||||||
|     e.trigger.dataset.content = e.trigger.dataset.original; | function onError(btn) { | ||||||
|   }); |   if (!btn.dataset.content) return; | ||||||
| 
 |   $(btn).popup('destroy'); | ||||||
|   clipboard.on('error', (e) => { |   btn.dataset.content = btn.dataset.error; | ||||||
|     $(e.trigger).popup('destroy'); |   $(btn).popup('show'); | ||||||
|     e.trigger.dataset.content = e.trigger.dataset.error; |   btn.dataset.content = btn.dataset.original; | ||||||
|     $(e.trigger).popup('show'); | } | ||||||
|     e.trigger.dataset.content = e.trigger.dataset.original; | 
 | ||||||
|   }); | export default async function initClipboard() { | ||||||
|  |   for (const btn of document.querySelectorAll(selector) || []) { | ||||||
|  |     btn.addEventListener('click', async () => { | ||||||
|  |       let text; | ||||||
|  |       if (btn.dataset.clipboardText) { | ||||||
|  |         text = btn.dataset.clipboardText; | ||||||
|  |       } else if (btn.dataset.clipboardTarget) { | ||||||
|  |         text = document.querySelector(btn.dataset.clipboardTarget)?.value; | ||||||
|  |       } | ||||||
|  |       if (!text) return; | ||||||
|  | 
 | ||||||
|  |       try { | ||||||
|  |         await navigator.clipboard.writeText(text); | ||||||
|  |         onSuccess(btn); | ||||||
|  |       } catch { | ||||||
|  |         onError(btn); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue