Compare commits
4 Commits
dfbd532efd
...
v1.3.1
Author | SHA1 | Date | |
---|---|---|---|
41450837f2 | |||
4edeb8709a | |||
6fc573c510 | |||
43c007c1fe |
27
Dockerfile
27
Dockerfile
@ -1,42 +1,19 @@
|
|||||||
FROM python:3.11-alpine
|
FROM python:3.11-slim
|
||||||
|
|
||||||
RUN apk add --no-cache --virtual .build-deps \
|
|
||||||
build-base \
|
|
||||||
jpeg-dev \
|
|
||||||
zlib-dev \
|
|
||||||
libffi-dev \
|
|
||||||
musl-dev \
|
|
||||||
&& apk add --no-cache \
|
|
||||||
jpeg \
|
|
||||||
zlib \
|
|
||||||
libwebp \
|
|
||||||
bash
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt \
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
&& apk del .build-deps
|
|
||||||
|
|
||||||
RUN rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
# Copy source code and scripts
|
|
||||||
COPY ./src/ ./src/
|
COPY ./src/ ./src/
|
||||||
COPY ./build.py ./build.py
|
COPY ./build.py ./build.py
|
||||||
COPY ./gallery.py ./gallery.py
|
COPY ./gallery.py ./gallery.py
|
||||||
|
|
||||||
# Copy default config
|
|
||||||
COPY ./config /app/default
|
COPY ./config /app/default
|
||||||
|
|
||||||
# Copy entrypoint and make executable
|
|
||||||
COPY ./docker/.sh/entrypoint.sh /app/entrypoint.sh
|
COPY ./docker/.sh/entrypoint.sh /app/entrypoint.sh
|
||||||
RUN chmod +x /app/entrypoint.sh
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
# Add wrapper scripts for convenience commands
|
|
||||||
RUN printf '#!/bin/sh\n/app/entrypoint.sh build\n' > /usr/local/bin/build && chmod +x /usr/local/bin/build && \
|
RUN printf '#!/bin/sh\n/app/entrypoint.sh build\n' > /usr/local/bin/build && chmod +x /usr/local/bin/build && \
|
||||||
printf '#!/bin/sh\n/app/entrypoint.sh gallery\n' > /usr/local/bin/gallery && chmod +x /usr/local/bin/gallery
|
printf '#!/bin/sh\n/app/entrypoint.sh gallery\n' > /usr/local/bin/gallery && chmod +x /usr/local/bin/gallery
|
||||||
|
|
||||||
|
|
||||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ copy_default_config() {
|
|||||||
|
|
||||||
if [ ! -e "$target" ]; then
|
if [ ! -e "$target" ]; then
|
||||||
echo "Copying default config file: $filename"
|
echo "Copying default config file: $filename"
|
||||||
cp "$file" "$target"
|
cp -r "$file" "$target"
|
||||||
files_copied=true
|
files_copied=true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -33,10 +33,16 @@ copy_default_config() {
|
|||||||
|
|
||||||
|
|
||||||
start_server() {
|
start_server() {
|
||||||
|
# Clean up old FIFOs
|
||||||
|
[ -p /tmp/build_logs_fifo ] && rm /tmp/build_logs_fifo
|
||||||
|
[ -p /tmp/build_logs_fifo2 ] && rm /tmp/build_logs_fifo2
|
||||||
|
|
||||||
mkfifo /tmp/build_logs_fifo
|
mkfifo /tmp/build_logs_fifo
|
||||||
mkfifo /tmp/build_logs_fifo2
|
mkfifo /tmp/build_logs_fifo2
|
||||||
|
|
||||||
cat /tmp/build_logs_fifo >&2 &
|
cat /tmp/build_logs_fifo >&2 &
|
||||||
cat /tmp/build_logs_fifo2 >&2 &
|
cat /tmp/build_logs_fifo2 >&2 &
|
||||||
|
|
||||||
echo "Starting HTTP server on port 3000..."
|
echo "Starting HTTP server on port 3000..."
|
||||||
python3 -u -m http.server 3000 -d /app/output &
|
python3 -u -m http.server 3000 -d /app/output &
|
||||||
SERVER_PID=$!
|
SERVER_PID=$!
|
||||||
@ -44,10 +50,9 @@ start_server() {
|
|||||||
wait $SERVER_PID
|
wait $SERVER_PID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
if [ $# -eq 0 ]; then
|
||||||
echo -e "${CYAN}╭───────────────────────────────────────────╮${NC}"
|
echo -e "${CYAN}╭───────────────────────────────────────────╮${NC}"
|
||||||
echo -e "${CYAN}│${NC} Lum${CYAN}eex${NC} - Version 1.3${NC} ${CYAN}│${NC}"
|
echo -e "${CYAN}│${NC} Lum${CYAN}eex${NC} - Version 1.3.1${NC} ${CYAN}│${NC}"
|
||||||
echo -e "${CYAN}├───────────────────────────────────────────┤${NC}"
|
echo -e "${CYAN}├───────────────────────────────────────────┤${NC}"
|
||||||
echo -e "${CYAN}│${NC} Source: https://git.djeex.fr/Djeex/lumeex ${CYAN}│${NC}"
|
echo -e "${CYAN}│${NC} Source: https://git.djeex.fr/Djeex/lumeex ${CYAN}│${NC}"
|
||||||
echo -e "${CYAN}│${NC} Mirror: https://github.com/Djeex/lumeex ${CYAN}│${NC}"
|
echo -e "${CYAN}│${NC} Mirror: https://github.com/Djeex/lumeex ${CYAN}│${NC}"
|
||||||
|
@ -17,24 +17,11 @@ const setupLoader = () => {
|
|||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const loader = document.querySelector('.page-loader');
|
const loader = document.querySelector('.page-loader');
|
||||||
if (loader) {
|
if (loader) loader.classList.add('hidden');
|
||||||
loader.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gallery randomizer to shuffle gallery sections on page load
|
|
||||||
const shuffleGallery = () => {
|
|
||||||
const gallery = document.querySelector('.gallery');
|
|
||||||
if (!gallery) return;
|
|
||||||
const sections = Array.from(gallery.querySelectorAll('.section'));
|
|
||||||
while (sections.length) {
|
|
||||||
const randomIndex = Math.floor(Math.random() * sections.length);
|
|
||||||
gallery.appendChild(sections.splice(randomIndex, 1)[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hero background randomizer
|
// Hero background randomizer
|
||||||
const randomizeHeroBackground = () => {
|
const randomizeHeroBackground = () => {
|
||||||
const heroBg = document.querySelector(".hero-background");
|
const heroBg = document.querySelector(".hero-background");
|
||||||
@ -65,32 +52,74 @@ const randomizeHeroBackground = () => {
|
|||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Gallery randomizer to shuffle gallery sections on page load
|
||||||
|
const shuffleGallery = () => {
|
||||||
|
const gallery = document.querySelector('.gallery');
|
||||||
|
if (!gallery) return;
|
||||||
|
const sections = Array.from(gallery.querySelectorAll('.section'));
|
||||||
|
while (sections.length) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * sections.length);
|
||||||
|
gallery.appendChild(sections.splice(randomIndex, 1)[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Tags filter functionality
|
// Tags filter functionality
|
||||||
const setupTagFilter = () => {
|
const setupTagFilter = () => {
|
||||||
|
const galleryContainer = document.querySelector('#gallery');
|
||||||
const allSections = document.querySelectorAll('.section[data-tags]');
|
const allSections = document.querySelectorAll('.section[data-tags]');
|
||||||
const allTags = document.querySelectorAll('.tag');
|
const allTags = document.querySelectorAll('.tag');
|
||||||
let activeTags = [];
|
let activeTags = [];
|
||||||
|
let lastClickedTag = null; // mémorise le dernier tag cliqué
|
||||||
|
|
||||||
const applyFilter = () => {
|
const applyFilter = () => {
|
||||||
|
let filteredSections = [];
|
||||||
|
let matchingSection = null;
|
||||||
|
|
||||||
allSections.forEach((section) => {
|
allSections.forEach((section) => {
|
||||||
const sectionTags = section.dataset.tags.toLowerCase().split(/\s+/);
|
const sectionTags = section.dataset.tags.toLowerCase().split(/\s+/);
|
||||||
const hasAllTags = activeTags.every((tag) => sectionTags.includes(tag));
|
const hasAllTags = activeTags.every((tag) => sectionTags.includes(tag));
|
||||||
section.style.display = hasAllTags ? '' : 'none';
|
section.style.display = hasAllTags ? '' : 'none';
|
||||||
|
|
||||||
|
if (hasAllTags) {
|
||||||
|
filteredSections.push(section);
|
||||||
|
if (lastClickedTag && sectionTags.includes(lastClickedTag) && !matchingSection) {
|
||||||
|
matchingSection = section;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Réorganise : la photo correspondante au dernier tag cliqué en premier
|
||||||
|
if (matchingSection && galleryContainer.contains(matchingSection)) {
|
||||||
|
galleryContainer.prepend(matchingSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Met à jour le style des tags
|
||||||
allTags.forEach((tagEl) => {
|
allTags.forEach((tagEl) => {
|
||||||
const tagText = tagEl.textContent.replace('#', '').toLowerCase();
|
const tagText = tagEl.textContent.replace('#', '').toLowerCase();
|
||||||
tagEl.classList.toggle('active', activeTags.includes(tagText));
|
tagEl.classList.toggle('active', activeTags.includes(tagText));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Met à jour l'URL
|
||||||
const base = window.location.pathname;
|
const base = window.location.pathname;
|
||||||
const query = activeTags.length > 0 ? `?tag=${activeTags.join(',')}` : '';
|
const query = activeTags.length > 0 ? `?tag=${activeTags.join(',')}` : '';
|
||||||
window.history.pushState({}, '', base + query);
|
window.history.pushState({}, '', base + query);
|
||||||
|
|
||||||
|
// Scroll jusqu'à la galerie
|
||||||
|
if (galleryContainer) {
|
||||||
|
galleryContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
allTags.forEach((tagEl) => {
|
allTags.forEach((tagEl) => {
|
||||||
tagEl.addEventListener('click', () => {
|
tagEl.addEventListener('click', () => {
|
||||||
const tagText = tagEl.textContent.replace('#', '').toLowerCase();
|
const tagText = tagEl.textContent.replace('#', '').toLowerCase();
|
||||||
activeTags = activeTags.includes(tagText)
|
lastClickedTag = tagText; // mémorise le dernier tag cliqué
|
||||||
? activeTags.filter((t) => t !== tagText)
|
|
||||||
: [...activeTags, tagText];
|
if (activeTags.includes(tagText)) {
|
||||||
|
activeTags = activeTags.filter((t) => t !== tagText);
|
||||||
|
} else {
|
||||||
|
activeTags.push(tagText);
|
||||||
|
}
|
||||||
applyFilter();
|
applyFilter();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -100,29 +129,24 @@ const setupTagFilter = () => {
|
|||||||
const urlTags = params.get('tag');
|
const urlTags = params.get('tag');
|
||||||
if (urlTags) {
|
if (urlTags) {
|
||||||
activeTags = urlTags.split(',').map((t) => t.toLowerCase());
|
activeTags = urlTags.split(',').map((t) => t.toLowerCase());
|
||||||
|
lastClickedTag = activeTags[activeTags.length - 1] || null;
|
||||||
applyFilter();
|
applyFilter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Disable right-click context menu and image dragging
|
// Disable right click and drag
|
||||||
const disableRightClickAndDrag = () => {
|
const disableRightClickAndDrag = () => {
|
||||||
document.addEventListener("contextmenu", (e) => e.preventDefault());
|
document.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
document.addEventListener("dragstart", (e) => {
|
document.addEventListener('dragstart', (e) => e.preventDefault());
|
||||||
if (e.target.tagName === "IMG") {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scroll-to-top button functionality
|
// Scroll to top button
|
||||||
const setupScrollToTopButton = () => {
|
const setupScrollToTopButton = () => {
|
||||||
const scrollBtn = document.getElementById("scrollToTop");
|
const scrollToTopButton = document.querySelector('.scroll-to-top');
|
||||||
window.addEventListener("scroll", () => {
|
if (!scrollToTopButton) return;
|
||||||
scrollBtn.style.display = window.scrollY > 300 ? "block" : "none";
|
scrollToTopButton.addEventListener('click', () => {
|
||||||
});
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
scrollBtn.addEventListener("click", () => {
|
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,8 +333,12 @@ h2 {
|
|||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sections */
|
|
||||||
|
|
||||||
|
.gallery {
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections */
|
||||||
.section {
|
.section {
|
||||||
max-width: 1140px;
|
max-width: 1140px;
|
||||||
margin:auto;
|
margin:auto;
|
||||||
@ -508,4 +512,9 @@ h2 {
|
|||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gallery {
|
||||||
|
margin: 10% 5% 0 5%;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,11 +23,11 @@ SITE_FILE = SRC_DIR / "config/site.yaml"
|
|||||||
THEMES_DIR = SRC_DIR / "config/themes"
|
THEMES_DIR = SRC_DIR / "config/themes"
|
||||||
|
|
||||||
def build():
|
def build():
|
||||||
build_version = "v1.3"
|
build_version = "v1.3.1"
|
||||||
logging.info("\n")
|
logging.info("\n")
|
||||||
logging.info("=" * 23)
|
logging.info("=" * 24)
|
||||||
logging.info(f"🚀 Lumeex builder {build_version}")
|
logging.info(f"🚀 Lumeex builder {build_version}")
|
||||||
logging.info("=" * 23)
|
logging.info("=" * 24)
|
||||||
logging.info("\n === Starting build === ")
|
logging.info("\n === Starting build === ")
|
||||||
ensure_dir(BUILD_DIR)
|
ensure_dir(BUILD_DIR)
|
||||||
copy_assets(JS_DIR, STYLE_DIR, BUILD_DIR)
|
copy_assets(JS_DIR, STYLE_DIR, BUILD_DIR)
|
||||||
|
Reference in New Issue
Block a user