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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b4a5c7ff703bd0049e8713cc0d08a73698657b85a0cccbf687545cb63d5476e
|
|
4
|
+
data.tar.gz: 1787cc1fcda221d1aad7fa838abaecb625428c6ea03f81a7b2e08b7d4976eaf1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eb0bea3dd530c918108078babc853563f0a404801807f56dbcff81694b26812f6e9edb09b49b11e6a00db175ffd84b92efe363260b1d6a5a81ff142c4f2c3ffe
|
|
7
|
+
data.tar.gz: '0251043911fc99d55b9b45d0cf991fb350f5ba6f3902bdbfce97f1919c221f86041ac4a46f03284888e74207d73036661da45768ecc924eec0407a052b8d4687'
|
data/{LICENSE.txt → LICENSE}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Creative Commons Attribution 4.0 International (CC BY 4.0)
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 {rawfeed} <https://rawfeed.github.io>
|
|
4
4
|
|
|
5
5
|
This theme is licensed under the Creative Commons Attribution 4.0 International License.
|
|
6
6
|
|
data/README.md
CHANGED
|
@@ -51,3 +51,15 @@ See [here](https://rawfeed.github.io/rawfeed-jekyll/changelog/)
|
|
|
51
51
|
# License
|
|
52
52
|
|
|
53
53
|
The theme is available as open source under the terms of [this License](https://rawfeed.github.io/rawfeed-jekyll/license/).
|
|
54
|
+
|
|
55
|
+
# Donation
|
|
56
|
+
|
|
57
|
+
Click on the image below to be redirected to the donation forms:
|
|
58
|
+
|
|
59
|
+
<div class="donation">
|
|
60
|
+
<a href="https://williamcanin.github.io/donate/" target="_blank">
|
|
61
|
+
<img width="160" height="100" src="assets/images/icons/donation.svg" alt="Donate"/>
|
|
62
|
+
</a>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
> It is very important that you make a donation to motivate further development of rawfeed-jekyll. :)
|
data/_data/options.yml
CHANGED
|
@@ -102,6 +102,7 @@ default:
|
|
|
102
102
|
width: 860 # default: 860
|
|
103
103
|
background_focus: true
|
|
104
104
|
rounding: false
|
|
105
|
+
user_select: none # none | text
|
|
105
106
|
font:
|
|
106
107
|
# Fonts Style Options: [default: monospace]
|
|
107
108
|
# "'Ubuntu', sans-serif"
|
|
@@ -221,8 +222,11 @@ pixels:
|
|
|
221
222
|
title: "pixels"
|
|
222
223
|
layout:
|
|
223
224
|
width: 860 # default: 860
|
|
225
|
+
|
|
224
226
|
# section: [page]
|
|
225
227
|
page:
|
|
228
|
+
toc:
|
|
229
|
+
title: "Table of Contents"
|
|
226
230
|
updated_on: "Page updated on"
|
|
227
231
|
error:
|
|
228
232
|
image: https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExNXlxYzc5eXp1Nm01cmtldzM5bHhwdzJ2Njk2c2E4b2RkdTBkeGs5eCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/c20UV66B7zCWA/giphy.gif
|
|
@@ -280,3 +284,46 @@ footer:
|
|
|
280
284
|
page_url: "/licenses/"
|
|
281
285
|
message: |
|
|
282
286
|
Your impactful phrase!
|
|
287
|
+
|
|
288
|
+
# section: [donation]
|
|
289
|
+
# Tip: use svg images for better quality (https://www.iconpacks.net)
|
|
290
|
+
donation:
|
|
291
|
+
title: "Support the Project"
|
|
292
|
+
description: "If this project helps you, consider supporting it"
|
|
293
|
+
copy_button:
|
|
294
|
+
text: "Copy"
|
|
295
|
+
clicked: "Copied!"
|
|
296
|
+
services:
|
|
297
|
+
- name: pix
|
|
298
|
+
logo: "/assets/images/icons/pix.svg"
|
|
299
|
+
description: |
|
|
300
|
+
Make your donation using PIX from Brazil. Use the key below.
|
|
301
|
+
address: "00b53f61-b009-4f05-8c43-444cce86af1d"
|
|
302
|
+
qrcode: "/assets/images/qrcode_inter.jpg"
|
|
303
|
+
|
|
304
|
+
- name: card
|
|
305
|
+
logo: "/assets/images/icons/card.svg"
|
|
306
|
+
description: |
|
|
307
|
+
Donation using card through the service `Buy Me a Coffee`.
|
|
308
|
+
address: "https://buymeacoffee.com/williamcanin"
|
|
309
|
+
|
|
310
|
+
- name: paypal
|
|
311
|
+
logo: "/assets/images/icons/paypal.svg"
|
|
312
|
+
description: |
|
|
313
|
+
Donate quickly and securely using your PayPal balance or linked card.
|
|
314
|
+
address: "https://www.paypal.com/donate/?cmd=_s-xclick&hosted_button_id=YBK2HEEYG8V5W&source=&ssrt=1775261628264"
|
|
315
|
+
|
|
316
|
+
- name: bitcoin (lightning network)
|
|
317
|
+
logo: "/assets/images/icons/lightning_network.svg"
|
|
318
|
+
description: |
|
|
319
|
+
Make an anonymous Bitcoin donation using a Lightning Address.
|
|
320
|
+
address: "williamcanin@walletofsatoshi.com"
|
|
321
|
+
qrcode: "/assets/images/qrcode_wos.jpg"
|
|
322
|
+
|
|
323
|
+
- name: bitcoin (on-chain)
|
|
324
|
+
logo: "/assets/images/icons/bitcoin.svg"
|
|
325
|
+
description: |
|
|
326
|
+
Make an anonymous Bitcoin donation using a On-Chain address (Binance).
|
|
327
|
+
address: "bc1qluh2mrchmtrwedspwhtta8ccgzsl9jqdr47f2p"
|
|
328
|
+
qrcode: "/assets/images/qrcode_btc_binance.jpg"
|
|
329
|
+
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
{%- assign search_url = "/blog/?search=open" | relative_url -%}
|
|
7
7
|
{%- assign tags_url = "/blog/tags/" | relative_url -%}
|
|
8
8
|
{%- assign pub_url = "/pub/" -%}
|
|
9
|
+
{%- assign donate_url = "/donate/" -%}
|
|
9
10
|
{%- assign feed_url = "/feed.xml" | relative_url -%}
|
|
10
11
|
{%- assign head_ = site.data.options.head -%}
|
|
11
12
|
{%- assign site_title = site.data.options.title -%}
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
{%- assign home_ = site.data.options.home -%}
|
|
17
18
|
{%- assign default_ = site.data.options.default -%}
|
|
18
19
|
{%- assign page_ = site.data.options.page -%}
|
|
20
|
+
{%- assign donation_ = site.data.options.donation -%}
|
|
19
21
|
{%- assign contact_ = site.data.options.contact -%}
|
|
20
22
|
{%- assign footer_ = site.data.options.footer -%}
|
|
21
23
|
{%- assign socials_ = site.data.options.socials -%}
|
data/_layouts/contact.html
CHANGED
|
@@ -81,82 +81,162 @@ layout: default
|
|
|
81
81
|
<p>To use the email submission form, you need to:</p>
|
|
82
82
|
<p>1 - Copy the script below and implement it in <a href="https://script.google.com" target="_blank">Google Apps Script</a>:</p>
|
|
83
83
|
<blockquote>
|
|
84
|
-
<p>Note1: Don't forget to
|
|
85
|
-
<p>Note2: Without editing the script in Google Apps Script, you need to
|
|
84
|
+
<p>Note1: Don't forget to change the constants: TO_ADDRESS, SITE, LOGO_URL, MINIMUM_MESSAGE.</p>
|
|
85
|
+
<p>Note2: Without editing the script in Google Apps Script, you will need to redeploy it.</p>
|
|
86
86
|
</blockquote>
|
|
87
87
|
|
|
88
88
|
{% highlight javascript linenos %}
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
/**
|
|
90
|
+
* GOOGLE APPS SCRIPT - HYBRID VERSION (RECAPTCHA & TURNSTYLE)
|
|
91
|
+
* by William C. Canin
|
|
92
|
+
*/
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
+
const TO_ADDRESS = "example@mail.com";
|
|
95
|
+
const SITE = "https://example.com";
|
|
96
|
+
const LOGO_URL = "https://example.com/assets/images/logo.png";
|
|
97
|
+
const MINIMUM_MESSAGE = 50;
|
|
94
98
|
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
// Accessing script properties
|
|
100
|
+
const props = PropertiesService.getScriptProperties();
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* HTML sanitization and Header Injection prevention
|
|
104
|
+
*/
|
|
105
|
+
function sanitize(str, isHeader = false) {
|
|
106
|
+
if (!str) return "";
|
|
107
|
+
let clean = str.trim();
|
|
108
|
+
if (isHeader) clean = clean.replace(/[\r\n]/g, "");
|
|
109
|
+
return clean.replace(/[&<>"']/g, function(m) {
|
|
110
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m];
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Cloudflare Turnstile Validation
|
|
116
|
+
*/
|
|
117
|
+
function validateTurnstile(token) {
|
|
118
|
+
if (!token) throw new Error("[Script]: Turnstile token missing.");
|
|
119
|
+
const secret = props.getProperty("TURNSTILE_SECRET_KEY");
|
|
105
120
|
|
|
106
|
-
const response = UrlFetchApp.fetch(
|
|
121
|
+
const response = UrlFetchApp.fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
|
107
122
|
method: "post",
|
|
108
|
-
payload:
|
|
123
|
+
payload: { secret: secret, response: token }
|
|
109
124
|
});
|
|
110
125
|
|
|
111
126
|
const result = JSON.parse(response.getContentText());
|
|
127
|
+
if (!result.success) throw new Error("[Script]: Turnstile validation failed.");
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
112
130
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Google reCAPTCHA Validation
|
|
133
|
+
*/
|
|
134
|
+
function validateRecaptcha(token) {
|
|
135
|
+
if (!token) throw new Error("[Script]: reCAPTCHA token missing.");
|
|
136
|
+
const secret = props.getProperty("RECAPTCHA_SECRET_KEY");
|
|
137
|
+
|
|
138
|
+
const response = UrlFetchApp.fetch("https://www.google.com/recaptcha/api/siteverify", {
|
|
139
|
+
method: "post",
|
|
140
|
+
payload: { secret: secret, response: token }
|
|
141
|
+
});
|
|
116
142
|
|
|
143
|
+
const result = JSON.parse(response.getContentText());
|
|
144
|
+
if (!result.success) throw new Error("[Script]: reCAPTCHA failed.");
|
|
117
145
|
return true;
|
|
118
146
|
}
|
|
119
147
|
|
|
120
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Main Function
|
|
150
|
+
*/
|
|
121
151
|
function doPost(e) {
|
|
122
152
|
try {
|
|
123
|
-
const
|
|
153
|
+
const contents = e.postData ? e.postData.contents : null;
|
|
154
|
+
if (!contents) throw new Error("No data received");
|
|
155
|
+
|
|
156
|
+
const data = JSON.parse(contents);
|
|
124
157
|
|
|
125
|
-
//
|
|
126
|
-
|
|
158
|
+
// Identifies the token coming from the front-end (accepts both names)
|
|
159
|
+
const token = data['g-recaptcha-response'] || data['turnstileToken'] || data['cf-turnstile-response'];
|
|
127
160
|
|
|
128
|
-
|
|
129
|
-
const { name, email, message } = data;
|
|
161
|
+
let antiRobot = "Unknown";
|
|
130
162
|
|
|
131
|
-
|
|
132
|
-
|
|
163
|
+
// Hybrid Logic: Validates according to the key present in the Script.
|
|
164
|
+
if (props.getProperty('RECAPTCHA_SECRET_KEY')) {
|
|
165
|
+
antiRobot = "Google reCAPTCHA";
|
|
166
|
+
validateRecaptcha(token);
|
|
167
|
+
} else if (props.getProperty('TURNSTILE_SECRET_KEY')) {
|
|
168
|
+
validateTurnstile(token);
|
|
169
|
+
antiRobot = "Cloudflare Turnstile";
|
|
170
|
+
} else {
|
|
171
|
+
throw new Error("No Captcha Secret Key configured in Script Properties.");
|
|
133
172
|
}
|
|
134
173
|
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
174
|
+
const name = sanitize(data.name, true);
|
|
175
|
+
const email = sanitize(data.email, true);
|
|
176
|
+
const message = data.message || "";
|
|
177
|
+
const pageUrl = data.page_url ? sanitize(data.page_url, true) : SITE;
|
|
178
|
+
const locationInfo = data.location_info || "Unknown";
|
|
179
|
+
|
|
180
|
+
if (!name || !email || !message) throw new Error("[Script]: Missing form data.");
|
|
181
|
+
if (message.length < MINIMUM_MESSAGE) throw new Error("[Script]: Message too short.");
|
|
182
|
+
|
|
183
|
+
// Anti-Spam Rate Limit
|
|
184
|
+
const lastSent = props.getProperty(`last_sent_${email}`);
|
|
185
|
+
const now = Date.now();
|
|
186
|
+
if (lastSent && (now - lastSent < 60000)) throw new Error("[Script]: Please wait 1 minute.");
|
|
187
|
+
props.setProperty(`last_sent_${email}`, now.toString());
|
|
188
|
+
|
|
189
|
+
// --- MESSAGE PROCESSING ---
|
|
190
|
+
let escapedContent = sanitize(message);
|
|
191
|
+
let codeBlocks = [];
|
|
192
|
+
let placeholder = "___CODE_BLOCK_";
|
|
193
|
+
|
|
194
|
+
let cleanMessage = escapedContent.replace(/```([\s\S]+?)```/g, function(match, code) {
|
|
195
|
+
const id = codeBlocks.length;
|
|
196
|
+
|
|
197
|
+
const codeHtml = `<pre style="background: #f6f8fa; color: #24292e; padding: 15px; border-radius: 6px; overflow-x: auto; font-family: 'Fira Code','Consolas',SFMono-Regular, SF Mono, Menlo, monospace; font-size: 15px; line-height: 1.85; border: 1px solid #d1d5da; border-bottom: 3px solid #a1a2a7; border-right: 1px solid #a1a2a7; border-top: 1px solid #a1a2a7; border-left: 1px solid #a1a2a7;">${code.trim()}</pre>`;
|
|
198
|
+
|
|
199
|
+
codeBlocks.push(codeHtml);
|
|
200
|
+
return placeholder + id + "___";
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
cleanMessage = cleanMessage.replace(/\n/g, '<br>');
|
|
204
|
+
codeBlocks.forEach((block, index) => {
|
|
205
|
+
cleanMessage = cleanMessage.replace(placeholder + index + "___", block);
|
|
149
206
|
});
|
|
150
207
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
208
|
+
const subject = `Message from: ${name} (${SITE})`;
|
|
209
|
+
const htmlBody = `
|
|
210
|
+
<div style="font-family: sans-serif; color: #333; max-width: 820px; border: 1px solid #eee; padding: 20px;">
|
|
211
|
+
${LOGO_URL ? `
|
|
212
|
+
<div style="text-align: center; margin-bottom: 20px;">
|
|
213
|
+
<img src="${LOGO_URL}" alt="Logo" style="width: 150px; padding: 10px; border-radius: 50%; border: 1px solid #ddd;">
|
|
214
|
+
</div>
|
|
215
|
+
` : ''}
|
|
216
|
+
|
|
217
|
+
<h2 style="color: #333; border-bottom: 2px solid #333; padding-bottom: 10px;"></h2>
|
|
218
|
+
|
|
219
|
+
<div style="margin-top: 20px;">
|
|
220
|
+
<p><b>Name:</b> ${name}</p>
|
|
221
|
+
<p><b>From:</b> <a href="mailto:${email}">${email}</a></p>
|
|
222
|
+
<p><b>Message:</b></p>
|
|
223
|
+
<div style="background: #fff; font-size: 15px; color: black; border: 1px solid transparent; padding: 15px; border-radius: 5px;">
|
|
224
|
+
${cleanMessage}
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<footer style="margin-top: 30px; font-size: 12px; color: #888; border-top: 1px solid #eee; padding-top: 10px;">
|
|
229
|
+
This is an automated email sent by your form ${pageUrl} using ${antiRobot}/Google Script.<br>
|
|
230
|
+
© ${new Date().getFullYear()} ${SITE.replace('https://', '')} - ${new Date().toLocaleString('pt-BR')} - <b>${locationInfo}</b>
|
|
231
|
+
</footer>
|
|
232
|
+
</div>`;
|
|
233
|
+
|
|
234
|
+
MailApp.sendEmail({ to: TO_ADDRESS, subject: subject, htmlBody: htmlBody, replyTo: email });
|
|
235
|
+
|
|
236
|
+
return ContentService.createTextOutput(JSON.stringify({ 'result': 'success' })).setMimeType(ContentService.MimeType.JSON);
|
|
154
237
|
|
|
155
238
|
} catch (err) {
|
|
156
|
-
|
|
157
|
-
return ContentService
|
|
158
|
-
.createTextOutput(JSON.stringify({ 'result': 'error', 'message': err.toString() }))
|
|
159
|
-
.setMimeType(ContentService.MimeType.JSON);
|
|
239
|
+
return ContentService.createTextOutput(JSON.stringify({ 'result': 'error', 'debug': err.message })).setMimeType(ContentService.MimeType.JSON);
|
|
160
240
|
}
|
|
161
241
|
}
|
|
162
242
|
{% endhighlight %}
|
data/_layouts/default.html
CHANGED
|
@@ -22,7 +22,13 @@
|
|
|
22
22
|
<!-- head -->
|
|
23
23
|
|
|
24
24
|
<!-- body -->
|
|
25
|
-
<body data-layout="{{ page.layout | default: '' }}"
|
|
25
|
+
<body data-layout="{{ page.layout | default: '' }}"
|
|
26
|
+
data-terminal-enabled="{{ home_.terminal.enable | default: false }}"
|
|
27
|
+
style="
|
|
28
|
+
font-family: {{ default_.font.style }} !important;
|
|
29
|
+
font-size: {{ default_.font.size }} !important;
|
|
30
|
+
letter-spacing: {{ default_.font.spacing }} !important;
|
|
31
|
+
user-select: {{ default_.user_select | default: 'none' }};">
|
|
26
32
|
|
|
27
33
|
<!-- container -->
|
|
28
34
|
<div class="container-fluid">
|
|
@@ -38,14 +44,15 @@
|
|
|
38
44
|
|
|
39
45
|
<!-- scripts -->
|
|
40
46
|
<script src="{{ '/assets/vendor/bootstrap/js/bootstrap.bundle.min.js' | relative_url }}"></script>
|
|
41
|
-
<script src="{{ '/assets/js/
|
|
47
|
+
<script src="{{ '/assets/js/default.js' | relative_url }}"></script>
|
|
42
48
|
{%- if page.url contains '/blog/' -%}
|
|
43
49
|
<script src="{{ '/assets/vendor/simple-jekyll-search.min.js' | relative_url }}"></script>
|
|
44
50
|
{%- endif -%}
|
|
45
|
-
<script src="{{ '/assets/js/
|
|
46
|
-
<script src="{{ '/assets/js/
|
|
47
|
-
<script src="{{ '/assets/js/
|
|
48
|
-
<script src="{{ '/assets/js/
|
|
51
|
+
<script src="{{ '/assets/js/blog.js' | relative_url }}"></script>
|
|
52
|
+
<script src="{{ '/assets/js/home.js' | relative_url }}"></script>
|
|
53
|
+
<script src="{{ '/assets/js/page.js' | relative_url }}"></script>
|
|
54
|
+
<script src="{{ '/assets/js/contact.js' | relative_url }}"></script>
|
|
55
|
+
<script src="{{ '/assets/js/donation.js' | relative_url }}"></script>
|
|
49
56
|
<!-- scripts -->
|
|
50
57
|
</body>
|
|
51
58
|
<!-- body -->
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
{%- include layout/data.liquid -%}
|
|
6
|
+
|
|
7
|
+
<div id="donation" class="donation py-5{% if default_.background_focus %} background_focus{% endif %}{% if default_.rounding %} rounding{% endif %}">
|
|
8
|
+
|
|
9
|
+
<div class="container">
|
|
10
|
+
|
|
11
|
+
{% if donation_.title or donation_.description %}
|
|
12
|
+
<div class="row justify-content-center mb-5">
|
|
13
|
+
<div class="col-lg-8 text-center">
|
|
14
|
+
<h1 class="display-5 fw-bold mb-3 donation__title">{{ donation_.title }}</h1>
|
|
15
|
+
<p class="mb-0 donation__description">
|
|
16
|
+
{{ donation_.description }}
|
|
17
|
+
</p>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
{% endif %}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<div class="row mt-5">
|
|
24
|
+
<div class="col donation__content">
|
|
25
|
+
{{ content }}
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="donation-list d-flex flex-column gap-4">
|
|
30
|
+
|
|
31
|
+
{%- for service in donation_.services -%}
|
|
32
|
+
<div class="donation__box">
|
|
33
|
+
<div class="row align-items-center g-4">
|
|
34
|
+
|
|
35
|
+
<!-- LOGO -->
|
|
36
|
+
<div class="col-md-2 col-12 text-center">
|
|
37
|
+
<img src="{{ service.logo | relative_url }}"
|
|
38
|
+
class="img-fluid donation__logo"
|
|
39
|
+
alt="{{ service.name }}">
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- INFO -->
|
|
43
|
+
<div class="col-md-7 col-12">
|
|
44
|
+
|
|
45
|
+
<h1 class="mb-2 text-capitalize donation__service__name">{{ service.name }}</h1>
|
|
46
|
+
<p class="mb-4 donation__service__description">
|
|
47
|
+
{{ service.description | markdownify }}
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
{%- unless service.name contains "bitcoin" or service.name == "pix" -%}
|
|
51
|
+
<div class="row">
|
|
52
|
+
<div class="col">
|
|
53
|
+
<a class="fw-bold donation__btn" href="{{ service.address }}"
|
|
54
|
+
target="_blank"
|
|
55
|
+
rel="noopener">
|
|
56
|
+
Open
|
|
57
|
+
</a>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
{%- endunless -%}
|
|
61
|
+
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<!-- QR CODE -->
|
|
65
|
+
<div class="col-md-3 col-12 text-center">
|
|
66
|
+
{%- if service.qrcode -%}
|
|
67
|
+
<img src="{{ service.qrcode | relative_url }}"
|
|
68
|
+
class="img-fluid clickable-qr donation__qr"
|
|
69
|
+
alt="QR {{ service.name }}"
|
|
70
|
+
data-bs-toggle="modal"
|
|
71
|
+
data-bs-target="#qrModal"
|
|
72
|
+
data-qr="{{ service.qrcode | relative_url }}">
|
|
73
|
+
{%- endif -%}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div class="row">
|
|
79
|
+
<div class="col-12 mt-4 donation__offset_input">
|
|
80
|
+
{% if service.name == "pix" or service.name contains "bitcoin" %}
|
|
81
|
+
<div class="row">
|
|
82
|
+
<div class="input-group">
|
|
83
|
+
{% if service.name contains "pix" %}
|
|
84
|
+
<span class="input-group-text donation__input__label">Key</span>
|
|
85
|
+
{% else %}
|
|
86
|
+
<span class="input-group-text donation__input__label">Address</span>
|
|
87
|
+
{% endif %}
|
|
88
|
+
<input type="text" class="form-control donation__address"
|
|
89
|
+
value="{{ service.address }}" readonly>
|
|
90
|
+
<button class="fw-bold donation__btn donation__btn--copy" data-copy="{{ service.address }}">
|
|
91
|
+
{{ donation_.copy_button.text }}
|
|
92
|
+
</button>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
{% endif %}
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
{%- endfor -%}
|
|
100
|
+
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<!-- QR Modal -->
|
|
107
|
+
<div class="modal fade" id="qrModal" tabindex="-1">
|
|
108
|
+
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
109
|
+
<div class="modal-content bg-transparent border-0 text-center">
|
|
110
|
+
<img id="qrModalImg" class="img-fluid rounded shadow">
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
data/_sass/base/_index.scss
CHANGED
|
@@ -6,9 +6,6 @@ body {
|
|
|
6
6
|
background-color: var(--bg-color);
|
|
7
7
|
color: var(--text-color);
|
|
8
8
|
|
|
9
|
-
// impede selecionar texto no site
|
|
10
|
-
user-select: none;
|
|
11
|
-
|
|
12
9
|
code,
|
|
13
10
|
pre,
|
|
14
11
|
.highlight,
|
|
@@ -92,8 +89,8 @@ body[data-layout="mobile"] .home-simple {
|
|
|
92
89
|
}
|
|
93
90
|
|
|
94
91
|
a[target="_blank"]::after {
|
|
95
|
-
content: "
|
|
96
|
-
font-size: .9em;
|
|
97
|
-
margin-left: 0.25em;
|
|
98
|
-
vertical-align: middle;
|
|
92
|
+
content: "↗";
|
|
93
|
+
// font-size: .9em;
|
|
94
|
+
// margin-left: 0.25em;
|
|
95
|
+
// vertical-align: middle;
|
|
99
96
|
}
|
|
@@ -306,14 +306,13 @@
|
|
|
306
306
|
position: fixed;
|
|
307
307
|
top: 0;
|
|
308
308
|
left: 0;
|
|
309
|
-
overflow:
|
|
309
|
+
overflow-y: auto;
|
|
310
310
|
display: flex;
|
|
311
311
|
flex-direction: column;
|
|
312
312
|
z-index: 9999;
|
|
313
313
|
min-width: 480px !important;
|
|
314
314
|
max-width: 480px !important;
|
|
315
315
|
width: auto !important;
|
|
316
|
-
margin: 0 auto;
|
|
317
316
|
max-height: 100vh;
|
|
318
317
|
}
|
|
319
318
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@use "../components/index";
|
|
2
|
+
|
|
3
|
+
.donation {
|
|
4
|
+
@extend %markdown;
|
|
5
|
+
margin-bottom: var(--margin-bottom);
|
|
6
|
+
|
|
7
|
+
&__offset_input {
|
|
8
|
+
@media (min-width: 768px) {
|
|
9
|
+
padding-left: 18% !important;
|
|
10
|
+
padding-right: 6.5% !important;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&__btn {
|
|
15
|
+
@extend %button;
|
|
16
|
+
|
|
17
|
+
&--copy {
|
|
18
|
+
min-width: 100px !important;
|
|
19
|
+
text-align: center !important;
|
|
20
|
+
border: 1px solid var(--background-focus-border-color) !important;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&__box {
|
|
25
|
+
padding: 1rem;
|
|
26
|
+
border: 2px dotted var(--card-border-color);
|
|
27
|
+
background-color: var(--card-bg-color);
|
|
28
|
+
transition: all 0.2s ease;
|
|
29
|
+
|
|
30
|
+
&:hover {
|
|
31
|
+
// transform: translateY(-3px);
|
|
32
|
+
border: 2px dotted var(--background-focus-border-color) !important;
|
|
33
|
+
box-shadow: 0 1rem 1.2rem var(--card-box-shadow-color-hover);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&__logo {
|
|
38
|
+
max-height: 64px;
|
|
39
|
+
opacity: 0.65;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&__input__label {
|
|
43
|
+
font-family: monospace;
|
|
44
|
+
font-size: 0.9rem;
|
|
45
|
+
color: var(--text-secondary);
|
|
46
|
+
background-color: var(--background-focus-color);
|
|
47
|
+
padding: 0.25rem 0.5rem;
|
|
48
|
+
border-radius: 0.25rem;
|
|
49
|
+
border: 1px solid var(--background-focus-border-color);
|
|
50
|
+
width: fit-content;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&__qr {
|
|
54
|
+
max-height: 90px;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
transition: transform .2s ease;
|
|
57
|
+
|
|
58
|
+
&:hover {
|
|
59
|
+
transform: scale(1.08);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&__service__description {
|
|
64
|
+
font-size: 0.95rem;
|
|
65
|
+
color: var(--text-secondary);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&__service__name {
|
|
69
|
+
margin-top: 0 !important;
|
|
70
|
+
text-transform: capitalize;
|
|
71
|
+
font-size: 1.3rem !important;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&__address {
|
|
75
|
+
font-family: monospace;
|
|
76
|
+
font-size: 0.9rem;
|
|
77
|
+
color: var(--text-secondary);
|
|
78
|
+
background-color: var(--background-focus-color);
|
|
79
|
+
padding: 0.25rem 0.5rem;
|
|
80
|
+
border-radius: 0.25rem;
|
|
81
|
+
border: 1px solid var(--background-focus-border-color);
|
|
82
|
+
width: fit-content;
|
|
83
|
+
|
|
84
|
+
&:focus {
|
|
85
|
+
color: inherit !important;
|
|
86
|
+
outline: none !important;
|
|
87
|
+
box-shadow: none !important;
|
|
88
|
+
background-color: var(--background-focus-color) !important;
|
|
89
|
+
border: 1px solid var(--background-focus-border-color) !important;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
}
|
data/_sass/layouts/_index.scss
CHANGED