just gonna push this before massively redesigning the popup modal under preston's recruitment

This commit is contained in:
quartinal 2025-01-25 17:28:22 -08:00
parent 804067db06
commit 76272b26a1
14 changed files with 758 additions and 206 deletions

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
dist/
dist-misc/
node_modules/
pnpm-lock.yaml
.vercel
# Local Netlify folder
.netlify
.idea/

View File

@ -25,7 +25,7 @@ You are welcome to open a pull request to contribute!
> You are more likely to be helped in the Discord Server than open an issue. You **MUST** join the discord server to apply for staff.
> [!NOTE]
> If you are forking this repository and want to keep your fork up to date. You can use the sync fork button **(safer)** on the repository or https://github.com/apps/pull (Github Only) to auto sync **(but read the warning below)**.
> If you are forking this repository and want to keep your fork up to date, you can use the sync fork button **(safer)** on the repository or https://github.com/apps/pull (Github Only) to auto sync **(but read the warning below)**.
> [!WARNING]
> If you choose to use the pull GitHub app, it deletes all the changes you made when it syncs to a new commit; so you should backup your changes.

View File

@ -1,17 +1,16 @@
/* General Styles */
body {
font-family: 'Arial', sans-serif;
font-family: 'Raleway', sans-serif;
background-color: var(--ctp-macchiato-overlay0);
background-size: auto;
margin: 0;
padding: 0;
text-align: center;
display: flex;
flex-direction: column;
min-height: 100vh;
overflow-x: hidden;
color: var(--ctp-macchiato-mantle);
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
display: grid;
grid-template-rows: auto 1fr auto;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
text-align: center;
}
body.dark-mode {
@ -22,88 +21,193 @@ body.dark-mode {
header {
background-color: var(--ctp-macchiato-green);
color: var(--ctp-macchiato-crust);
padding: 20px 0;
text-align: center;
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
padding: 1.5rem 0;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
header h1 {
margin: 0;
transform: translateY(0);
transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
header h1:hover {
transform: translateY(-2px);
}
main {
flex: 1;
padding: 20px;
display: grid;
gap: 2rem;
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
width: 100%;
place-items: center;
}
.darkmodediv {
padding-left: 480px;
padding-right: 480px;
padding: 1rem;
background: var(--ctp-macchiato-rosewater);
}
.counter, .info, .clients, .danger-zone {
margin-bottom: 20px;
border-radius: 8px;
margin: 0 auto;
max-width: 800px;
width: 100%;
}
.Container18, .Container15, .ContainerOther {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 40px;
margin: 20px 0;
align-items: center;
gap: 1rem;
width: 100%;
max-width: 1200px;
padding: 2rem;
background-color: var(--ctp-macchiato-surface0);
border-radius: 12px;
margin: 1rem 0;
}
/* To prevent buttons from becoming too small on narrow screens */
.Container18 button,
.Container15 button,
.ContainerOther button,
.Container18 .source-btn,
.Container15 .source-btn,
.ContainerOther .source-btn,
.Container18 .dsc-btn,
.Container15 .dsc-btn,
.ContainerOther .dsc-btn,
.Container18 .clr-btn,
.Container15 .clr-btn,
.ContainerOther .clr-btn {
min-width: 120px;
margin: 0.5rem;
flex-shrink: 0;
}
/* Add a container for each version category for better organization */
.version-category {
width: 100%;
margin: 1rem 0;
padding: 1rem;
background-color: var(--ctp-macchiato-surface0);
border-radius: 8px;
}
/* Make sure the category title is visible */
.version-category h2 {
margin-bottom: 1rem;
color: var(--ctp-macchiato-text);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.Container18, .Container15, .ContainerOther {
padding: 0.5rem;
}
.Container18 button,
.Container15 button,
.ContainerOther button,
.Container18 .source-btn,
.Container15 .source-btn,
.ContainerOther .source-btn,
.Container18 .dsc-btn,
.Container15 .dsc-btn,
.ContainerOther .dsc-btn,
.Container18 .clr-btn,
.Container15 .clr-btn,
.ContainerOther .clr-btn {
min-width: 100px;
font-size: 0.9rem;
padding: 0.5rem 1rem;
}
}
@media (max-width: 480px) {
.Container18, .Container15, .ContainerOther {
justify-content: flex-start;
overflow-x: auto;
padding: 1rem 0.5rem;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
}
.Container18::-webkit-scrollbar,
.Container15::-webkit-scrollbar,
.ContainerOther::-webkit-scrollbar {
height: 4px;
}
.Container18::-webkit-scrollbar-thumb,
.Container15::-webkit-scrollbar-thumb,
.ContainerOther::-webkit-scrollbar-thumb {
background-color: var(--ctp-macchiato-overlay2);
border-radius: 4px;
}
}
/* Base button styles */
button, .source-btn, .dsc-btn, .clr-btn {
background-color: var(--ctp-macchiato-green);
color: var(--ctp-macchiato-mantle);
padding: 10px 20px;
font-size: 16px;
padding: 0.75rem 1.5rem;
font-size: 1rem;
cursor: pointer;
border: none;
border-radius: 5px;
border-radius: 8px;
text-decoration: none;
display: inline-block;
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
.clientbutton button {
background-color: var(--ctp-macchiato-green);
/* GSAP-like animations only for regular buttons */
button {
position: relative;
overflow: hidden;
transform-origin: center;
transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1),
background-color 0.3s cubic-bezier(0.16, 1, 0.3, 1),
box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
button::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(
120deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transform: translateX(-100%);
transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
button:hover::before {
transform: translateX(100%);
}
button:hover {
transform: scale(+1.14) translateX(-20px);
transform: scale(1.05) translateY(-2px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
button:focus {
outline: 3px solid var(--ctp-macchiato-overlay2);
outline-offset: 2px;
button:active {
transform: scale(0.95);
transition-duration: 0.1s;
}
.clr-btn:hover {
background-color: var(--ctp-macchiato-peach);
transform: scale(+1.14) translateX(-20px);
}
.dsc-btn:hover {
background-color: var(--ctp-macchiato-mauve);
transform: scale(+1.14) translateX(-20px);
color: var(--ctp-macchiato-mantle);
}
.source-btn:hover {
background-color: var(--ctp-macchiato-mantle);
transform: scale(+1.14) translateX(-20px);
}
.source-btn {
background-color: var(--ctp-macchiato-mantle); /* Black color for GitHub button */
/* Simple transitions for dsc-btn and clr-btn */
.dsc-btn, .clr-btn {
transition: background-color 0.3s ease;
}
.dsc-btn {
background-color: var(--ctp-macchiato-crust);
color: var(--ctp-macchiato-lavender);
transition: 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
background-color: var(--ctp-macchiato-mauve);
}
.clr-btn {
@ -111,183 +215,148 @@ button:focus {
}
.search-container {
margin: 20px 0;
display: grid;
place-items: center;
gap: 1rem;
margin: 2rem 0;
width: 100%;
}
#search-bar {
background-color: var(--ctp-macchiato-mantle);
padding: 10px;
border-radius: 35px;
width: 50%;
padding: 1rem 1.5rem;
border-radius: 999px;
width: 100%;
max-width: 500px;
outline: none;
border: 4px solid var(--ctp-macchiato-green);
border: 3px solid var(--ctp-macchiato-green);
color: var(--ctp-macchiato-text);
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
#search-bar:focus {
border-width: 5px;
}
#search-bar::placeholder {
color: var(--ctp-macchiato-text);
border-width: 4px;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.footer {
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 2rem;
padding: 1.5rem;
background-color: var(--ctp-macchiato-overlay1);
color: var(--ctp-macchiato-mantle); /* Light text color for footer */
padding: 10px;
text-align: center;
opacity: 0.9;
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
color: var(--ctp-macchiato-text);
place-items: center;
transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.footer a {
color: var(--ctp-macchiato-text); /* Light text color for footer links */
text-decoration: none;
margin: 0 10px;
opacity: 1;
}
.footer a:hover {
text-decoration: underline;
opacity: 1;
}
.footer button {
color: var(--ctp-macchiato-mantle);
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
opacity: 1;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: var(--ctp-macchiato-mantle);
justify-content: center;
align-items: center;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
place-items: center;
backdrop-filter: blur(4px);
}
.modal-content {
background-color: var(--ctp-macchiato-text);
padding: 20px;
border-radius: 10px;
width: 80%;
max-width: 400px;
text-align: center;
box-shadow: 0px 4px 8px var(--ctp-macchiato-mantle);
transition: background-color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55), color 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
padding: 2rem;
border-radius: 12px;
width: 90%;
max-width: 500px;
display: grid;
gap: 1.5rem;
place-items: center;
transform: translateY(0);
transition: all 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.modal h2 {
color: var(--ctp-macchiato-surface1);
/* Source button with minimal animation */
.source-btn {
background-color: var(--ctp-macchiato-mantle);
transition: background-color 0.3s ease;
}
.modal p {
color: var(--ctp-macchiato-mantle);
margin-bottom: 20px;
}
.modal button {
background-color: var(--ctp-macchiato-green);
color: var(--ctp-macchiato-text);
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 5px;
margin: 5px;
}
.modal button.cancel-btn {
background-color: var(--ctp-macchiato-peach);
}
.modal button:hover {
background-color: var(--ctp-macchiato-green);
}
.modal button.cancel-btn:hover {
background-color: var(--ctp-macchiato-maroon);
}
.copy-link {
background-color: var(--ctp-macchiato-lavender);
padding: 10px;
border: 1px solid var(--ctp-macchiato-text);
border-radius: 5px;
margin-bottom: 15px;
}
.copy-btn {
background-color: var(--ctp-macchiato-mauve);
}
.copy-btn:hover {
filter: brightness(1.2);
}
/* Dark Mode Styles */
/* Dark Mode enhancements */
body.dark-mode .modal-content {
background-color: var(--ctp-macchiato-mantle);
color: var(--ctp-macchiato-text);
}
body.dark-mode .modal h2 {
color: var(--ctp-macchiato-text);
}
body.dark-mode .modal p {
color: var(--ctp-macchiato-text);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
body.dark-mode #search-bar {
background-color: var(--ctp-macchiato-overlay0);
color: var(--ctp-macchiato-text);
border-color: var(--ctp-macchiato-overlay1);
}
body.dark-mode #search-bar:focus {
border-color: var(--ctp-macchiato-green);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
body.dark-mode .footer {
background-color: var(--ctp-macchiato-overlay0); /* Dark gray color for footer in dark mode */
color: var(--ctp-macchiato-text); /* Light text color for footer in dark mode */
background-color: var(--ctp-macchiato-overlay0);
border-top: 1px solid var(--ctp-macchiato-overlay1);
}
body.dark-mode .footer a {
color: var(--ctp-macchiato-text); /* Light text color for footer links in dark mode */
/* Responsive centering for smaller screens */
@media (max-width: 768px) {
.Container18, .Container15, .ContainerOther {
grid-template-columns: 1fr;
max-width: 400px;
margin: 0 auto;
}
.darkmodediv {
padding: 1rem;
margin: 0 1rem;
}
}
body.dark-mode .footer button.server-list {
background-color: var(--ctp-macchiato-crust); /* Black color for Server List button in dark mode */
/* Tabs styling */
.tabs {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-bottom: 2rem;
padding: 0 1rem;
}
body.dark-mode .footer button.server-list:hover {
background-color: var(--ctp-macchiato-overlay1); /* Slightly lighter shade for hover effect in dark mode */
.tab {
background-color: var(--ctp-macchiato-surface0);
color: var(--ctp-macchiato-text);
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-family: 'Raleway', sans-serif;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
body.dark-mode .footer button.eaglerrinth-mod-list {
background-color: var(--ctp-macchiato-mauve); /* Same color as Discord link button in dark mode */
.tab.active {
background-color: var(--ctp-macchiato-mauve);
color: var(--ctp-macchiato-base);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
body.dark-mode .footer button.eaglerrinth-mod-list:hover {
filter: brightness(1.2); /* Slightly lighter shade for hover effect in dark mode */
.tab:hover:not(.active) {
background-color: var(--ctp-macchiato-surface1);
transform: translateY(-1px);
}
.tab-content {
display: none;
opacity: 0;
transform: translateY(10px);
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.tab-content.active {
display: block;
opacity: 1;
transform: translateY(0);
}
/* Version text styling */
.version-text {
display: none; /* Hide the original version text */
}

View File

@ -0,0 +1,49 @@
import prettifyMilliseconds from '../packages/pretty-ms/index.js';
export default function getPageLoadTime() {
const [navigation] = performance.getEntriesByType('navigation');
const loadTime = navigation.loadEventEnd - navigation.startTime;
const prettifiedLoadTime = prettifyMilliseconds(loadTime);
return { loadTime, prettifiedLoadTime };
}
export function initializePeformanceChecks() {
window.addEventListener('load', () => {
const { loadTime, prettifiedLoadTime } = getPageLoadTime();
const { sanitize } = self.DOMPurify;
if (loadTime >= 2500) {
document.body.setAttribute('data-slow', 'true');
}
const pageLoadedSlowly = Boolean(document.body.dataset.slow);
if (pageLoadedSlowly)
document.body.classList.add('performance-popover');
if (document.body.classList.contains('performance-popover')) {
document.body.innerHTML = sanitize(
`
<div class="performance-popover-section">
<h2>Whoops!</h2>
<p>Looks like <span>${location.host}</span> loaded slower than usual!</p>
<p>Precisely, it loaded in ${prettifiedLoadTime}.</p>
<p data-question-anchor>
Do you want to <a data-one>turn off script obfuscation</a> or <a data-two>continue</a>?
</p>
</div>
`
);
const styleSheet = document.createElement('style');
document.head.appendChild(styleSheet);
const { sheet } = styleSheet;
const rulesLength = sheet.cssRules.length;
}
});
}

View File

@ -0,0 +1 @@
export { default as default } from 'pretty-ms';

View File

@ -0,0 +1,323 @@
export const TemplateEngine = {
state: new Proxy({}, {
set(target, property, value) {
target[property] = value;
TemplateEngine.updateDependents(property);
return true;
}
}),
dependencyMap: new Map(),
components: new Map(),
init() {
this.registerComponents();
this.processDOM(document.body);
this.setupEventListeners();
},
registerComponent(name, template) {
this.components.set(name, template);
},
registerComponents() {
const templates = document.querySelectorAll('template[data-component]');
templates.forEach(template => {
const name = template.dataset.component;
this.components.set(name, template.innerHTML);
template.remove();
});
},
setupTwoWayBinding(element) {
if (element.hasAttribute('bind')) {
const bindExpression = element.getAttribute('bind');
const [stateKey] = bindExpression.split('.');
element.value = this.evaluateExpression(bindExpression);
this.addDependency(stateKey, element);
element.addEventListener('input', (e) => {
const value = element.type === 'checkbox' ? element.checked : element.value;
this.setState(bindExpression, value);
});
}
},
setupEventListeners() {
document.addEventListener('click', (e) => {
let target = e.target;
while (target && target !== document) {
const eventAttrs = [...target.attributes].filter(attr =>
attr.name.startsWith('@')
);
eventAttrs.forEach(attr => {
const handler = attr.value;
try {
const func = new Function('event', `
const target = event.target;
${handler}
`);
func(e);
} catch (error) {
console.error(`Error in event handler "${handler}":`, error);
}
});
target = target.parentNode;
}
});
},
processDOM(rootElement) {
this.processComponents(rootElement);
this.evaluateAttributes(rootElement);
this.processControlFlow(rootElement);
this.processLoops(rootElement);
this.setupReactivity(rootElement);
},
processComponents(element) {
this.components.forEach((template, name) => {
const components = element.getElementsByTagName(name);
[...components].forEach(component => {
const props = [...component.attributes].reduce((acc, attr) => {
acc[attr.name] = this.evaluateExpression(attr.value);
return acc;
}, {});
const content = template.replace(/\${([^}]+)}/g, (_, expr) => {
return this.evaluateExpression(expr, props);
});
component.innerHTML = content;
});
});
},
processLoops(element) {
const processForLoop = (node) => {
const forExpr = node.textContent.trim().slice(4);
const matches = forExpr.match(/(\w+)\s+of\s+(.+)/);
if (!matches) return;
const [_, itemName, arrayExpr] = matches;
const array = this.evaluateExpression(arrayExpr);
if (!Array.isArray(array)) {
throw new Error(`Expression "${arrayExpr}" must evaluate to an array`);
}
const template = document.createDocumentFragment();
let currentNode = node.nextSibling;
while (currentNode && currentNode.textContent.trim() !== 'endfor') {
template.appendChild(currentNode.cloneNode(true));
currentNode = currentNode.nextSibling;
}
const parent = node.parentNode;
array.forEach((item, index) => {
const context = {
[itemName]: item,
index
};
const instance = template.cloneNode(true);
this.evaluateWithContext(instance, context);
parent.insertBefore(instance, node);
});
while (currentNode && currentNode.textContent.trim() !== 'endfor') {
const next = currentNode.nextSibling;
parent.removeChild(currentNode);
currentNode = next;
}
parent.removeChild(node);
if (currentNode) parent.removeChild(currentNode);
};
const walker = document.createTreeWalker(
element,
NodeFilter.SHOW_COMMENT,
null,
false
);
const forNodes = [];
let currentNode;
while (currentNode = walker.nextNode()) {
if (currentNode.textContent.trim().startsWith('for ')) {
forNodes.push(currentNode);
}
}
forNodes.forEach(node => processForLoop(node));
},
setupReactivity(element) {
[...element.attributes || []].forEach(attr => {
const match = attr.value.match(/^{(.+)}$/);
if (match) {
const expression = match[1];
const stateKeys = this.extractStateKeys(expression);
stateKeys.forEach(key => {
this.addDependency(key, element);
});
}
});
[...element.children].forEach(child => this.setupReactivity(child));
},
extractStateKeys(expression) {
const stateKeys = new Set();
const matches = expression.match(/\b\w+\b/g) || [];
matches.forEach(match => {
if (this.state.hasOwnProperty(match)) {
stateKeys.add(match);
}
});
return Array.from(stateKeys);
},
addDependency(stateKey, element) {
if (!this.dependencyMap.has(stateKey)) {
this.dependencyMap.set(stateKey, new Set());
}
this.dependencyMap.get(stateKey).add(element);
},
updateDependents(stateKey) {
const dependents = this.dependencyMap.get(stateKey);
if (dependents) {
dependents.forEach(element => {
this.evaluateAttributes(element);
});
}
},
setState(path, value) {
const parts = path.split('.');
let current = this.state;
for (let i = 0; i < parts.length - 1; i++) {
current = current[parts[i]];
}
current[parts[parts.length - 1]] = value;
},
evaluateExpression(expression, context = {}) {
try {
const func = new Function(
...Object.keys(context),
`return ${expression}`
);
return func(...Object.values(context));
} catch (error) {
throw new Error(`Error evaluating expression "${expression}": ${error.message}`);
}
},
evaluateWithContext(element, context) {
[...element.attributes || []].forEach(attr => {
const match = attr.value.match(/^{(.+)}$/);
if (match) {
const expression = match[1];
try {
const result = this.evaluateExpression(expression, context);
element.setAttribute(attr.name, result);
} catch (error) {
console.error(error);
}
}
});
[...element.children].forEach(child => this.evaluateWithContext(child, context));
},
evaluateAttributes(element) {
const attributes = [...element.attributes || []];
attributes.forEach(attr => {
const match = attr.value.match(/^{(.+)}$/);
if (match) {
const expression = match[1];
try {
const result = this.evaluateExpression(expression);
if (result === undefined || result === null) {
throw new Error(`Variable "${expression}" is undefined or null`);
}
element.setAttribute(attr.name, result);
} catch (error) {
throw new Error(`Error evaluating expression "${expression}" in attribute "${attr.name}": ${error.message}`);
}
}
});
[...element.children].forEach(child => this.evaluateAttributes(child));
},
processControlFlow(element) {
const processIfStatements = (startNode) => {
let currentNode = startNode;
let removeNodes = [];
let keepContent = false;
let foundTruthy = false;
while (currentNode) {
if (currentNode.nodeType === Node.COMMENT_NODE) {
const content = currentNode.textContent.trim();
if (content.startsWith('if ')) {
const condition = content.slice(3);
try {
keepContent = this.evaluateExpression(condition);
foundTruthy = keepContent;
} catch (error) {
throw new Error(`Error evaluating if condition "${condition}": ${error.message}`);
}
} else if (content === 'else if' || content === 'else') {
keepContent = !foundTruthy;
if (keepContent && content === 'else if') {
foundTruthy = true;
}
} else if (content === 'endif') {
break;
}
removeNodes.push(currentNode);
} else if (!keepContent && currentNode.nodeType === Node.ELEMENT_NODE) {
removeNodes.push(currentNode);
}
currentNode = currentNode.nextSibling;
}
removeNodes.forEach(node => node.parentNode.removeChild(node));
};
const walker = document.createTreeWalker(
element,
NodeFilter.SHOW_COMMENT,
null,
false
);
const ifNodes = [];
let currentNode;
while (currentNode = walker.nextNode()) {
if (currentNode.textContent.trim().startsWith('if ')) {
ifNodes.push(currentNode);
}
}
ifNodes.forEach(node => processIfStatements(node));
}
};

28
getTsupTargets.js Normal file
View File

@ -0,0 +1,28 @@
import bcd from '@mdn/browser-compat-data/forLegacyNode';
function getTsupTargets() {
const popularBrowsers = ['chrome', 'firefox', 'safari', 'edge'];
return Object.entries(bcd.browsers)
.filter(([name]) => popularBrowsers.includes(name.toLowerCase()))
.map(([name, data]) => {
const browserName = name.toLowerCase();
const latestVersion = Object.keys(data.releases || {})
.filter(versionKey => {
const release = data.releases?.[versionKey];
return release?.status === 'current';
})
.map(versionKey => parseFloat(versionKey))
.sort((a, b) => b - a)[0];
if (!latestVersion) {
return null;
}
return `${browserName}${Math.floor(latestVersion)}`;
})
.filter(Boolean);
}
export const target = getTsupTargets();

View File

@ -9,6 +9,7 @@
<link rel="icon" type="image/x-icon" href="images/eaglercommunity.png">
<link rel="stylesheet" href="./css/styles.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@catppuccin/palette/css/catppuccin.min.css">
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script async src="https://cdn.jsdelivr.net/npm/es-module-shims"></script>
<script type="importmap">
@ -22,12 +23,14 @@
<script defer src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script defer async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2593894696548093" crossorigin="anonymous"></script>
<script type="module-shim" src="js/darkmode.js"></script>
<script type="module" src="js/main.js"></script>
<script type="module" src="js/darkmode.js"></script>
<script type="module" src="js/ga4.js"></script>
<script type="module-shim" src="js/main.js"></script>
<script type="module" src="js/popupPrompt.js"></script>
<script type="module" src="js/tabs.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bowser"></script>
<script src="https://cdn.jsdelivr.net/npm/fuse.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify"></script>
<meta property="og:title" content="Eaglercraft Client Collections">
<meta property="og:type" content="website">
@ -71,8 +74,6 @@
<div class="clientbutton">
<section class="clients">
<h2 class="pick-client">Pick a Client:</h2>
<label for="showModded">Show Modded Clients</label>
<input type="checkbox" id="showModded">
<div class="search-container">
<input type="text" id="search-bar" placeholder="Search Clients...">
</div>

View File

@ -1,13 +1,11 @@
import {
hexToRGB,
pushStyles,
pushStyles,
selectClass,
selectId,
selectId,
selectTag,
} from "./helperFunctions.js";
global.querySelectorAll = document.querySelectorAll;
$(function() {
function applyStyles(elements, styles) {
elements.forEach(element => pushStyles(element, styles));
@ -20,13 +18,12 @@ $(function() {
color: hexToRGB('#f1f1f1')
} : {
backgroundColor: '#f1f1f1',
color: 'black',
color: 'var(--ctp-macchiato-mantle)',
backgroundImage: "url('/images/grass-background.jpg')"
};
pushStyles(body, commonStyles);
applyStyles(document.querySelectorAll('p'), { color: commonStyles.color });
applyStyles([selectTag('h2'), selectTag('h1')], { color: commonStyles.color });
if (isChecked) {

View File

@ -61,9 +61,13 @@ $(function() {
}
}
function updateShowModded() {
toggleVisibility("#moddedButtons", $("#showModded").is(":checked"));
}
// fix something very absurd
window.addEventListener('load', () => {
if (!($('#darkModeCheckbox').is(':checked'))) {
$('.footer p').removeAttr('style');
$('.footer p').css('color', 'var(--ctp-macchiato-text)');
}
});
$("#darkModeCheckbox").on("change", updateDarkMode);
updateDarkMode();
@ -71,7 +75,4 @@ $(function() {
selectId('clr-data-modal').addEventListener('click', handleClrModalClick);
$('#search-bar').on('keyup', handleSearchBarKeyup);
$("#showModded").on("change", updateShowModded);
updateShowModded();
});

48
js/tabs.js Normal file
View File

@ -0,0 +1,48 @@
document.addEventListener('DOMContentLoaded', function() {
const tabsContainer = document.createElement('div');
tabsContainer.className = 'tabs';
const tabs = [
{ id: 'tab18', text: '1.8 Clients', content: '#desktopVersion18' },
{ id: 'tabModded', text: 'Modded Clients', content: '#moddedButtons' },
{ id: 'tab152', text: '1.5.2 Clients', content: '#desktopVersion152' },
{ id: 'tabOther', text: 'Other Versions', content: '#desktopVersionOther' }
];
const searchContainer = document.querySelector('.search-container');
tabs.forEach((tab, index) => {
const button = document.createElement('button');
button.className = `tab ${index === 0 ? 'active' : ''}`;
button.setAttribute('data-tab', tab.content);
button.textContent = tab.text;
tabsContainer.appendChild(button);
});
searchContainer.after(tabsContainer);
document.querySelectorAll('.version-text').forEach(text => {
text.style.display = 'none';
});
document.querySelector(tabs[0].content).classList.add('tab-content', 'active');
tabs.slice(1).forEach(tab => {
document.querySelector(tab.content).classList.add('tab-content');
});
tabsContainer.addEventListener('click', (e) => {
if (e.target.classList.contains('tab')) {
document.querySelectorAll('.tab').forEach(tab => {
tab.classList.remove('active');
});
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
e.target.classList.add('active');
const contentId = e.target.getAttribute('data-tab');
document.querySelector(contentId).classList.add('active');
}
});
});

View File

@ -2,18 +2,22 @@
"name": "somethingidontknowabout",
"private": true,
"dependencies": {
"@mdn/browser-compat-data": "^5.6.33",
"brotli-wasm": "^3.0.1",
"fast-glob": "^3.3.3",
"tsup": "^8.3.5"
"pretty-ms": "^9.2.0",
"tsup": "^8.3.6"
},
"devDependencies": {
"@types/jquery": "^3.5.32",
"@types/node": "^22.10.7",
"@types/node": "^22.10.10",
"jscrewit": "^2.39.0",
"typescript": "^5.7.3"
},
"scripts": {
"compress": "tsup --config tsup.config.js",
"compressWasm": "node compressWasm.cjs ./eagler-files/**/*.wasm"
"compressWasm": "node compressWasm.cjs ./eagler-files/**/*.wasm",
"compressMisc": "tsup --config tsup.config.misc.js"
},
"type": "module"
}

View File

@ -1,10 +1,11 @@
import { defineConfig } from 'tsup';
import fg from 'fast-glob';
import { target } from './getTsupTargets';
export default defineConfig({
entry: fg.globSync('eagler-files/**/*.js'),
format: ['esm'],
target: ['chrome131'],
target,
dts: false,
clean: true,
sourcemap: true,

28
tsup.config.misc.js Normal file
View File

@ -0,0 +1,28 @@
import { defineConfig } from 'tsup';
import fg from 'fast-glob';
import { target } from './getTsupTargets.js';
export default defineConfig([
{
entry: fg.globSync('dist-templates/**/*.js'),
format: 'esm',
target,
dts: false,
clean: true,
sourcemap: false,
minify: true,
watch: false,
outDir: 'dist-misc'
},
{
entry: fg.globSync('js/*.js'),
format: 'esm',
target,
dts: false,
clean: true,
sourcemap: false,
minify: true,
watch: false,
outDir: 'dist-misc/js'
}
]);