insights4you-jekyll-theme 0.1.1 → 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 +38 -5
- 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 -48
- data/_includes/head.html +59 -0
- data/_includes/header-logo.html +91 -0
- data/_includes/header-navbar.html +59 -0
- data/_includes/header-svg.html +275 -0
- data/_includes/ui/button.html +30 -0
- data/_includes/ui/empty.html +23 -0
- data/_includes/ui/icon.html +33 -0
- data/_includes/ui/illustration.html +20 -0
- data/_layouts/default.html +19 -0
- data/_layouts/error.html +12 -0
- data/_layouts/home.html +19 -0
- data/_layouts/post.html +19 -0
- data/assets/css/theme.min.css +120 -2
- data/assets/images/android-chrome-192x192.png +0 -0
- data/assets/images/android-chrome-512x512.png +0 -0
- data/assets/images/apple-touch-icon.png +0 -0
- data/assets/images/favicon-16x16.png +0 -0
- data/assets/images/favicon-32x32.png +0 -0
- data/assets/images/favicon.ico +0 -0
- data/assets/images/i4y-logo.jpg +0 -0
- data/assets/images/preview-dark.png +0 -0
- data/assets/images/site.webmanifest +1 -0
- data/assets/js/theme.js +186 -23
- metadata +99 -20
- data/_includes/header.html +0 -405
- data/_includes/sidebar.html +0 -24
- data/_layouts/base.html +0 -54
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,35 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insights4you-jekyll-theme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
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
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.9'
|
20
|
-
- - "<"
|
17
|
+
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
19
|
+
version: 4.4.1
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
|
26
|
+
version: 4.4.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jekyll-feed
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
31
32
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
33
|
+
version: '0.15'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.15'
|
33
41
|
- !ruby/object:Gem::Dependency
|
34
42
|
name: jekyll-seo-tag
|
35
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,10 +66,53 @@ dependencies:
|
|
58
66
|
- - "~>"
|
59
67
|
- !ruby/object:Gem::Version
|
60
68
|
version: '2.4'
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '13.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '13.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.50'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.50'
|
111
|
+
description: "A sleek and modern Jekyll theme inspired by the Tabler Admin Dashboard.
|
112
|
+
\nThis theme offers a clean, professional, and responsive interface, making it ideal
|
113
|
+
for developers, \ncontent creators, and businesses. Whether you're building documentation
|
114
|
+
sites, admin panels, or \nproject showcases, this theme provides a minimal-effort
|
115
|
+
solution with customizable layouts and \nmodern design elements.\n"
|
65
116
|
email:
|
66
117
|
- mpaivabarbosa@gmail.com
|
67
118
|
executables: []
|
@@ -70,11 +121,35 @@ extra_rdoc_files: []
|
|
70
121
|
files:
|
71
122
|
- LICENSE
|
72
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
|
73
130
|
- _includes/footer.html
|
74
|
-
- _includes/
|
75
|
-
- _includes/
|
76
|
-
-
|
131
|
+
- _includes/head.html
|
132
|
+
- _includes/header-logo.html
|
133
|
+
- _includes/header-navbar.html
|
134
|
+
- _includes/header-svg.html
|
135
|
+
- _includes/ui/button.html
|
136
|
+
- _includes/ui/empty.html
|
137
|
+
- _includes/ui/icon.html
|
138
|
+
- _includes/ui/illustration.html
|
139
|
+
- _layouts/default.html
|
140
|
+
- _layouts/error.html
|
141
|
+
- _layouts/home.html
|
142
|
+
- _layouts/post.html
|
77
143
|
- assets/css/theme.min.css
|
144
|
+
- assets/images/android-chrome-192x192.png
|
145
|
+
- assets/images/android-chrome-512x512.png
|
146
|
+
- assets/images/apple-touch-icon.png
|
147
|
+
- assets/images/favicon-16x16.png
|
148
|
+
- assets/images/favicon-32x32.png
|
149
|
+
- assets/images/favicon.ico
|
150
|
+
- assets/images/i4y-logo.jpg
|
151
|
+
- assets/images/preview-dark.png
|
152
|
+
- assets/images/site.webmanifest
|
78
153
|
- assets/js/theme.js
|
79
154
|
homepage: https://github.com/marciopaiva/insights4you-jekyll-theme
|
80
155
|
licenses:
|
@@ -84,7 +159,11 @@ metadata:
|
|
84
159
|
documentation_uri: https://github.com/marciopaiva/insights4you-jekyll-theme/#readme
|
85
160
|
source_code_uri: https://github.com/marciopaiva/insights4you-jekyll-theme
|
86
161
|
wiki_uri: https://github.com/marciopaiva/insights4you-jekyll-theme/wiki
|
162
|
+
changelog_uri: https://github.com/marciopaiva/insights4you-jekyll-theme/blob/main/CHANGELOG.md
|
87
163
|
plugin_type: theme
|
164
|
+
funding_uri: https://github.com/sponsors/marciopaiva
|
165
|
+
usage_uri: https://github.com/marciopaiva/insights4you-jekyll-theme/wiki/Usage
|
166
|
+
examples_uri: https://github.com/marciopaiva/insights4you-jekyll-theme/tree/main/example-site
|
88
167
|
post_install_message:
|
89
168
|
rdoc_options: []
|
90
169
|
require_paths:
|
@@ -93,14 +172,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
93
172
|
requirements:
|
94
173
|
- - "~>"
|
95
174
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3.
|
175
|
+
version: '3.0'
|
97
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
177
|
requirements:
|
99
178
|
- - ">="
|
100
179
|
- !ruby/object:Gem::Version
|
101
180
|
version: '0'
|
102
181
|
requirements: []
|
103
|
-
rubygems_version: 3.3.
|
182
|
+
rubygems_version: 3.3.7
|
104
183
|
signing_key:
|
105
184
|
specification_version: 4
|
106
185
|
summary: A sleek and modern Jekyll theme inspired by the Tabler Admin Dashboard.
|