jekyll-theme-centos 2.52.0.beta.57 → 2.52.0.beta.59

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/_data/base/announcement_schema.yml +2 -3
  3. data/_data/base/breadcrumb_schema.yml +13 -0
  4. data/_data/base/breakingnews_schema.yml +8 -0
  5. data/_data/base/event_schema.yml +10 -2
  6. data/_data/base/fontawesome_schema.yml +13 -0
  7. data/_data/base/navbar_schema.yml +8 -0
  8. data/_data/base/ogp.yml +1 -0
  9. data/_data/base/ogp_schema.yml +14 -0
  10. data/_includes/base/announcement.html.liquid +2 -2
  11. data/_includes/base/artwork.html.liquid +9 -9
  12. data/_includes/base/breadcrumb.html.liquid +15 -4
  13. data/_includes/base/breakingnews.html.liquid +6 -4
  14. data/_includes/base/event.html.liquid +4 -2
  15. data/_includes/base/fontawesome.html.liquid +23 -4
  16. data/_includes/base/footer.html.liquid +2 -2
  17. data/_includes/base/head.html.liquid +5 -3
  18. data/_includes/base/link.html.liquid +3 -7
  19. data/_includes/base/navbar.html.liquid +3 -3
  20. data/_includes/base/ogp.html.liquid +12 -2
  21. data/_includes/base/sponsors-cards.html.liquid +3 -3
  22. data/_includes/base/sponsors-carousel.html.liquid +3 -3
  23. data/_includes/base/title.html.liquid +2 -2
  24. data/_includes/base/toc.html.liquid +21 -19
  25. data/assets/img/base/page-with-alert.svg +164 -140
  26. data/assets/img/base/page-with-announcement.svg +792 -331
  27. data/assets/img/base/page-with-breakingnews.svg +861 -767
  28. data/assets/img/base/page-with-navbar.svg +827 -268
  29. data/assets/img/base/page-with-project.svg +367 -726
  30. data/assets/js/base/copyvalue.js +61 -177
  31. metadata +1 -40
  32. data/assets/img/base/example-ogp-image.png +0 -0
  33. data/assets/img/base/example-sponsors-design.png +0 -0
  34. data/assets/img/base/example-sponsors-logo-1.png +0 -0
  35. data/assets/img/base/example-sponsors-logo-2.png +0 -0
  36. data/assets/img/base/example-sponsors-logo-3.png +0 -0
  37. data/assets/img/base/example-sponsors-logo-4.png +0 -0
  38. data/assets/img/base/example-sponsors-logo-5.png +0 -0
  39. data/assets/img/base/example-sponsors-logo-6.png +0 -0
  40. data/assets/img/base/example-sponsors-logo-7.png +0 -0
  41. data/assets/img/base/example-sponsors-logo-8.png +0 -0
  42. data/assets/img/base/page-layout-default.png +0 -0
  43. data/assets/img/base/page-with-alert.png +0 -0
  44. data/assets/img/base/page-with-announcement.png +0 -0
  45. data/assets/img/base/page-with-artwork.png +0 -0
  46. data/assets/img/base/page-with-backtotop.png +0 -0
  47. data/assets/img/base/page-with-bits.png +0 -0
  48. data/assets/img/base/page-with-breadcrumb.png +0 -0
  49. data/assets/img/base/page-with-breakingnews.png +0 -0
  50. data/assets/img/base/page-with-color.png +0 -0
  51. data/assets/img/base/page-with-copyright.png +0 -0
  52. data/assets/img/base/page-with-copyvalue.png +0 -0
  53. data/assets/img/base/page-with-datatable.png +0 -0
  54. data/assets/img/base/page-with-event.png +0 -0
  55. data/assets/img/base/page-with-fontawesome.png +0 -0
  56. data/assets/img/base/page-with-footer.png +0 -0
  57. data/assets/img/base/page-with-heading.png +0 -0
  58. data/assets/img/base/page-with-highlight.png +0 -0
  59. data/assets/img/base/page-with-link.png +0 -0
  60. data/assets/img/base/page-with-locales.png +0 -0
  61. data/assets/img/base/page-with-navbar.png +0 -0
  62. data/assets/img/base/page-with-navindex.png +0 -0
  63. data/assets/img/base/page-with-ogp.png +0 -0
  64. data/assets/img/base/page-with-project.png +0 -0
  65. data/assets/img/base/page-with-shortcut.png +0 -0
  66. data/assets/img/base/page-with-social.png +0 -0
  67. data/assets/img/base/page-with-sponsors.png +0 -0
  68. data/assets/img/base/page-with-title.png +0 -0
  69. data/assets/img/base/page-with-toc.png +0 -0
  70. data/assets/img/base/screenshot-1200x600.png +0 -0
@@ -1,187 +1,71 @@
1
1
  // Copy Value Component
2
- // Provides copy-to-clipboard functionality with visual feedback
3
- // Safely handles escaped and unescaped values, HTML entities, and special characters
4
- // ARMORED IMPLEMENTATION: Handles any value passed via data-copy-value attribute
2
+ // Provides copy-to-clipboard functionality with visual feedback.
5
3
 
6
4
  (function () {
7
5
  class CopyButtonHandler {
8
6
  constructor (button, config = {}) {
9
7
  this.button = button
10
- this.originalTitle = this.button.getAttribute('data-bs-title') || this.button.getAttribute('aria-label') || this.button.getAttribute('title')
11
- this.originalSvgHTML = this.button.innerHTML
8
+ this.originalTitle = button.getAttribute('data-bs-title') || button.getAttribute('aria-label') || button.getAttribute('title')
12
9
  this.resetDelay = config.resetDelay || 2000
13
10
  this.checkmarkPath = config.checkmarkPath || 'M434.8 70.1c14.3 10.4 17.5 30.4 7.1 44.7l-256 352c-5.5 7.6-14 12.3-23.4 13.1s-18.5-2.7-25.1-9.3l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l101.5 101.5 234-321.7c10.4-14.3 30.4-17.5 44.7-7.1z'
14
11
  this.checkmarkViewbox = config.checkmarkViewbox || '0 0 448 512'
15
12
  this.successMessage = config.successMessage || 'Copied!'
13
+ this.originalIcon = this._captureIcon()
16
14
 
17
- this.button.addEventListener('click', (e) => this.handleClick(e))
15
+ button.addEventListener('click', (e) => this.handleClick(e))
18
16
  }
19
17
 
20
- handleClick (e) {
21
- e.preventDefault()
22
-
23
- // ARMOR: Retrieve the attribute value (may be escaped or unescaped)
24
- let rawValue = this.button.getAttribute('data-copy-value')
25
-
26
- // ARMOR: If attribute appears truncated or incomplete, try HTML extraction fallback
27
- const appearsTruncated = !rawValue ||
28
- rawValue.endsWith('=') ||
29
- rawValue.match(/^[a-zA-Z-]+$/) ||
30
- (rawValue.length < 5 && rawValue.includes(' '))
31
-
32
- if (appearsTruncated) {
33
- const extractedValue = this.extractDataCopyValueFromHTML()
34
- if (extractedValue && extractedValue.length > (rawValue?.length || 0)) {
35
- rawValue = extractedValue
36
- }
18
+ _captureIcon () {
19
+ const svg = this.button.querySelector('svg')
20
+ if (svg) {
21
+ const path = svg.querySelector('path')
22
+ return { mode: 'svg', viewBox: svg.getAttribute('viewBox'), pathD: path ? path.getAttribute('d') : null }
37
23
  }
38
-
39
- // Defensive check: ensure we have a value to copy
40
- if (!rawValue) {
41
- console.warn('No copy value found in data-copy-value attribute', this.button)
42
- return
24
+ const iconEl = this.button.querySelector('[class*="fa-"]')
25
+ if (iconEl) {
26
+ return { mode: 'css', className: iconEl.className }
43
27
  }
28
+ return null
29
+ }
44
30
 
45
- // ARMOR: Auto-detect and handle both escaped and unescaped values
46
- const finalValue = this.normalizeAttributeValue(rawValue)
31
+ handleClick (e) {
32
+ e.preventDefault()
47
33
 
48
- const svg = this.button.querySelector('svg')
34
+ const value = this.button.getAttribute('data-copy-value')
49
35
 
50
- if (!svg) {
51
- console.error('Icon SVG not found in button', this.button)
36
+ if (!value) {
37
+ console.warn('No copy value found in data-copy-value attribute', this.button)
52
38
  return
53
39
  }
54
40
 
55
- // ARMOR: Use trim() to remove accidental whitespace
56
- navigator.clipboard.writeText(finalValue.trim())
57
- .then(() => this.showSuccess(svg))
41
+ navigator.clipboard.writeText(value.trim())
42
+ .then(() => this.showSuccess())
58
43
  .catch((err) => {
59
- console.error('Failed to copy value:', finalValue, 'Error:', err)
44
+ console.error('Failed to copy value:', value, 'Error:', err)
60
45
  })
61
46
  }
62
47
 
63
- extractDataCopyValueFromHTML () {
64
- // ARMOR: Extract data-copy-value from raw HTML string
65
- try {
66
- const outerHTML = this.button.outerHTML
67
-
68
- const patterns = [
69
- /data-copy-value="([^"]*)"/,
70
- /data-copy-value='([^']*)'/,
71
- /data-copy-value="((?:[^"\\]|\\.*)*)"/,
72
- /data-copy-value="([^"]*(?:&quot;[^"]*)*?)"/,
73
- /data-copy-value=["']?([^"\s>]+?)["'\s>]/,
74
- /data-copy-value="([^"]*(?:[^"]*?)?)"/
75
- ]
76
-
77
- for (const pattern of patterns) {
78
- const match = outerHTML.match(pattern)
79
- if (match && match[1] && match[1].length > 0) {
80
- if (!match[1].startsWith('data-') && !match[1].startsWith('class') && !match[1].startsWith('id')) {
81
- return match[1]
82
- }
83
- }
84
- }
85
-
86
- const attrIndex = outerHTML.indexOf('data-copy-value')
87
- if (attrIndex !== -1) {
88
- const afterAttr = outerHTML.substring(attrIndex + 15).trim()
89
-
90
- if (afterAttr.startsWith('=')) {
91
- const afterEquals = afterAttr.substring(1).trim()
92
- const quoteChar = afterEquals[0]
93
-
94
- if (quoteChar === '"' || quoteChar === "'") {
95
- let endIndex = 1
96
- let escaped = false
97
-
98
- for (; endIndex < afterEquals.length; endIndex++) {
99
- const char = afterEquals[endIndex]
100
-
101
- if (escaped) {
102
- escaped = false
103
- continue
104
- }
105
-
106
- if (char === '\\') {
107
- escaped = true
108
- continue
109
- }
110
-
111
- if (char === quoteChar) {
112
- return afterEquals.substring(1, endIndex)
113
- }
114
- }
115
- }
116
- }
117
- }
118
-
119
- return null
120
- } catch (err) {
121
- console.warn('Failed to extract data-copy-value from HTML:', err)
122
- return null
123
- }
124
- }
125
-
126
- normalizeAttributeValue (text) {
127
- // ARMOR: Smart normalization for escaped and unescaped values
128
- if (!text) {
129
- return text
130
- }
131
-
132
- const hasHTMLEntities = /&(?:quot|apos|amp|lt|gt|#34|#39|#47|#60|#62|#x22|#x27|#x2[Ff]|#x3[Cc]|#x3[Ee]);/.test(text)
133
-
134
- if (hasHTMLEntities) {
135
- return this.decodeHTMLEntities(text)
136
- }
137
-
138
- const hasUnescapedQuotes = /"(?![>\s])|'(?![>\s])/.test(text.trim())
139
- const hasUnescapedSpecialChars = /[<>]/.test(text)
140
-
141
- if (hasUnescapedQuotes || hasUnescapedSpecialChars) {
142
- return text
143
- }
144
-
145
- return text
146
- }
147
-
148
- decodeHTMLEntities (text) {
149
- // ARMOR: Comprehensively decode HTML entities
150
- const textarea = document.createElement('textarea')
151
- textarea.innerHTML = text
152
- let decoded = textarea.value
153
-
154
- decoded = decoded
155
- .replace(/&quot;/gi, '"')
156
- .replace(/&#34;/gi, '"')
157
- .replace(/&#x22;/gi, '"')
158
- .replace(/&#39;/gi, "'")
159
- .replace(/&apos;/gi, "'")
160
- .replace(/&#x27;/gi, "'")
161
- .replace(/&#x2[Ff];/g, '/')
162
- .replace(/&#47;/g, '/')
163
- .replace(/&lt;/gi, '<')
164
- .replace(/&#60;/gi, '<')
165
- .replace(/&#x3[Cc];/g, '<')
166
- .replace(/&gt;/gi, '>')
167
- .replace(/&#62;/gi, '>')
168
- .replace(/&#x3[Ee];/g, '>')
169
- .replace(/&amp;/gi, '&')
170
-
171
- return decoded
172
- }
173
-
174
- showSuccess (svg) {
175
- this.changeToCheckmark(svg)
48
+ showSuccess () {
49
+ this.changeToCheckmark()
176
50
  this.updateTooltip(this.successMessage)
177
- setTimeout(() => this.reset(svg), this.resetDelay)
51
+ setTimeout(() => this.reset(), this.resetDelay)
178
52
  }
179
53
 
180
- changeToCheckmark (svg) {
181
- const path = svg.querySelector('path')
182
- if (path) {
183
- svg.setAttribute('viewBox', this.checkmarkViewbox)
184
- path.setAttribute('d', this.checkmarkPath)
54
+ changeToCheckmark () {
55
+ if (!this.originalIcon) return
56
+
57
+ if (this.originalIcon.mode === 'svg') {
58
+ const svg = this.button.querySelector('svg')
59
+ if (svg) {
60
+ svg.setAttribute('viewBox', this.checkmarkViewbox)
61
+ const path = svg.querySelector('path')
62
+ if (path) path.setAttribute('d', this.checkmarkPath)
63
+ }
64
+ } else {
65
+ // CSS/webfont mode: fa-check only exists in Solid style — force fa-solid
66
+ // regardless of the original style prefix to avoid a missing-glyph box.
67
+ const iconEl = this.button.querySelector('[class*="fa-"]')
68
+ if (iconEl) iconEl.className = 'fa-solid fa-check'
185
69
  }
186
70
  }
187
71
 
@@ -205,44 +89,44 @@ class CopyButtonHandler {
205
89
  }
206
90
  }
207
91
 
208
- reset (svg) {
209
- this.button.innerHTML = this.originalSvgHTML
92
+ reset () {
93
+ if (this.originalIcon) {
94
+ if (this.originalIcon.mode === 'svg') {
95
+ const svg = this.button.querySelector('svg')
96
+ if (svg) {
97
+ svg.setAttribute('viewBox', this.originalIcon.viewBox)
98
+ const path = svg.querySelector('path')
99
+ if (path && this.originalIcon.pathD) path.setAttribute('d', this.originalIcon.pathD)
100
+ }
101
+ } else {
102
+ const iconEl = this.button.querySelector('[class*="fa-"]')
103
+ if (iconEl) iconEl.className = this.originalIcon.className
104
+ }
105
+ }
106
+
210
107
  this.updateTooltip(this.originalTitle)
211
108
 
212
109
  try {
213
110
  const tooltip = bootstrap.Tooltip.getInstance(this.button)
214
- if (tooltip) {
215
- tooltip.hide()
216
- }
111
+ if (tooltip) tooltip.hide()
217
112
  } catch (err) {
218
113
  console.warn('Bootstrap Tooltip unavailable or error hiding tooltip:', err)
219
114
  }
220
115
  }
221
116
  }
222
117
 
223
- // Initialize all copy buttons when DOM is ready
224
118
  document.addEventListener('DOMContentLoaded', function () {
225
- // Get configuration from script's data attributes
226
119
  const scriptElement = document.getElementById('centos-copyvalue')
227
120
  const config = {}
228
121
 
229
122
  if (scriptElement) {
230
- if (scriptElement.dataset.resetDelay) {
231
- config.resetDelay = parseInt(scriptElement.dataset.resetDelay, 10)
232
- }
233
- if (scriptElement.dataset.checkmarkPath) {
234
- config.checkmarkPath = scriptElement.dataset.checkmarkPath
235
- }
236
- if (scriptElement.dataset.checkmarkViewbox) {
237
- config.checkmarkViewbox = scriptElement.dataset.checkmarkViewbox
238
- }
239
- if (scriptElement.dataset.successMessage) {
240
- config.successMessage = scriptElement.dataset.successMessage
241
- }
123
+ if (scriptElement.dataset.resetDelay) config.resetDelay = parseInt(scriptElement.dataset.resetDelay, 10)
124
+ if (scriptElement.dataset.checkmarkPath) config.checkmarkPath = scriptElement.dataset.checkmarkPath
125
+ if (scriptElement.dataset.checkmarkViewbox) config.checkmarkViewbox = scriptElement.dataset.checkmarkViewbox
126
+ if (scriptElement.dataset.successMessage) config.successMessage = scriptElement.dataset.successMessage
242
127
  }
243
128
 
244
- const copyButtons = document.querySelectorAll('.copy-btn')
245
- copyButtons.forEach(button => {
129
+ document.querySelectorAll('.copy-btn').forEach(button => {
246
130
  try {
247
131
  new CopyButtonHandler(button, config)
248
132
  } catch (err) {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-theme-centos
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.52.0.beta.57
4
+ version: 2.52.0.beta.59
5
5
  platform: ruby
6
6
  authors:
7
7
  - ReleaseBot
@@ -488,83 +488,44 @@ files:
488
488
  - assets/img/anaconda-symbolic.svg
489
489
  - assets/img/anaconda.svg
490
490
  - assets/img/base/centos-colors.gpl
491
- - assets/img/base/example-ogp-image.png
492
491
  - assets/img/base/example-ogp-image.svg
493
- - assets/img/base/example-sponsors-design.png
494
492
  - assets/img/base/example-sponsors-design.svg
495
- - assets/img/base/example-sponsors-logo-1.png
496
493
  - assets/img/base/example-sponsors-logo-1.svg
497
- - assets/img/base/example-sponsors-logo-2.png
498
494
  - assets/img/base/example-sponsors-logo-2.svg
499
- - assets/img/base/example-sponsors-logo-3.png
500
495
  - assets/img/base/example-sponsors-logo-3.svg
501
- - assets/img/base/example-sponsors-logo-4.png
502
496
  - assets/img/base/example-sponsors-logo-4.svg
503
- - assets/img/base/example-sponsors-logo-5.png
504
497
  - assets/img/base/example-sponsors-logo-5.svg
505
- - assets/img/base/example-sponsors-logo-6.png
506
498
  - assets/img/base/example-sponsors-logo-6.svg
507
- - assets/img/base/example-sponsors-logo-7.png
508
499
  - assets/img/base/example-sponsors-logo-7.svg
509
- - assets/img/base/example-sponsors-logo-8.png
510
500
  - assets/img/base/example-sponsors-logo-8.svg
511
- - assets/img/base/page-layout-default.png
512
501
  - assets/img/base/page-layout-default.svg
513
- - assets/img/base/page-with-alert.png
514
502
  - assets/img/base/page-with-alert.svg
515
- - assets/img/base/page-with-announcement.png
516
503
  - assets/img/base/page-with-announcement.svg
517
- - assets/img/base/page-with-artwork.png
518
504
  - assets/img/base/page-with-artwork.svg
519
- - assets/img/base/page-with-backtotop.png
520
505
  - assets/img/base/page-with-backtotop.svg
521
- - assets/img/base/page-with-bits.png
522
506
  - assets/img/base/page-with-bits.svg
523
- - assets/img/base/page-with-breadcrumb.png
524
507
  - assets/img/base/page-with-breadcrumb.svg
525
- - assets/img/base/page-with-breakingnews.png
526
508
  - assets/img/base/page-with-breakingnews.svg
527
- - assets/img/base/page-with-color.png
528
509
  - assets/img/base/page-with-color.svg
529
- - assets/img/base/page-with-copyright.png
530
510
  - assets/img/base/page-with-copyright.svg
531
- - assets/img/base/page-with-copyvalue.png
532
511
  - assets/img/base/page-with-copyvalue.svg
533
- - assets/img/base/page-with-datatable.png
534
512
  - assets/img/base/page-with-datatable.svg
535
- - assets/img/base/page-with-event.png
536
513
  - assets/img/base/page-with-event.svg
537
- - assets/img/base/page-with-fontawesome.png
538
514
  - assets/img/base/page-with-fontawesome.svg
539
- - assets/img/base/page-with-footer.png
540
515
  - assets/img/base/page-with-footer.svg
541
- - assets/img/base/page-with-heading.png
542
516
  - assets/img/base/page-with-heading.svg
543
- - assets/img/base/page-with-highlight.png
544
517
  - assets/img/base/page-with-highlight.svg
545
- - assets/img/base/page-with-link.png
546
518
  - assets/img/base/page-with-link.svg
547
- - assets/img/base/page-with-locales.png
548
519
  - assets/img/base/page-with-locales.svg
549
- - assets/img/base/page-with-navbar.png
550
520
  - assets/img/base/page-with-navbar.svg
551
- - assets/img/base/page-with-navindex.png
552
521
  - assets/img/base/page-with-navindex.svg
553
- - assets/img/base/page-with-ogp.png
554
522
  - assets/img/base/page-with-ogp.svg
555
- - assets/img/base/page-with-project.png
556
523
  - assets/img/base/page-with-project.svg
557
- - assets/img/base/page-with-shortcut.png
558
524
  - assets/img/base/page-with-shortcut.svg
559
- - assets/img/base/page-with-social.png
560
525
  - assets/img/base/page-with-social.svg
561
- - assets/img/base/page-with-sponsors.png
562
526
  - assets/img/base/page-with-sponsors.svg
563
- - assets/img/base/page-with-title.png
564
527
  - assets/img/base/page-with-title.svg
565
- - assets/img/base/page-with-toc.png
566
528
  - assets/img/base/page-with-toc.svg
567
- - assets/img/base/screenshot-1200x600.png
568
529
  - assets/img/base/screenshot-1200x600.svg
569
530
  - assets/img/centos-dynamicmsg-logo.svg
570
531
  - assets/img/centos-dynamicmsg-type.svg
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file