insights4you-jekyll-theme 0.2.0 → 0.2.2
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/README.md +1 -2
- data/_data/i4y-errors.json +32 -0
- data/_data/i4y-icons.json +1 -0
- data/_data/i4y-illustrations.json +20 -0
- data/_data/i4y-social-media.yml +26 -0
- data/_data/notifications.yml +10 -0
- data/_includes/card/profile.html +42 -0
- data/_includes/footer.html +48 -45
- data/_includes/head.html +5 -9
- data/_includes/header-logo.html +35 -123
- data/_includes/header-navbar.html +39 -49
- data/_includes/header-svg.html +275 -39
- data/_layouts/default.html +8 -6
- data/_layouts/home.html +1 -1
- data/_layouts/post.html +19 -0
- data/assets/css/theme.min.css +98 -68
- data/assets/images/i4y-logo.jpg +0 -0
- data/assets/images/preview-dark.png +0 -0
- data/assets/js/theme.js +186 -23
- metadata +13 -4
data/assets/js/theme.js
CHANGED
@@ -1,31 +1,194 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
// Ensure jsyaml is available
|
2
|
+
/* eslint-disable no-undef */ // Disable undefined variable check for 'jsyaml'
|
3
|
+
if (typeof jsyaml === "undefined") {
|
4
|
+
throw new Error("js-yaml library is not loaded. Please include it in your project.");
|
5
|
+
}
|
6
|
+
/* eslint-enable no-undef */
|
6
7
|
|
7
8
|
const THEME_STORAGE_KEY = "tablerTheme";
|
8
|
-
const
|
9
|
-
let selectedTheme;
|
9
|
+
const DEFAULT_THEME = "light";
|
10
10
|
|
11
|
-
//
|
12
|
-
// Create a Proxy for URLSearchParams to simplify access to query parameters.
|
13
|
-
// This allows us to use `params.key` instead of `params.get('key')`.
|
11
|
+
// Proxy to access URL parameters securely
|
14
12
|
const params = new Proxy(new URLSearchParams(window.location.search), {
|
15
|
-
|
13
|
+
get: (searchParams, prop) => searchParams.get(prop),
|
16
14
|
});
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
22
|
-
|
23
|
-
|
16
|
+
// Validate theme values
|
17
|
+
function isValidTheme(theme) {
|
18
|
+
return ["light", "dark"].includes(theme);
|
19
|
+
}
|
20
|
+
|
21
|
+
// Apply the selected theme to the document
|
22
|
+
function applyTheme(theme) {
|
23
|
+
document.body.setAttribute("data-bs-theme", theme);
|
24
|
+
|
25
|
+
// Accessibility: Notify screen readers of theme change
|
26
|
+
const themeAnnouncement = document.getElementById("theme-announcement");
|
27
|
+
if (themeAnnouncement) {
|
28
|
+
themeAnnouncement.textContent = `Theme changed to ${theme}`;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
// Save the selected theme to localStorage
|
33
|
+
function saveTheme(theme) {
|
34
|
+
localStorage.setItem(THEME_STORAGE_KEY, theme);
|
35
|
+
}
|
36
|
+
|
37
|
+
// Load the current theme based on priority: URL > localStorage > system preference > default
|
38
|
+
function loadTheme() {
|
39
|
+
let selectedTheme;
|
40
|
+
|
41
|
+
// Prioritize theme from URL (sanitize input to prevent XSS)
|
42
|
+
if (params.theme && isValidTheme(params.theme)) {
|
43
|
+
selectedTheme = params.theme;
|
44
|
+
saveTheme(selectedTheme);
|
45
|
+
} else {
|
46
|
+
// Use localStorage or system preference
|
47
|
+
const storedTheme = localStorage.getItem(THEME_STORAGE_KEY);
|
48
|
+
selectedTheme = isValidTheme(storedTheme)
|
49
|
+
? storedTheme
|
50
|
+
: window.matchMedia("(prefers-color-scheme: dark)").matches
|
51
|
+
? "dark"
|
52
|
+
: DEFAULT_THEME;
|
53
|
+
}
|
54
|
+
|
55
|
+
// Apply the selected theme
|
56
|
+
applyTheme(selectedTheme);
|
57
|
+
}
|
58
|
+
|
59
|
+
// Toggle between light and dark themes
|
60
|
+
/* eslint-disable no-unused-vars */ // Disable unused function check for 'toggleTheme'
|
61
|
+
function toggleTheme(theme) {
|
62
|
+
saveTheme(theme);
|
63
|
+
applyTheme(theme);
|
64
|
+
}
|
65
|
+
/* eslint-enable no-unused-vars */
|
66
|
+
|
67
|
+
// Load dynamic notifications
|
68
|
+
async function loadNotifications() {
|
69
|
+
const notificationsList = document.getElementById("notifications-list");
|
70
|
+
const badge = document.getElementById("notification-badge");
|
71
|
+
|
72
|
+
if (!notificationsList || !badge) return;
|
73
|
+
|
74
|
+
try {
|
75
|
+
// Fetch local and remote notifications
|
76
|
+
const [localNotifications, remoteNotifications] = await Promise.all([
|
77
|
+
getLocalNotifications(),
|
78
|
+
fetchRemoteNotifications(),
|
79
|
+
]);
|
80
|
+
|
81
|
+
// Combine, sort, and render notifications
|
82
|
+
const allNotifications = combineAndSortNotifications(localNotifications, remoteNotifications);
|
83
|
+
renderNotifications(allNotifications, notificationsList, badge);
|
84
|
+
} catch (error) {
|
85
|
+
console.error("Error loading notifications:", error);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
// Fetch local notifications from site data
|
90
|
+
function getLocalNotifications() {
|
91
|
+
try {
|
92
|
+
return Array.isArray(window.siteData?.notifications) ? window.siteData.notifications : [];
|
93
|
+
} catch (error) {
|
94
|
+
console.error("Error loading local notifications:", error);
|
95
|
+
return [];
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
// Fetch remote notifications from GitHub repository
|
100
|
+
async function fetchRemoteNotifications() {
|
101
|
+
try {
|
102
|
+
const response = await fetch(
|
103
|
+
"https://raw.githubusercontent.com/marciopaiva/insights4you-jekyll-theme/main/_data/notifications.yml"
|
104
|
+
);
|
105
|
+
if (!response.ok) throw new Error("Failed to fetch remote notifications");
|
106
|
+
const yamlText = await response.text();
|
107
|
+
/* eslint-disable no-undef */ // Disable undefined variable check for 'jsyaml'
|
108
|
+
const parsedData = jsyaml.load(yamlText); // Parse YAML data
|
109
|
+
/* eslint-enable no-undef */
|
110
|
+
return Array.isArray(parsedData) ? parsedData : [];
|
111
|
+
} catch (error) {
|
112
|
+
console.error("Error fetching remote notifications:", error);
|
113
|
+
return [];
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
// Combine and sort notifications by date
|
118
|
+
function combineAndSortNotifications(local, remote) {
|
119
|
+
return [...remote, ...local]
|
120
|
+
.filter((notification) => notification.date) // Ensure each notification has a valid date
|
121
|
+
.sort((a, b) => new Date(b.date) - new Date(a.date))
|
122
|
+
.slice(0, 5); // Display only the latest 5 notifications
|
123
|
+
}
|
124
|
+
|
125
|
+
// Render notifications in the DOM securely
|
126
|
+
function renderNotifications(notifications, listElement, badgeElement) {
|
127
|
+
badgeElement.textContent = notifications.length;
|
128
|
+
|
129
|
+
// Clear existing notifications
|
130
|
+
listElement.innerHTML = "";
|
131
|
+
|
132
|
+
// Append notifications using DOM manipulation for security
|
133
|
+
notifications.forEach((notification) => {
|
134
|
+
const item = createNotificationItem(notification);
|
135
|
+
listElement.appendChild(item);
|
136
|
+
});
|
137
|
+
}
|
138
|
+
|
139
|
+
// Create a single notification item securely
|
140
|
+
function createNotificationItem(notification) {
|
141
|
+
const container = document.createElement("div");
|
142
|
+
container.className = "list-group-item";
|
143
|
+
|
144
|
+
const row = document.createElement("div");
|
145
|
+
row.className = "row align-items-center";
|
146
|
+
|
147
|
+
const colAuto = document.createElement("div");
|
148
|
+
colAuto.className = "col-auto";
|
149
|
+
const statusDot = document.createElement("span");
|
150
|
+
statusDot.className = `status-dot bg-${notification.color || "blue"} d-block`;
|
151
|
+
colAuto.appendChild(statusDot);
|
152
|
+
|
153
|
+
const colText = document.createElement("div");
|
154
|
+
colText.className = "col text-truncate";
|
155
|
+
const title = document.createElement("a");
|
156
|
+
title.href = notification.link;
|
157
|
+
title.className = "text-body d-block";
|
158
|
+
title.textContent = notification.title || "Untitled Notification";
|
159
|
+
const description = document.createElement("div");
|
160
|
+
description.className = "text-secondary";
|
161
|
+
description.textContent = notification.description || "No description available";
|
162
|
+
const date = document.createElement("small");
|
163
|
+
date.className = "text-muted";
|
164
|
+
date.textContent = new Date(notification.date).toLocaleDateString();
|
165
|
+
colText.append(title, description, date);
|
166
|
+
|
167
|
+
const colActions = document.createElement("div");
|
168
|
+
colActions.className = "col-auto";
|
169
|
+
const actionLink = document.createElement("a");
|
170
|
+
actionLink.href = notification.link;
|
171
|
+
actionLink.className = "list-group-item-actions";
|
172
|
+
actionLink.target = "_blank";
|
173
|
+
const svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
174
|
+
svgIcon.setAttribute("class", "icon text-muted icon-2");
|
175
|
+
svgIcon.setAttribute("viewBox", "0 0 24 24");
|
176
|
+
svgIcon.setAttribute("stroke", "currentColor");
|
177
|
+
svgIcon.setAttribute("fill", "none");
|
178
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
179
|
+
path.setAttribute("d", "M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873z");
|
180
|
+
svgIcon.appendChild(path);
|
181
|
+
actionLink.appendChild(svgIcon);
|
182
|
+
colActions.appendChild(actionLink);
|
183
|
+
|
184
|
+
row.append(colAuto, colText, colActions);
|
185
|
+
container.appendChild(row);
|
186
|
+
|
187
|
+
return container;
|
24
188
|
}
|
25
189
|
|
26
|
-
//
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
}
|
190
|
+
// Initialize theme and notifications when the page loads
|
191
|
+
document.addEventListener("DOMContentLoaded", () => {
|
192
|
+
loadTheme();
|
193
|
+
loadNotifications();
|
194
|
+
});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insights4you-jekyll-theme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcio Paiva Barbosa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.50'
|
111
|
-
description: "A sleek and modern Jekyll theme inspired by the
|
111
|
+
description: "A sleek and modern Jekyll theme inspired by the Tabler Admin Dashboard.
|
112
112
|
\nThis theme offers a clean, professional, and responsive interface, making it ideal
|
113
113
|
for developers, \ncontent creators, and businesses. Whether you're building documentation
|
114
114
|
sites, admin panels, or \nproject showcases, this theme provides a minimal-effort
|
@@ -121,6 +121,12 @@ extra_rdoc_files: []
|
|
121
121
|
files:
|
122
122
|
- LICENSE
|
123
123
|
- README.md
|
124
|
+
- _data/i4y-errors.json
|
125
|
+
- _data/i4y-icons.json
|
126
|
+
- _data/i4y-illustrations.json
|
127
|
+
- _data/i4y-social-media.yml
|
128
|
+
- _data/notifications.yml
|
129
|
+
- _includes/card/profile.html
|
124
130
|
- _includes/footer.html
|
125
131
|
- _includes/head.html
|
126
132
|
- _includes/header-logo.html
|
@@ -133,6 +139,7 @@ files:
|
|
133
139
|
- _layouts/default.html
|
134
140
|
- _layouts/error.html
|
135
141
|
- _layouts/home.html
|
142
|
+
- _layouts/post.html
|
136
143
|
- assets/css/theme.min.css
|
137
144
|
- assets/images/android-chrome-192x192.png
|
138
145
|
- assets/images/android-chrome-512x512.png
|
@@ -140,6 +147,8 @@ files:
|
|
140
147
|
- assets/images/favicon-16x16.png
|
141
148
|
- assets/images/favicon-32x32.png
|
142
149
|
- assets/images/favicon.ico
|
150
|
+
- assets/images/i4y-logo.jpg
|
151
|
+
- assets/images/preview-dark.png
|
143
152
|
- assets/images/site.webmanifest
|
144
153
|
- assets/js/theme.js
|
145
154
|
homepage: https://github.com/marciopaiva/insights4you-jekyll-theme
|
@@ -170,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
179
|
- !ruby/object:Gem::Version
|
171
180
|
version: '0'
|
172
181
|
requirements: []
|
173
|
-
rubygems_version: 3.3.
|
182
|
+
rubygems_version: 3.3.7
|
174
183
|
signing_key:
|
175
184
|
specification_version: 4
|
176
185
|
summary: A sleek and modern Jekyll theme inspired by the Tabler Admin Dashboard.
|