swh.web 0.16.2__py3-none-any.whl → 0.16.4__py3-none-any.whl

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.
Files changed (144) hide show
  1. swh/web/add_forge_now/templates/add-forge-request-dashboard.html +5 -2
  2. swh/web/api/views/origin.py +2 -2
  3. swh/web/archive_coverage/views.py +4 -7
  4. swh/web/badges/__init__.py +1 -1
  5. swh/web/badges/assets/index.js +40 -14
  6. swh/web/browse/assets/browse/browse.css +5 -0
  7. swh/web/browse/assets/browse/sidetabs.js +3 -16
  8. swh/web/browse/templates/browse-iframe.html +10 -7
  9. swh/web/browse/templates/browse-origin-visits.html +2 -2
  10. swh/web/browse/templates/browse-revision.html +5 -3
  11. swh/web/browse/templates/includes/content-display.html +10 -5
  12. swh/web/browse/templates/includes/readme-display.html +3 -2
  13. swh/web/browse/templates/includes/show-metadata.html +3 -2
  14. swh/web/browse/templates/includes/sidetabs.html +9 -7
  15. swh/web/browse/templates/includes/top-navigation.html +2 -1
  16. swh/web/browse/tests/views/test_origin.py +3 -1
  17. swh/web/deposit/templates/deposit-admin.html +6 -1
  18. swh/web/inbound_email/handle_message.py +1 -1
  19. swh/web/inbound_email/tests/test_utils.py +2 -2
  20. swh/web/save_code_now/assets/origin-save-admin.js +5 -2
  21. swh/web/save_code_now/assets/origin-save.js +9 -4
  22. swh/web/static/css/{archive_coverage.70eba3d32ed75472d638.css → archive_coverage.df54ae8fe40453ecd972.css} +2 -2
  23. swh/web/static/css/archive_coverage.df54ae8fe40453ecd972.css.map +1 -0
  24. swh/web/static/css/browse.633076034514e6a3977d.css +2 -0
  25. swh/web/static/css/browse.633076034514e6a3977d.css.map +1 -0
  26. swh/web/static/css/guided_tour.d496a0c252e1bb193496.css +2 -0
  27. swh/web/static/css/{guided_tour.62c03630e944b8b8d9ad.css.map → guided_tour.d496a0c252e1bb193496.css.map} +1 -1
  28. swh/web/static/css/{highlightjs.0c1b181eb006699a4c3e.css → highlightjs.37238c93749cb449800d.css} +2 -2
  29. swh/web/static/css/highlightjs.37238c93749cb449800d.css.map +1 -0
  30. swh/web/static/css/origin_visits.9a796c4df6606bd9905f.css +2 -0
  31. swh/web/static/css/origin_visits.9a796c4df6606bd9905f.css.map +1 -0
  32. swh/web/static/css/vendors.a4844da6ce54cbc04960.css +24 -0
  33. swh/web/static/css/vendors.a4844da6ce54cbc04960.css.map +1 -0
  34. swh/web/static/css/{webapp.4655323082740f1a4862.css → webapp.e995faa24f8c84db0d06.css} +2 -2
  35. swh/web/static/css/webapp.e995faa24f8c84db0d06.css.map +1 -0
  36. swh/web/static/js/add_forge_now.e85d09463e38c1e19632.js +3 -0
  37. swh/web/static/js/add_forge_now.e85d09463e38c1e19632.js.map +1 -0
  38. swh/web/static/js/auth.06c697ab58b81d08ebce.js +3 -0
  39. swh/web/static/js/auth.06c697ab58b81d08ebce.js.map +1 -0
  40. swh/web/static/js/badges.50941e27bf5e4453b0e0.js +3 -0
  41. swh/web/static/js/badges.50941e27bf5e4453b0e0.js.LICENSE.txt +6 -0
  42. swh/web/static/js/badges.50941e27bf5e4453b0e0.js.map +1 -0
  43. swh/web/static/js/browse.3f22819b69002c8b6407.js +3 -0
  44. swh/web/static/js/browse.3f22819b69002c8b6407.js.map +1 -0
  45. swh/web/static/js/deposit.d47e18177b16ccdbdb84.js.map +1 -1
  46. swh/web/static/js/{highlightjs.dc9b8354c69d942fad33.js → highlightjs.516e784a1e62011c7605.js} +3 -3
  47. swh/web/static/js/highlightjs.516e784a1e62011c7605.js.map +1 -0
  48. swh/web/static/js/mailmap.de04f685e56eff5b627f.js +3 -0
  49. swh/web/static/js/mailmap.de04f685e56eff5b627f.js.map +1 -0
  50. swh/web/static/js/mathjax.98ef576f318f1a0b0c4a.js.map +1 -1
  51. swh/web/static/js/pdf.worker.min.js +1 -1
  52. swh/web/static/js/pdfjs.018d9890c044b3612ece.js +3 -0
  53. swh/web/static/js/pdfjs.018d9890c044b3612ece.js.map +1 -0
  54. swh/web/static/js/{revision.ac9293e1b984b4d4d909.js → revision.122a31614a5f9abffc3c.js} +3 -3
  55. swh/web/static/js/revision.122a31614a5f9abffc3c.js.map +1 -0
  56. swh/web/static/js/save_code_now.d4d8fc47420a4badb683.js +3 -0
  57. swh/web/static/js/save_code_now.d4d8fc47420a4badb683.js.map +1 -0
  58. swh/web/static/js/vault.d2ec3dd1d84a8d038a6c.js +3 -0
  59. swh/web/static/js/vault.d2ec3dd1d84a8d038a6c.js.map +1 -0
  60. swh/web/static/js/vendors.f62cb86cf3b92ae280ee.js +3 -0
  61. swh/web/static/js/{vendors.2eeadf2e0831a7a82b6d.js.LICENSE.txt → vendors.f62cb86cf3b92ae280ee.js.LICENSE.txt} +5 -1
  62. swh/web/static/js/vendors.f62cb86cf3b92ae280ee.js.map +1 -0
  63. swh/web/static/js/webapp.e93873983e400db67bf8.js +3 -0
  64. swh/web/static/js/{webapp.26efc059a8f5fe204240.js.LICENSE.txt → webapp.e93873983e400db67bf8.js.LICENSE.txt} +1 -1
  65. swh/web/static/js/webapp.e93873983e400db67bf8.js.map +1 -0
  66. swh/web/static/jssources/@myriaddreamin/highlighter-typst/dist/esm/contrib/hljs/typst-lite.bundle.js +180 -111
  67. swh/web/static/jssources/assets/src/utils/functions.js +5 -5
  68. swh/web/static/jssources/core-js/LICENSE.txt +1 -1
  69. swh/web/static/jssources/core-js/internals/shared-store.js +3 -3
  70. swh/web/static/jssources/core-js/modules/es.object.group-by.js +2 -1
  71. swh/web/static/jssources/datatables.net/js/dataTables.mjs +108 -44
  72. swh/web/static/jssources/datatables.net-fixedheader/js/dataTables.fixedHeader.mjs +10 -4
  73. swh/web/static/jssources/datatables.net-fixedheader/node_modules/datatables.net/js/dataTables.mjs +14027 -0
  74. swh/web/static/jssources/datatables.net-fixedheader-bs5/node_modules/datatables.net/js/dataTables.mjs +14027 -0
  75. swh/web/static/jssources/datatables.net-fixedheader-bs5/node_modules/datatables.net-bs5/js/dataTables.bootstrap5.mjs +81 -0
  76. swh/web/static/jssources/dompurify/dist/purify.es.mjs +35 -12
  77. swh/web/static/jssources/highlightjs-line-numbers.js/src/highlightjs-line-numbers.js +1 -1
  78. swh/web/static/jssources/highlightjs-macaulay2/dist/macaulay2.min.js +3 -3
  79. swh/web/static/jssources/jslicenses.json +1 -1
  80. swh/web/static/jssources/pdfjs-dist/build/pdf.worker.mjs +885 -596
  81. swh/web/static/jssources/pdfjs-dist/legacy/build/pdf.mjs +4982 -4566
  82. swh/web/static/jssources/swh/web/badges/assets/index.js +40 -14
  83. swh/web/static/jssources/swh/web/browse/assets/browse/sidetabs.js +3 -16
  84. swh/web/static/jssources/swh/web/save_code_now/assets/origin-save-admin.js +5 -2
  85. swh/web/static/jssources/swh/web/save_code_now/assets/origin-save.js +9 -4
  86. swh/web/static/jssources/swh/web/vault/assets/vault-ui.js +6 -4
  87. swh/web/static/jssources/swh/web/webapp/assets/webapp/webapp-utils.js +18 -1
  88. swh/web/static/security.txt +3 -0
  89. swh/web/static/webpack-stats.json +240 -235
  90. swh/web/tests/views.py +9 -8
  91. swh/web/utils/archive.py +1 -1
  92. swh/web/utils/swh_templatetags.py +8 -13
  93. swh/web/vault/assets/vault-ui.js +6 -4
  94. swh/web/webapp/assets/webapp/webapp-utils.js +18 -1
  95. swh/web/webapp/assets/webapp/webapp.css +8 -0
  96. swh/web/webapp/templates/layout.html +13 -10
  97. swh/web/webapp/tests/test_views.py +16 -1
  98. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/METADATA +2 -3
  99. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/RECORD +112 -107
  100. swh/web/static/css/archive_coverage.70eba3d32ed75472d638.css.map +0 -1
  101. swh/web/static/css/browse.0a250d3b07ce628588a5.css +0 -2
  102. swh/web/static/css/browse.0a250d3b07ce628588a5.css.map +0 -1
  103. swh/web/static/css/guided_tour.62c03630e944b8b8d9ad.css +0 -2
  104. swh/web/static/css/highlightjs.0c1b181eb006699a4c3e.css.map +0 -1
  105. swh/web/static/css/origin_visits.88099d68a63f86af2f8e.css +0 -2
  106. swh/web/static/css/origin_visits.88099d68a63f86af2f8e.css.map +0 -1
  107. swh/web/static/css/vendors.1cfc8080eed63af482cf.css +0 -24
  108. swh/web/static/css/vendors.1cfc8080eed63af482cf.css.map +0 -1
  109. swh/web/static/css/webapp.4655323082740f1a4862.css.map +0 -1
  110. swh/web/static/js/add_forge_now.e25d1ad2ab6c45e60b67.js +0 -3
  111. swh/web/static/js/add_forge_now.e25d1ad2ab6c45e60b67.js.map +0 -1
  112. swh/web/static/js/auth.bd2f475f49caa9f84e99.js +0 -3
  113. swh/web/static/js/auth.bd2f475f49caa9f84e99.js.map +0 -1
  114. swh/web/static/js/badges.f02607179ad0264e7522.js +0 -2
  115. swh/web/static/js/badges.f02607179ad0264e7522.js.map +0 -1
  116. swh/web/static/js/browse.fc5d5fafca71e03d2add.js +0 -3
  117. swh/web/static/js/browse.fc5d5fafca71e03d2add.js.map +0 -1
  118. swh/web/static/js/highlightjs.dc9b8354c69d942fad33.js.map +0 -1
  119. swh/web/static/js/mailmap.631c53127ba5511ebda7.js +0 -3
  120. swh/web/static/js/mailmap.631c53127ba5511ebda7.js.map +0 -1
  121. swh/web/static/js/pdfjs.40675676ebcbdde8baab.js +0 -3
  122. swh/web/static/js/pdfjs.40675676ebcbdde8baab.js.map +0 -1
  123. swh/web/static/js/revision.ac9293e1b984b4d4d909.js.map +0 -1
  124. swh/web/static/js/save_code_now.369ff7f28aaf74e7728e.js +0 -3
  125. swh/web/static/js/save_code_now.369ff7f28aaf74e7728e.js.map +0 -1
  126. swh/web/static/js/vault.1229427aed95c78d4ee2.js +0 -3
  127. swh/web/static/js/vault.1229427aed95c78d4ee2.js.map +0 -1
  128. swh/web/static/js/vendors.2eeadf2e0831a7a82b6d.js +0 -3
  129. swh/web/static/js/vendors.2eeadf2e0831a7a82b6d.js.map +0 -1
  130. swh/web/static/js/webapp.26efc059a8f5fe204240.js +0 -3
  131. swh/web/static/js/webapp.26efc059a8f5fe204240.js.map +0 -1
  132. /swh/web/static/js/{add_forge_now.e25d1ad2ab6c45e60b67.js.LICENSE.txt → add_forge_now.e85d09463e38c1e19632.js.LICENSE.txt} +0 -0
  133. /swh/web/static/js/{auth.bd2f475f49caa9f84e99.js.LICENSE.txt → auth.06c697ab58b81d08ebce.js.LICENSE.txt} +0 -0
  134. /swh/web/static/js/{browse.fc5d5fafca71e03d2add.js.LICENSE.txt → browse.3f22819b69002c8b6407.js.LICENSE.txt} +0 -0
  135. /swh/web/static/js/{highlightjs.dc9b8354c69d942fad33.js.LICENSE.txt → highlightjs.516e784a1e62011c7605.js.LICENSE.txt} +0 -0
  136. /swh/web/static/js/{mailmap.631c53127ba5511ebda7.js.LICENSE.txt → mailmap.de04f685e56eff5b627f.js.LICENSE.txt} +0 -0
  137. /swh/web/static/js/{pdfjs.40675676ebcbdde8baab.js.LICENSE.txt → pdfjs.018d9890c044b3612ece.js.LICENSE.txt} +0 -0
  138. /swh/web/static/js/{revision.ac9293e1b984b4d4d909.js.LICENSE.txt → revision.122a31614a5f9abffc3c.js.LICENSE.txt} +0 -0
  139. /swh/web/static/js/{save_code_now.369ff7f28aaf74e7728e.js.LICENSE.txt → save_code_now.d4d8fc47420a4badb683.js.LICENSE.txt} +0 -0
  140. /swh/web/static/js/{vault.1229427aed95c78d4ee2.js.LICENSE.txt → vault.d2ec3dd1d84a8d038a6c.js.LICENSE.txt} +0 -0
  141. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/WHEEL +0 -0
  142. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/licenses/AUTHORS +0 -0
  143. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/licenses/LICENSE +0 -0
  144. {swh_web-0.16.2.dist-info → swh_web-0.16.4.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,12 @@
1
1
  /**
2
- * Copyright (C) 2019-2023 The Software Heritage developers
2
+ * Copyright (C) 2019-2025 The Software Heritage developers
3
3
  * See the AUTHORS file at the top-level directory of this distribution
4
4
  * License: GNU Affero General Public License version 3, or any later version
5
5
  * See top-level LICENSE file for more information
6
6
  */
7
7
 
8
+ import ClipboardJS from 'clipboard';
9
+
8
10
  import './badges.css';
9
11
 
10
12
  export function showBadgeInfoModal(objectType, objectSWHID) {
@@ -35,22 +37,46 @@ export function showBadgeInfoModal(objectType, objectSWHID) {
35
37
  <a href="${absoluteBadgeLinkUrl}">
36
38
  <img class="swh-badge" src="${absoluteBadgeImageUrl}" alt="Archived | ${objectSWHID}"/>
37
39
  </a>
38
- <div>
39
- <label>HTML</label>
40
- <pre><code class="swh-badge-html html">&lt;a href="${absoluteBadgeLinkUrl}"&gt;
41
- &lt;img src="${absoluteBadgeImageUrl}" alt="Archived | ${objectCoreSWHID}"/&gt;
40
+ <ul class="nav nav-tabs">
41
+ <li class="nav-item">
42
+ <a class="nav-link active" data-bs-toggle="tab" href="#swh-badge-html">HTML</a>
43
+ </li>
44
+ <li class="nav-item">
45
+ <a class="nav-link" data-bs-toggle="tab" href="#swh-badge-markdown">Markdown</a>
46
+ </li>
47
+ <li class="nav-item">
48
+ <a class="nav-link" data-bs-toggle="tab" href="#swh-badge-rst">reStructuredText</a>
49
+ </li>
50
+ </ul>
51
+ <div class="tab-content swh-badges-integrations">
52
+ <div class="tab-pane active" id="swh-badge-html">
53
+ <pre><code class="swh-badge-html html">&lt;a href="${absoluteBadgeLinkUrl}"&gt;
54
+ &lt;img src="${absoluteBadgeImageUrl}" alt="Archived | ${objectCoreSWHID}"/&gt;
42
55
  &lt;/a&gt;</code></pre>
43
- </div>
44
- <div>
45
- <label>Markdown</label>
46
- <pre><code class="swh-badge-md markdown">[![SWH](${absoluteBadgeImageUrl})](${absoluteBadgeLinkUrl})</code></pre>
47
- </div>
48
- <div>
49
- <label>reStructuredText</label>
50
- <pre class="swh-badge-rst">.. image:: ${absoluteBadgeImageUrl}
51
- :target: ${absoluteBadgeLinkUrl}</pre>
56
+ </div>
57
+ <div class="tab-pane" id="swh-badge-markdown">
58
+ <pre><code class="swh-badge-md markdown">[![SWH](${absoluteBadgeImageUrl})](${absoluteBadgeLinkUrl})</code></pre>
59
+ </div>
60
+ <div class="tab-pane" id="swh-badge-rst">
61
+ <pre class="swh-badge-rst">.. image:: ${absoluteBadgeImageUrl}
62
+ :target: ${absoluteBadgeLinkUrl}</pre>
63
+ </div>
64
+ <button type="button"
65
+ class="btn btn-secondary btn-sm btn-swh-copy-badge-code float-end"
66
+ title="Copy badge code to clipboard">
67
+ <i class="mdi mdi-content-copy mdi-fw" aria-hidden="true"></i>Copy badge code
68
+ </button>
52
69
  </div>`;
53
70
  swh.webapp.showModalHtml('Software Heritage badge integration', html);
54
71
  swh.webapp.highlightCode(false, '.swh-badge-html');
55
72
  swh.webapp.highlightCode(false, '.swh-badge-md');
73
+ new ClipboardJS('.btn-swh-copy-badge-code', {
74
+ text: () => {
75
+ return $('.swh-badges-integrations .tab-pane.active pre').text();
76
+ },
77
+ container: document.getElementById('swh-web-modal-html')
78
+ }).on('success', function(e) {
79
+ swh.webapp.toggleButtonText(e.trigger, 'Copied!');
80
+ e.clearSelection();
81
+ });
56
82
  }
@@ -183,26 +183,13 @@ export async function generateCitationForObjectType(event) {
183
183
  export async function initSideTabs() {
184
184
 
185
185
  $(document).ready(() => {
186
- const toggleButtonText = (button, text) => {
187
- const currentLabel = button.innerHTML;
188
-
189
- if (currentLabel === text) {
190
- return;
191
- }
192
-
193
- button.innerHTML = text;
194
- setTimeout(function() {
195
- button.innerHTML = currentLabel;
196
- }, 1000);
197
- };
198
-
199
186
  new ClipboardJS('.btn-swhid-copy', {
200
187
  text: trigger => {
201
188
  const swhId = $(trigger).closest('.swhid-ui').find('.swhid').text();
202
189
  return swhId.replace(/;\n/g, ';');
203
190
  }
204
191
  }).on('success', function(e) {
205
- toggleButtonText(e.trigger, 'Copied!');
192
+ swh.webapp.toggleButtonText(e.trigger, 'Copied!');
206
193
  e.clearSelection();
207
194
  });
208
195
 
@@ -212,7 +199,7 @@ export async function initSideTabs() {
212
199
  return window.location.origin + swhIdUrl;
213
200
  }
214
201
  }).on('success', function(e) {
215
- toggleButtonText(e.trigger, 'Copied!');
202
+ swh.webapp.toggleButtonText(e.trigger, 'Copied!');
216
203
  e.clearSelection();
217
204
  });
218
205
 
@@ -310,7 +297,7 @@ export async function initSideTabs() {
310
297
  return citation;
311
298
  }
312
299
  }).on('success', function(e) {
313
- toggleButtonText(e.trigger, 'Copied!');
300
+ swh.webapp.toggleButtonText(e.trigger, 'Copied!');
314
301
  });
315
302
 
316
303
  const tabSlideOptionsCitations = {
@@ -73,6 +73,7 @@ export function initOriginSaveAdmin() {
73
73
  if (type === 'display') {
74
74
  let html = '';
75
75
  const sanitizedURL = $.fn.dataTable.render.text().display(data);
76
+ const parsedURL = new URL(sanitizedURL);
76
77
  if (row.save_task_status === 'succeeded') {
77
78
  let browseOriginUrl = `${Urls.browse_origin()}?origin_url=${encodeURIComponent(sanitizedURL)}`;
78
79
  if (row.visit_date) {
@@ -82,8 +83,10 @@ export function initOriginSaveAdmin() {
82
83
  } else {
83
84
  html += sanitizedURL;
84
85
  }
85
- html += `&nbsp;<a href="${sanitizedURL}" target="_blank" rel="noopener noreferrer">` +
86
- '<i class="mdi mdi-open-in-new" aria-hidden="true"></i></a>';
86
+ if (parsedURL.protocol.startsWith('http')) {
87
+ html += `&nbsp;<a href="${sanitizedURL}" target="_blank" rel="noopener noreferrer">` +
88
+ '<i class="mdi mdi-open-in-new" aria-hidden="true"></i></a>';
89
+ }
87
90
  return html;
88
91
  }
89
92
  return data;
@@ -182,6 +182,7 @@ export function initOriginSave() {
182
182
  if (type === 'display') {
183
183
  let html = '';
184
184
  const sanitizedURL = $.fn.dataTable.render.text().display(data);
185
+ const parsedURL = new URL(sanitizedURL);
185
186
  if (row.save_task_status === 'succeeded') {
186
187
  if (row.visit_status === 'full' || row.visit_status === 'partial') {
187
188
  let browseOriginUrl = `${Urls.browse_origin()}?origin_url=${encodeURIComponent(sanitizedURL)}`;
@@ -196,8 +197,10 @@ export function initOriginSave() {
196
197
  } else {
197
198
  html += sanitizedURL;
198
199
  }
199
- html += `&nbsp;<a href="${sanitizedURL}" target="_blank" rel="noopener noreferrer">` +
200
- '<i class="mdi mdi-open-in-new" aria-hidden="true"></i></a>';
200
+ if (parsedURL.protocol.startsWith('http')) {
201
+ html += `&nbsp;<a href="${sanitizedURL}" target="_blank" rel="noopener noreferrer">` +
202
+ '<i class="mdi mdi-open-in-new" aria-hidden="true"></i></a>';
203
+ }
201
204
  return html;
202
205
  }
203
206
  return data;
@@ -359,8 +362,10 @@ export function initOriginSave() {
359
362
 
360
363
  }
361
364
 
362
- const tarballExtensions =
363
- ['.jar', '.tar', '.tar.bz2', '.tar.gz', '.tar.lz', '.tar.xz', '.tar.zst', '.zip'];
365
+ const tarballExtensions = [
366
+ '.jar', '.tar', '.tar.bz2', '.tbz', '.tbz2', '.tar.gz', '.tgz', '.tar.lz',
367
+ '.tar.xz', '.tar.zst', '.zip'
368
+ ];
364
369
 
365
370
  function updateVisitType() {
366
371
  const originUrl = $('#swh-input-origin-url').val().trim();
@@ -181,15 +181,17 @@ async function checkVaultCookingTasks() {
181
181
  });
182
182
  try {
183
183
  const responses = await Promise.all(cookingTaskRequests);
184
- handleFetchErrors(responses);
184
+ handleFetchErrors(responses, [404]);
185
185
  const cookingTasks = await Promise.all(responses.map(r => r.json()));
186
186
 
187
187
  const table = $('#vault-cooking-tasks tbody');
188
188
  for (let i = 0; i < cookingTasks.length; ++i) {
189
189
  const cookingTask = tasks[cookingTasks[i].swhid];
190
- cookingTask.status = cookingTasks[i].status;
191
- cookingTask.fetch_url = cookingTasks[i].fetch_url;
192
- cookingTask.progress_message = cookingTasks[i].progress_message;
190
+ if (cookingTask) {
191
+ cookingTask.status = cookingTasks[i].status;
192
+ cookingTask.fetch_url = cookingTasks[i].fetch_url;
193
+ cookingTask.progress_message = cookingTasks[i].progress_message;
194
+ }
193
195
  }
194
196
  for (let i = 0; i < vaultCookingTasks.length; ++i) {
195
197
  const cookingTask = vaultCookingTasks[i];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (C) 2018-2024 The Software Heritage developers
2
+ * Copyright (C) 2018-2025 The Software Heritage developers
3
3
  * See the AUTHORS file at the top-level directory of this distribution
4
4
  * License: GNU Affero General Public License version 3, or any later version
5
5
  * See top-level LICENSE file for more information
@@ -399,3 +399,20 @@ export function mirrorConfig() {
399
399
  export function resizeIframe() {
400
400
  return iframeResize.apply(null, arguments)[0].iframeResizer;
401
401
  }
402
+
403
+ export function parseJsonScript(scriptElementId) {
404
+ return JSON.parse($(`#${scriptElementId}`).text());
405
+ }
406
+
407
+ export function toggleButtonText(button, text) {
408
+ const currentLabel = button.innerHTML;
409
+
410
+ if (currentLabel === text) {
411
+ return;
412
+ }
413
+
414
+ button.innerHTML = text;
415
+ setTimeout(function() {
416
+ button.innerHTML = currentLabel;
417
+ }, 1000);
418
+ };
@@ -0,0 +1,3 @@
1
+ Contact: mailto:security@softwareheritage.org
2
+ Expires: 2026-11-30T23:00:00.000Z
3
+ Preferred-Languages: en,fr