rawfeed 0.2.11 → 0.3.1
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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +12 -0
- data/_data/options.yml +47 -0
- data/_includes/layout/data.liquid +2 -0
- data/_layouts/contact.html +130 -50
- data/_layouts/default.html +13 -6
- data/_layouts/donation.html +113 -0
- data/_sass/base/_index.scss +4 -7
- data/_sass/components/_markdown.scss +1 -2
- data/_sass/layouts/_donation.scss +93 -0
- data/_sass/layouts/_index.scss +1 -0
- data/_sass/layouts/_post.scss +146 -0
- data/_sass/main.scss +10 -0
- data/_sass/theme/_dark.scss +5 -0
- data/_sass/theme/_light.scss +5 -0
- data/assets/images/icons/bitcoin.svg +6 -0
- data/assets/images/icons/card.svg +17 -0
- data/assets/images/icons/donation.svg +11 -0
- data/assets/images/icons/lightning_network.svg +11 -0
- data/assets/images/icons/paypal.svg +7 -0
- data/assets/images/icons/pix.svg +1 -0
- data/assets/images/icons/wos.png +0 -0
- data/assets/images/qrcode_btc_binance.jpg +0 -0
- data/assets/images/qrcode_inter.jpg +0 -0
- data/assets/images/qrcode_wos.jpg +0 -0
- data/assets/js/donation.js +30 -0
- data/assets/js/{fallback/page.js → page.js} +94 -167
- data/lib/rawfeed/version.rb +1 -1
- metadata +26 -41
- data/_includes/toc +0 -20
- data/assets/js/blog.coffee +0 -102
- data/assets/js/contact.coffee +0 -105
- data/assets/js/default.coffee +0 -172
- data/assets/js/discus.coffee +0 -30
- data/assets/js/fallback/README.md +0 -3
- data/assets/js/fallback/google_analytics.js +0 -15
- data/assets/js/home.coffee +0 -250
- data/assets/js/no_inframe.coffee +0 -9
- data/assets/js/page.coffee +0 -379
- data/assets/js/pixels.coffee +0 -2
- data/assets/js/resume.coffee +0 -9
- data/assets/js/tags.coffee +0 -2
- data/assets/js/theme_load.coffee +0 -6
- /data/assets/js/{fallback/blog.js → blog.js} +0 -0
- /data/assets/js/{fallback/contact.js → contact.js} +0 -0
- /data/assets/js/{fallback/default.js → default.js} +0 -0
- /data/assets/js/{fallback/discus.js → discus.js} +0 -0
- /data/assets/js/{fallback/home.js → home.js} +0 -0
- /data/assets/js/{fallback/no_inframe.js → no_inframe.js} +0 -0
- /data/assets/js/{fallback/pixels.js → pixels.js} +0 -0
- /data/assets/js/{fallback/resume.js → resume.js} +0 -0
- /data/assets/js/{fallback/tags.js → tags.js} +0 -0
- /data/assets/js/{fallback/theme_load.js → theme_load.js} +0 -0
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rawfeed
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William C. Canin
|
|
@@ -29,20 +29,6 @@ dependencies:
|
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '5.0'
|
|
32
|
-
- !ruby/object:Gem::Dependency
|
|
33
|
-
name: jekyll-coffeescript
|
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
|
35
|
-
requirements:
|
|
36
|
-
- - "~>"
|
|
37
|
-
- !ruby/object:Gem::Version
|
|
38
|
-
version: 2.0.0
|
|
39
|
-
type: :runtime
|
|
40
|
-
prerelease: false
|
|
41
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
-
requirements:
|
|
43
|
-
- - "~>"
|
|
44
|
-
- !ruby/object:Gem::Version
|
|
45
|
-
version: 2.0.0
|
|
46
32
|
- !ruby/object:Gem::Dependency
|
|
47
33
|
name: jekyll-sitemap
|
|
48
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -133,7 +119,7 @@ executables: []
|
|
|
133
119
|
extensions: []
|
|
134
120
|
extra_rdoc_files: []
|
|
135
121
|
files:
|
|
136
|
-
- LICENSE
|
|
122
|
+
- LICENSE
|
|
137
123
|
- README.md
|
|
138
124
|
- _data/options.yml
|
|
139
125
|
- _data/resume.yml
|
|
@@ -154,11 +140,11 @@ files:
|
|
|
154
140
|
- _includes/layout/paginator.html
|
|
155
141
|
- _includes/socials
|
|
156
142
|
- _includes/tabs
|
|
157
|
-
- _includes/toc
|
|
158
143
|
- _includes/video
|
|
159
144
|
- _layouts/blog.html
|
|
160
145
|
- _layouts/contact.html
|
|
161
146
|
- _layouts/default.html
|
|
147
|
+
- _layouts/donation.html
|
|
162
148
|
- _layouts/error.html
|
|
163
149
|
- _layouts/home.html
|
|
164
150
|
- _layouts/licenses.html
|
|
@@ -191,6 +177,7 @@ files:
|
|
|
191
177
|
- _sass/layouts/_blog.scss
|
|
192
178
|
- _sass/layouts/_contact.scss
|
|
193
179
|
- _sass/layouts/_default.scss
|
|
180
|
+
- _sass/layouts/_donation.scss
|
|
194
181
|
- _sass/layouts/_error.scss
|
|
195
182
|
- _sass/layouts/_home.scss
|
|
196
183
|
- _sass/layouts/_index.scss
|
|
@@ -213,31 +200,29 @@ files:
|
|
|
213
200
|
- assets/images/avatar_light.png
|
|
214
201
|
- assets/images/blog/.keep
|
|
215
202
|
- assets/images/favicon.png
|
|
203
|
+
- assets/images/icons/bitcoin.svg
|
|
204
|
+
- assets/images/icons/card.svg
|
|
205
|
+
- assets/images/icons/donation.svg
|
|
206
|
+
- assets/images/icons/lightning_network.svg
|
|
207
|
+
- assets/images/icons/paypal.svg
|
|
208
|
+
- assets/images/icons/pix.svg
|
|
209
|
+
- assets/images/icons/wos.png
|
|
216
210
|
- assets/images/pixels/luffy.jpg
|
|
217
|
-
- assets/
|
|
218
|
-
- assets/
|
|
219
|
-
- assets/
|
|
220
|
-
- assets/js/
|
|
221
|
-
- assets/js/
|
|
222
|
-
- assets/js/
|
|
223
|
-
- assets/js/
|
|
224
|
-
- assets/js/
|
|
225
|
-
- assets/js/
|
|
226
|
-
- assets/js/
|
|
227
|
-
- assets/js/
|
|
228
|
-
- assets/js/
|
|
229
|
-
- assets/js/
|
|
230
|
-
- assets/js/
|
|
231
|
-
- assets/js/
|
|
232
|
-
- assets/js/fallback/tags.js
|
|
233
|
-
- assets/js/fallback/theme_load.js
|
|
234
|
-
- assets/js/home.coffee
|
|
235
|
-
- assets/js/no_inframe.coffee
|
|
236
|
-
- assets/js/page.coffee
|
|
237
|
-
- assets/js/pixels.coffee
|
|
238
|
-
- assets/js/resume.coffee
|
|
239
|
-
- assets/js/tags.coffee
|
|
240
|
-
- assets/js/theme_load.coffee
|
|
211
|
+
- assets/images/qrcode_btc_binance.jpg
|
|
212
|
+
- assets/images/qrcode_inter.jpg
|
|
213
|
+
- assets/images/qrcode_wos.jpg
|
|
214
|
+
- assets/js/blog.js
|
|
215
|
+
- assets/js/contact.js
|
|
216
|
+
- assets/js/default.js
|
|
217
|
+
- assets/js/discus.js
|
|
218
|
+
- assets/js/donation.js
|
|
219
|
+
- assets/js/home.js
|
|
220
|
+
- assets/js/no_inframe.js
|
|
221
|
+
- assets/js/page.js
|
|
222
|
+
- assets/js/pixels.js
|
|
223
|
+
- assets/js/resume.js
|
|
224
|
+
- assets/js/tags.js
|
|
225
|
+
- assets/js/theme_load.js
|
|
241
226
|
- assets/json/blog_search.json
|
|
242
227
|
- assets/json/datelang.json
|
|
243
228
|
- assets/vendor/bootstrap/css/bootstrap-grid.css
|
data/_includes/toc
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{%- include layout/data.liquid -%}
|
|
2
|
-
|
|
3
|
-
<nav id="toc"
|
|
4
|
-
style="border-top-left-radius: 0px !important; border-top-right-radius: 0px !important;"
|
|
5
|
-
class="toc{% if default_.rounding %} rounding-plugins{% endif %}{% if default_.background_focus %} background_focus{% endif %}"
|
|
6
|
-
data-toc-selector="{{ include.selector | default: '.post-content' }}"
|
|
7
|
-
data-toc-max-level="{{ include.max_level | default: 3 }}"
|
|
8
|
-
data-toc-scroll-offset="{{ include.scroll_offset | default: 20 }}"
|
|
9
|
-
data-btn-show="{{ include.btn_show }}"
|
|
10
|
-
data-btn-hidden="{{ include.btn_hidden }}">
|
|
11
|
-
|
|
12
|
-
<div class="toc-head">
|
|
13
|
-
<h2>{{ include.title | default: "TOC" }}</h2>
|
|
14
|
-
<button class="toc-toggle" aria-expanded="true" type="button"></button>
|
|
15
|
-
</div>
|
|
16
|
-
<div class="toc-list-wrapper">
|
|
17
|
-
<ul class="toc-list" role="list"></ul>
|
|
18
|
-
<p class="toc-empty" style="display:none">No titles found. Remove TOC!</p>
|
|
19
|
-
</div>
|
|
20
|
-
</nav>
|
data/assets/js/blog.coffee
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
{%- include layout/data.liquid -%}
|
|
5
|
-
|
|
6
|
-
document.addEventListener "DOMContentLoaded", ->
|
|
7
|
-
|
|
8
|
-
blog = document.getElementById "blog"
|
|
9
|
-
|
|
10
|
-
if blog
|
|
11
|
-
btn = document.getElementById 'blog-search__btn'
|
|
12
|
-
box = document.querySelector '.blog-search'
|
|
13
|
-
searchInput = document.getElementById 'blog-search__input'
|
|
14
|
-
blogPosts = document.getElementById 'posts'
|
|
15
|
-
searchResults = document.getElementById 'blog-search__results'
|
|
16
|
-
searchResultsWrapper = document.getElementById 'blog-search__results-wrapper'
|
|
17
|
-
btnSearchClean = document.getElementById 'blog-search__btn-clean'
|
|
18
|
-
blogSeachInput = document.getElementById 'blog-search__input'
|
|
19
|
-
|
|
20
|
-
openSearch = ->
|
|
21
|
-
box.classList.add 'is-open'
|
|
22
|
-
box.removeAttribute 'inert'
|
|
23
|
-
box.style.maxHeight = "#{box.scrollHeight}px"
|
|
24
|
-
box.style.opacity = '1'
|
|
25
|
-
box.addEventListener 'transitionend', onOpened = (e) ->
|
|
26
|
-
if e.propertyName is 'max-height'
|
|
27
|
-
box.style.maxHeight = 'none'
|
|
28
|
-
box.removeEventListener 'transitionend', onOpened
|
|
29
|
-
blogSeachInput.focus()
|
|
30
|
-
|
|
31
|
-
closeSearch = ->
|
|
32
|
-
box.style.maxHeight = "#{box.scrollHeight}px"
|
|
33
|
-
_ = box.offsetHeight # reflow force
|
|
34
|
-
requestAnimationFrame ->
|
|
35
|
-
box.style.maxHeight = '0'
|
|
36
|
-
box.style.opacity = '0'
|
|
37
|
-
box.setAttribute 'inert', ''
|
|
38
|
-
box.classList.remove 'is-open'
|
|
39
|
-
|
|
40
|
-
btn.addEventListener 'click', (e) ->
|
|
41
|
-
e.preventDefault()
|
|
42
|
-
|
|
43
|
-
# if are already in /blog/, toggle
|
|
44
|
-
pathname = location.pathname.replace /\/$/, ''
|
|
45
|
-
isBlog = pathname is '/blog' or pathname is '/blog/index.html'
|
|
46
|
-
|
|
47
|
-
unless isBlog
|
|
48
|
-
# if are on another page, go to /blog/ and open it
|
|
49
|
-
window.location.href = "{{ search_url }}"
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
# toggle
|
|
53
|
-
if box.classList.contains 'is-open'
|
|
54
|
-
closeSearch()
|
|
55
|
-
searchInput.value = ''
|
|
56
|
-
blogPosts.classList.remove 'disabled'
|
|
57
|
-
searchResultsWrapper.classList.add 'disabled'
|
|
58
|
-
else
|
|
59
|
-
openSearch()
|
|
60
|
-
|
|
61
|
-
# opens automatically if arrived from another link with ?search=open
|
|
62
|
-
params = new URLSearchParams location.search
|
|
63
|
-
if params.get('search') is 'open'
|
|
64
|
-
setTimeout openSearch, 30
|
|
65
|
-
|
|
66
|
-
# clean button input blog search
|
|
67
|
-
# ----------------------------------------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
clearSearch = ->
|
|
70
|
-
blogSeachInput.value = ''
|
|
71
|
-
blogPosts.classList.remove 'disabled'
|
|
72
|
-
searchResults.classList.add 'disabled'
|
|
73
|
-
searchResultsWrapper.classList.add 'disabled'
|
|
74
|
-
blogSeachInput.focus()
|
|
75
|
-
|
|
76
|
-
btnSearchClean.addEventListener 'click', clearSearch
|
|
77
|
-
|
|
78
|
-
document.addEventListener 'keydown', (e) ->
|
|
79
|
-
if e.key is 'Escape'
|
|
80
|
-
clearSearch()
|
|
81
|
-
closeSearch()
|
|
82
|
-
|
|
83
|
-
# open results and close posts in search (toggle)
|
|
84
|
-
# ----------------------------------------------------------------------------------------------
|
|
85
|
-
|
|
86
|
-
searchInput.addEventListener 'input', ->
|
|
87
|
-
if searchInput.value.trim().length > 0
|
|
88
|
-
blogPosts.classList.add 'disabled'
|
|
89
|
-
searchResults.classList.remove 'disabled'
|
|
90
|
-
searchResultsWrapper.classList.remove 'disabled'
|
|
91
|
-
else
|
|
92
|
-
blogPosts.classList.remove 'disabled'
|
|
93
|
-
searchResults.classList.add 'disabled'
|
|
94
|
-
searchResultsWrapper.classList.add 'disabled'
|
|
95
|
-
|
|
96
|
-
sjs = SimpleJekyllSearch
|
|
97
|
-
searchInput: document.getElementById 'blog-search__input'
|
|
98
|
-
resultsContainer: document.getElementById 'blog-search__results'
|
|
99
|
-
searchResultTemplate: '<li><span class="blog-list__meta"><time datetime="{date}">{date}</time></span> » <a class="blog-list__link" href="{{ site.url }}{url}">{title}</a></li>'
|
|
100
|
-
noResultsText: '<p>{{ blog_.no_results | default: "No results found" }}</p>'
|
|
101
|
-
json: "{{ '/assets/json/blog_search.json' | relative_url }}"
|
|
102
|
-
|
data/assets/js/contact.coffee
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
{%- include layout/data.liquid -%}
|
|
5
|
-
|
|
6
|
-
document.addEventListener "DOMContentLoaded", ->
|
|
7
|
-
|
|
8
|
-
contact = document.getElementById "contact"
|
|
9
|
-
|
|
10
|
-
if contact
|
|
11
|
-
form = document.getElementById "contactForm"
|
|
12
|
-
submitButton = document.getElementById "submitButton"
|
|
13
|
-
endpoint = "{{ head_.google.apps_script.url }}" # URL Google Apps Script
|
|
14
|
-
|
|
15
|
-
# função para exibir modal
|
|
16
|
-
showModal = (title, message, type = 'success') ->
|
|
17
|
-
modalEl = document.getElementById 'contactMessageModal'
|
|
18
|
-
modalTitle = modalEl.querySelector '.modal-title'
|
|
19
|
-
modalBody = modalEl.querySelector '.modal-body'
|
|
20
|
-
modalContent = modalEl.querySelector '.modal-content'
|
|
21
|
-
|
|
22
|
-
modalContent.classList.remove 'contact-message-success', 'contact-message-error', 'contact-message-warning'
|
|
23
|
-
|
|
24
|
-
# Aplica a cor de acordo com o tipo
|
|
25
|
-
if type is 'success'
|
|
26
|
-
modalContent.classList.add 'contact-message-success'
|
|
27
|
-
else if type is 'error'
|
|
28
|
-
modalContent.classList.add 'contact-message-error'
|
|
29
|
-
else if type is 'warning'
|
|
30
|
-
modalContent.classList.add 'contact-message-warning'
|
|
31
|
-
|
|
32
|
-
modalTitle.innerHTML = title
|
|
33
|
-
modalBody.innerHTML = message
|
|
34
|
-
|
|
35
|
-
bsModal = new bootstrap.Modal modalEl
|
|
36
|
-
bsModal.show()
|
|
37
|
-
|
|
38
|
-
form.addEventListener "submit", (e) ->
|
|
39
|
-
e.preventDefault()
|
|
40
|
-
|
|
41
|
-
recaptchaResponse = grecaptcha.getResponse()
|
|
42
|
-
unless recaptchaResponse
|
|
43
|
-
showModal(
|
|
44
|
-
"""{{ contact_.recaptcha.warning.title | default: "Warning" }}""",
|
|
45
|
-
"""{{ contact_.recaptcha.warning.content | default: "Please tick the 'I'm not a robot' box." }}""",
|
|
46
|
-
"warning"
|
|
47
|
-
)
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
textarea = document.getElementById 'textMessage'
|
|
51
|
-
text = textarea.value.trim()
|
|
52
|
-
if text.length < "{{ contact_.message.caracters.min }}"
|
|
53
|
-
showModal(
|
|
54
|
-
"""{{ contact_.message.caracters.warning.title | default: "Warning" }}""",
|
|
55
|
-
"""{{ contact_.message.caracters.warning.content | default: "The message must have at least 50 characters." }}""",
|
|
56
|
-
"warning"
|
|
57
|
-
)
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
submitButton.disabled = true
|
|
61
|
-
submitButton.textContent = """{{ contact_.message.status | default: "Sending...Wait" }}"""
|
|
62
|
-
|
|
63
|
-
formData = new FormData form
|
|
64
|
-
data = Object.fromEntries formData.entries()
|
|
65
|
-
|
|
66
|
-
fetch(endpoint,
|
|
67
|
-
method: "POST"
|
|
68
|
-
redirect: "follow"
|
|
69
|
-
body: JSON.stringify data
|
|
70
|
-
).then (response) ->
|
|
71
|
-
response.json()
|
|
72
|
-
.then (result) ->
|
|
73
|
-
if result.result is 'success'
|
|
74
|
-
form.reset()
|
|
75
|
-
grecaptcha.reset()
|
|
76
|
-
showModal(
|
|
77
|
-
"""{{ contact_.message.success.title | default: "Message Sent" }}""",
|
|
78
|
-
"""{{ contact_.message.success.content | default: "Your message has been sent successfully!" }}""",
|
|
79
|
-
"success"
|
|
80
|
-
)
|
|
81
|
-
else
|
|
82
|
-
showModal(
|
|
83
|
-
"""{{ contact_.message.error.title | default: "Error" }}""",
|
|
84
|
-
"""{{ contact_.message.error.content | default: "Something went wrong while sending your message." }}""",
|
|
85
|
-
"error"
|
|
86
|
-
)
|
|
87
|
-
throw new Error result.message or "{{ contact_.message.error.content | default: 'An unknown error has occurred.' }}"
|
|
88
|
-
.catch (error) ->
|
|
89
|
-
console.error "Error sending:", error
|
|
90
|
-
if error.message.includes "reCAPTCHA"
|
|
91
|
-
showModal(
|
|
92
|
-
"""{{ contact_.message.error.title | default: "Error" }}""",
|
|
93
|
-
"""{{ contact_.recaptcha.fail | default: "Verification failed. Please reload the page and try again." }}""",
|
|
94
|
-
"error"
|
|
95
|
-
)
|
|
96
|
-
else
|
|
97
|
-
showModal(
|
|
98
|
-
"""{{ contact_.message.error.title | default: "Error" }}""",
|
|
99
|
-
"""{{ contact_.recaptcha.error | default: "An error occurred while sending the message. Please try again." }}""",
|
|
100
|
-
"error"
|
|
101
|
-
)
|
|
102
|
-
grecaptcha.reset()
|
|
103
|
-
.finally ->
|
|
104
|
-
submitButton.disabled = false
|
|
105
|
-
submitButton.textContent = """{{ contact_.button.text | default: "Send!" }}"""
|
data/assets/js/default.coffee
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
{%- include layout/data.liquid -%}
|
|
5
|
-
|
|
6
|
-
# Script that will be used throughout the site
|
|
7
|
-
|
|
8
|
-
document.addEventListener "DOMContentLoaded", ->
|
|
9
|
-
# lock menu context (click right mouse)
|
|
10
|
-
# ------------------------------------------------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
document.addEventListener 'contextmenu', (e) -> e.preventDefault()
|
|
13
|
-
|
|
14
|
-
# avatar
|
|
15
|
-
#-------------------------------------------------------------------------------------------------
|
|
16
|
-
do ->
|
|
17
|
-
flipperAvatars = document.querySelectorAll('.avatar-flipper__open-true')
|
|
18
|
-
modalEl = document.getElementById('avatarModal')
|
|
19
|
-
modalAvatar = document.getElementById('modalAvatar')
|
|
20
|
-
header = document.querySelector('.header')
|
|
21
|
-
bsModal = new bootstrap.Modal(modalEl)
|
|
22
|
-
|
|
23
|
-
for flipper in flipperAvatars
|
|
24
|
-
do (flipper) -> # the 'do' creates a new scope and passes the 'flipper' as an argument
|
|
25
|
-
flipper.addEventListener "click", ->
|
|
26
|
-
# NOW, 'flipper' refers to the correct avatar as it was isolated by IIFE
|
|
27
|
-
card = flipper.querySelector('.avatar-card')
|
|
28
|
-
backImage = flipper.querySelector('.avatar-back img')
|
|
29
|
-
backImageSrc = backImage.src
|
|
30
|
-
|
|
31
|
-
card.classList.add "flip-avatar"
|
|
32
|
-
|
|
33
|
-
card.addEventListener "animationend", (event) ->
|
|
34
|
-
card.classList.remove "flip-avatar"
|
|
35
|
-
modalAvatar.src = backImageSrc
|
|
36
|
-
bsModal.show()
|
|
37
|
-
, { once: true }
|
|
38
|
-
|
|
39
|
-
modalEl.addEventListener "shown.bs.modal", ->
|
|
40
|
-
modalAvatar.classList.remove "modal-avatar"
|
|
41
|
-
modalAvatar.offsetWidth
|
|
42
|
-
modalAvatar.classList.add "modal-avatar"
|
|
43
|
-
header.classList.remove "modal-active"
|
|
44
|
-
|
|
45
|
-
for f in flipperAvatars
|
|
46
|
-
f.classList.add "hidden"
|
|
47
|
-
|
|
48
|
-
modalEl.addEventListener "hidden.bs.modal", ->
|
|
49
|
-
for f in flipperAvatars
|
|
50
|
-
f.classList.remove "hidden"
|
|
51
|
-
|
|
52
|
-
# change theme light/dark
|
|
53
|
-
# ------------------------------------------------------------------------------------------------
|
|
54
|
-
#
|
|
55
|
-
toggleButton = document.getElementById 'toggle-theme'
|
|
56
|
-
iconToggleButton = toggleButton.querySelector 'i'
|
|
57
|
-
root = document.documentElement
|
|
58
|
-
|
|
59
|
-
setTheme = (theme) ->
|
|
60
|
-
root.setAttribute 'data-theme', theme
|
|
61
|
-
|
|
62
|
-
iconToggleButton.classList.remove 'fa-sun', 'fa-moon'
|
|
63
|
-
iconToggleButton.classList.add if theme is 'dark' then 'fa-sun' else 'fa-moon'
|
|
64
|
-
|
|
65
|
-
if typeof setGiscusTheme is 'function'
|
|
66
|
-
setGiscusTheme theme
|
|
67
|
-
|
|
68
|
-
localStorage.setItem 'theme', theme
|
|
69
|
-
|
|
70
|
-
# boot with saved or light
|
|
71
|
-
setTheme localStorage.getItem('theme') or 'light'
|
|
72
|
-
|
|
73
|
-
# change theme on click
|
|
74
|
-
toggleButton.addEventListener 'click', ->
|
|
75
|
-
current = root.getAttribute 'data-theme'
|
|
76
|
-
next = if current is 'light' then 'dark' else 'light'
|
|
77
|
-
setTheme next
|
|
78
|
-
|
|
79
|
-
# Show/disappear top button
|
|
80
|
-
# ------------------------------------------------------------------------------------------------
|
|
81
|
-
|
|
82
|
-
topButton = document.getElementById "top-link"
|
|
83
|
-
scrollThreshold = 700
|
|
84
|
-
window.onscroll = -> scrollFunction()
|
|
85
|
-
|
|
86
|
-
scrollFunction = ->
|
|
87
|
-
if document.body.scrollTop > scrollThreshold or document.documentElement.scrollTop > scrollThreshold
|
|
88
|
-
topButton.style.display = "block"
|
|
89
|
-
else
|
|
90
|
-
topButton.style.display = "none"
|
|
91
|
-
|
|
92
|
-
topButton.addEventListener "click", -> topFunction()
|
|
93
|
-
|
|
94
|
-
topFunction = ->
|
|
95
|
-
window.scrollTo
|
|
96
|
-
top: 0
|
|
97
|
-
behavior: 'smooth'
|
|
98
|
-
|
|
99
|
-
# function Giscus
|
|
100
|
-
# ------------------------------------------------------------------------------------------------
|
|
101
|
-
#
|
|
102
|
-
setGiscusTheme = (theme) ->
|
|
103
|
-
# The function only executes if the themes object exists
|
|
104
|
-
if window.giscusThemes
|
|
105
|
-
giscusTheme = if theme is 'light' then window.giscusThemes.light else window.giscusThemes.dark
|
|
106
|
-
|
|
107
|
-
message =
|
|
108
|
-
giscus:
|
|
109
|
-
setConfig:
|
|
110
|
-
theme: giscusTheme
|
|
111
|
-
|
|
112
|
-
# Let's use a timeout to ensure the Giscus iframe is ready
|
|
113
|
-
giscusInterval = setInterval ->
|
|
114
|
-
giscusFrame = document.querySelector 'iframe.giscus-frame'
|
|
115
|
-
# Se o iframe existir no documento...
|
|
116
|
-
if giscusFrame
|
|
117
|
-
# ...we sent the message...
|
|
118
|
-
giscusFrame.contentWindow.postMessage message, 'https://giscus.app'
|
|
119
|
-
# ...and we stopped trying.
|
|
120
|
-
clearInterval giscusInterval
|
|
121
|
-
, 500
|
|
122
|
-
|
|
123
|
-
# As an extra safeguard, we stop trying after a few seconds
|
|
124
|
-
# to avoid creating an infinite loop if something goes wrong.
|
|
125
|
-
setTimeout ->
|
|
126
|
-
clearInterval giscusInterval
|
|
127
|
-
, 4000 # Stop trying after 4 seconds
|
|
128
|
-
|
|
129
|
-
# giscus theme
|
|
130
|
-
#-------------------------------------------------------------------------------------------------
|
|
131
|
-
giscus = document.getElementById "giscus"
|
|
132
|
-
if giscus
|
|
133
|
-
window.giscusThemes
|
|
134
|
-
light: "{{ blog_.post.comments.giscus.theme_light | default: 'light' }}"
|
|
135
|
-
dark: "{{ blog_.post.comments.giscus.theme_dark | default: 'dark' }}"
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# highlight code
|
|
139
|
-
#-------------------------------------------------------------------------------------------------
|
|
140
|
-
document.querySelectorAll("div.highlight, figure.highlight").forEach (highlightBlock) ->
|
|
141
|
-
container = document.createElement "div"
|
|
142
|
-
container.className = "code-block-container"
|
|
143
|
-
header = document.createElement "div"
|
|
144
|
-
header.className = "code-block-header"
|
|
145
|
-
|
|
146
|
-
# button copy
|
|
147
|
-
button = document.createElement "button"
|
|
148
|
-
button.className = "copy-btn"
|
|
149
|
-
button.type = "button"
|
|
150
|
-
button.setAttribute "aria-label", "Copy code"
|
|
151
|
-
|
|
152
|
-
icon = document.createElement "i"
|
|
153
|
-
icon.className = "fa-solid fa-clipboard"
|
|
154
|
-
button.appendChild icon
|
|
155
|
-
|
|
156
|
-
header.appendChild button
|
|
157
|
-
|
|
158
|
-
highlightBlock.parentNode.insertBefore container, highlightBlock
|
|
159
|
-
container.appendChild header
|
|
160
|
-
container.appendChild highlightBlock
|
|
161
|
-
|
|
162
|
-
# event copy
|
|
163
|
-
button.addEventListener "click", ->
|
|
164
|
-
codeElement = highlightBlock.querySelector "td.code"
|
|
165
|
-
textToCopy = if codeElement then codeElement.innerText.trim() else highlightBlock.innerText.trim()
|
|
166
|
-
|
|
167
|
-
navigator.clipboard.writeText(textToCopy).then ->
|
|
168
|
-
icon.className = "fa-solid fa-check"
|
|
169
|
-
setTimeout (-> icon.className = "fa-solid fa-clipboard"), 2000
|
|
170
|
-
, ->
|
|
171
|
-
icon.className = "fa-solid fa-xmark"
|
|
172
|
-
setTimeout (-> icon.className = "fa-solid fa-clipboard"), 2000
|
data/assets/js/discus.coffee
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
{%- include layout/data.liquid -%}
|
|
5
|
-
|
|
6
|
-
document.addEventListener "DOMContentLoaded", ->
|
|
7
|
-
# discus
|
|
8
|
-
# ------------------------------------------------------------------------------------------------
|
|
9
|
-
discus = document.getElementById 'disqus_thread'
|
|
10
|
-
|
|
11
|
-
if discus
|
|
12
|
-
###*
|
|
13
|
-
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES
|
|
14
|
-
###
|
|
15
|
-
disqus_shortname = '{{ blog_.post.comments.disqus.shortname }}'
|
|
16
|
-
|
|
17
|
-
disqus_config = ->
|
|
18
|
-
@page.url = '{{ page.url | absolute_url }}' # substitua pelo seu permalink completo
|
|
19
|
-
@page.identifier = '{{ page.id }}' # ID unico para a discussão
|
|
20
|
-
@page.disable_ads = true # desativa anuncios
|
|
21
|
-
@page.recommendations = false # sesativa recomendações
|
|
22
|
-
|
|
23
|
-
do ->
|
|
24
|
-
d = document
|
|
25
|
-
s = d.createElement 'script'
|
|
26
|
-
|
|
27
|
-
s.src = '//' + disqus_shortname + '.disqus.com/embed.js'
|
|
28
|
-
s.setAttribute 'data-timestamp', +new Date()
|
|
29
|
-
|
|
30
|
-
(d.head or d.body).appendChild s
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
{%- include layout/data.liquid -%}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if(!(window.doNotTrack === "1" || navigator.doNotTrack === "1" || navigator.doNotTrack === "yes" || navigator.msDoNotTrack === "1")) {
|
|
8
|
-
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
9
|
-
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
10
|
-
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
11
|
-
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
12
|
-
|
|
13
|
-
ga('create', '{{ head_.google.analytics.id }}', 'auto');
|
|
14
|
-
ga('send', 'pageview');
|
|
15
|
-
}
|