mirror of
https://gitlab.com/Anson-Projects/projects.git
synced 2025-06-15 14:36:47 +00:00
Merge branch 'modernize' into 'master'
FIx Dev Container See merge request Anson-Projects/projects!9
This commit is contained in:
commit
51c03d9213
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
_freeze/
|
|
||||||
_site/
|
_site/
|
||||||
public/
|
public/
|
||||||
ghost-upload/target/
|
ghost-upload/target/
|
||||||
|
@ -8,13 +8,9 @@ build:
|
|||||||
--context "${CI_PROJECT_DIR}"
|
--context "${CI_PROJECT_DIR}"
|
||||||
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
||||||
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}"
|
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}"
|
||||||
--destination "${CI_REGISTRY_IMAGE}:latest"
|
|
||||||
--cleanup
|
--cleanup
|
||||||
|
|
||||||
staging:
|
staging:
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- _freeze
|
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}
|
image: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_BRANCH}
|
||||||
script:
|
script:
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -2,7 +2,8 @@ const kProgressiveAttr = "data-src";
|
|||||||
let categoriesLoaded = false;
|
let categoriesLoaded = false;
|
||||||
|
|
||||||
window.quartoListingCategory = (category) => {
|
window.quartoListingCategory = (category) => {
|
||||||
category = atob(category);
|
// category is URI encoded in EJS template for UTF-8 support
|
||||||
|
category = decodeURIComponent(atob(category));
|
||||||
if (categoriesLoaded) {
|
if (categoriesLoaded) {
|
||||||
activateCategory(category);
|
activateCategory(category);
|
||||||
setCategoryHash(category);
|
setCategoryHash(category);
|
||||||
|
15
Dockerfile
15
Dockerfile
@ -1,11 +1,12 @@
|
|||||||
FROM ubuntu:22.04
|
FROM debian:bookworm
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
ENV JULIA_VERSION=1.11.1 \
|
ENV JULIA_VERSION=1.11.5 \
|
||||||
JULIA_MAJOR_VERSION=1.11 \
|
JULIA_MAJOR_VERSION=1.11 \
|
||||||
JULIA_PATH=/usr/local/julia \
|
JULIA_PATH=/usr/local/julia
|
||||||
QUARTO_VERSION=1.6.37
|
|
||||||
|
ENV QUARTO_VERSION=1.7.31
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
apt-utils dialog \
|
apt-utils dialog \
|
||||||
@ -13,19 +14,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
python3 python3-pip python3-dev \
|
python3 python3-pip python3-dev \
|
||||||
r-base \
|
r-base \
|
||||||
gcc g++ \
|
gcc g++ \
|
||||||
wget curl tar \
|
curl tar \
|
||||||
openssh-client \
|
openssh-client \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Use a RUN command for architecture detection and conditional logic
|
# Use a RUN command for architecture detection and conditional logic
|
||||||
RUN wget https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-$(if [ "$(uname -m)" = "x86_64" ]; then echo "amd64"; else echo "arm64"; fi).tar.gz -O quarto.tar.gz \
|
RUN curl -fsSL "https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-$(if [ "$(uname -m)" = "x86_64" ]; then echo "amd64"; else echo "arm64"; fi).tar.gz" -o quarto.tar.gz \
|
||||||
&& tar -xzf quarto.tar.gz -C /opt \
|
&& tar -xzf quarto.tar.gz -C /opt \
|
||||||
&& mkdir -p /opt/quarto \
|
&& mkdir -p /opt/quarto \
|
||||||
&& mv /opt/quarto-${QUARTO_VERSION}/* /opt/quarto/ \
|
&& mv /opt/quarto-${QUARTO_VERSION}/* /opt/quarto/ \
|
||||||
&& ln -s /opt/quarto/bin/quarto /usr/local/bin/quarto \
|
&& ln -s /opt/quarto/bin/quarto /usr/local/bin/quarto \
|
||||||
&& rm -rf quarto.tar.gz /opt/quarto-${QUARTO_VERSION}
|
&& rm -rf quarto.tar.gz /opt/quarto-${QUARTO_VERSION}
|
||||||
|
|
||||||
RUN python3 -m pip install jupyter webio_jupyter_extension jupyter-cache
|
RUN python3 -m pip install --break-system-packages jupyter webio_jupyter_extension jupyter-cache
|
||||||
|
|
||||||
RUN curl -fsSL "https://julialang-s3.julialang.org/bin/linux/$(if [ "$(uname -m)" = "x86_64" ]; then echo "x64"; else echo "aarch64"; fi)/${JULIA_MAJOR_VERSION}/julia-${JULIA_VERSION}-linux-$(if [ "$(uname -m)" = "x86_64" ]; then echo "x86_64"; else echo "aarch64"; fi).tar.gz" -o julia.tar.gz \
|
RUN curl -fsSL "https://julialang-s3.julialang.org/bin/linux/$(if [ "$(uname -m)" = "x86_64" ]; then echo "x64"; else echo "aarch64"; fi)/${JULIA_MAJOR_VERSION}/julia-${JULIA_VERSION}-linux-$(if [ "$(uname -m)" = "x86_64" ]; then echo "x86_64"; else echo "aarch64"; fi).tar.gz" -o julia.tar.gz \
|
||||||
&& tar -xzf julia.tar.gz -C /tmp \
|
&& tar -xzf julia.tar.gz -C /tmp \
|
||||||
|
2711
Manifest.toml
2711
Manifest.toml
File diff suppressed because it is too large
Load Diff
11
Project.toml
11
Project.toml
@ -1,20 +1,9 @@
|
|||||||
[deps]
|
[deps]
|
||||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
|
||||||
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
|
|
||||||
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
|
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
|
||||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
|
||||||
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
|
|
||||||
GR_jll = "d2c73de3-f751-5644-a686-071e5b155ba9"
|
|
||||||
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
|
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
|
||||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
|
|
||||||
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
|
|
||||||
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
|
|
||||||
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
|
||||||
Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
|
Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
|
||||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||||
SatelliteToolbox = "6ac157d9-b43d-51bb-8fab-48bf53814f4a"
|
|
||||||
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
|
|
||||||
|
|
||||||
[compat]
|
[compat]
|
||||||
julia = "1.11"
|
julia = "1.11"
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
_freeze/site_libs/clipboard/clipboard.min.js
vendored
Normal file
7
_freeze/site_libs/clipboard/clipboard.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
_freeze/site_libs/quarto-listing/list.min.js
vendored
Normal file
2
_freeze/site_libs/quarto-listing/list.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
253
_freeze/site_libs/quarto-listing/quarto-listing.js
Normal file
253
_freeze/site_libs/quarto-listing/quarto-listing.js
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
const kProgressiveAttr = "data-src";
|
||||||
|
let categoriesLoaded = false;
|
||||||
|
|
||||||
|
window.quartoListingCategory = (category) => {
|
||||||
|
category = atob(category);
|
||||||
|
if (categoriesLoaded) {
|
||||||
|
activateCategory(category);
|
||||||
|
setCategoryHash(category);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window["quarto-listing-loaded"] = () => {
|
||||||
|
// Process any existing hash
|
||||||
|
const hash = getHash();
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
// If there is a category, switch to that
|
||||||
|
if (hash.category) {
|
||||||
|
// category hash are URI encoded so we need to decode it before processing
|
||||||
|
// so that we can match it with the category element processed in JS
|
||||||
|
activateCategory(decodeURIComponent(hash.category));
|
||||||
|
}
|
||||||
|
// Paginate a specific listing
|
||||||
|
const listingIds = Object.keys(window["quarto-listings"]);
|
||||||
|
for (const listingId of listingIds) {
|
||||||
|
const page = hash[getListingPageKey(listingId)];
|
||||||
|
if (page) {
|
||||||
|
showPage(listingId, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listingIds = Object.keys(window["quarto-listings"]);
|
||||||
|
for (const listingId of listingIds) {
|
||||||
|
// The actual list
|
||||||
|
const list = window["quarto-listings"][listingId];
|
||||||
|
|
||||||
|
// Update the handlers for pagination events
|
||||||
|
refreshPaginationHandlers(listingId);
|
||||||
|
|
||||||
|
// Render any visible items that need it
|
||||||
|
renderVisibleProgressiveImages(list);
|
||||||
|
|
||||||
|
// Whenever the list is updated, we also need to
|
||||||
|
// attach handlers to the new pagination elements
|
||||||
|
// and refresh any newly visible items.
|
||||||
|
list.on("updated", function () {
|
||||||
|
renderVisibleProgressiveImages(list);
|
||||||
|
setTimeout(() => refreshPaginationHandlers(listingId));
|
||||||
|
|
||||||
|
// Show or hide the no matching message
|
||||||
|
toggleNoMatchingMessage(list);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.document.addEventListener("DOMContentLoaded", function (_event) {
|
||||||
|
// Attach click handlers to categories
|
||||||
|
const categoryEls = window.document.querySelectorAll(
|
||||||
|
".quarto-listing-category .category"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const categoryEl of categoryEls) {
|
||||||
|
// category needs to support non ASCII characters
|
||||||
|
const category = decodeURIComponent(
|
||||||
|
atob(categoryEl.getAttribute("data-category"))
|
||||||
|
);
|
||||||
|
categoryEl.onclick = () => {
|
||||||
|
activateCategory(category);
|
||||||
|
setCategoryHash(category);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach a click handler to the category title
|
||||||
|
// (there should be only one, but since it is a class name, handle N)
|
||||||
|
const categoryTitleEls = window.document.querySelectorAll(
|
||||||
|
".quarto-listing-category-title"
|
||||||
|
);
|
||||||
|
for (const categoryTitleEl of categoryTitleEls) {
|
||||||
|
categoryTitleEl.onclick = () => {
|
||||||
|
activateCategory("");
|
||||||
|
setCategoryHash("");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
categoriesLoaded = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleNoMatchingMessage(list) {
|
||||||
|
const selector = `#${list.listContainer.id} .listing-no-matching`;
|
||||||
|
const noMatchingEl = window.document.querySelector(selector);
|
||||||
|
if (noMatchingEl) {
|
||||||
|
if (list.visibleItems.length === 0) {
|
||||||
|
noMatchingEl.classList.remove("d-none");
|
||||||
|
} else {
|
||||||
|
if (!noMatchingEl.classList.contains("d-none")) {
|
||||||
|
noMatchingEl.classList.add("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCategoryHash(category) {
|
||||||
|
setHash({ category });
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPageHash(listingId, page) {
|
||||||
|
const currentHash = getHash() || {};
|
||||||
|
currentHash[getListingPageKey(listingId)] = page;
|
||||||
|
setHash(currentHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getListingPageKey(listingId) {
|
||||||
|
return `${listingId}-page`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshPaginationHandlers(listingId) {
|
||||||
|
const listingEl = window.document.getElementById(listingId);
|
||||||
|
const paginationEls = listingEl.querySelectorAll(
|
||||||
|
".pagination li.page-item:not(.disabled) .page.page-link"
|
||||||
|
);
|
||||||
|
for (const paginationEl of paginationEls) {
|
||||||
|
paginationEl.onclick = (sender) => {
|
||||||
|
setPageHash(listingId, sender.target.getAttribute("data-i"));
|
||||||
|
showPage(listingId, sender.target.getAttribute("data-i"));
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderVisibleProgressiveImages(list) {
|
||||||
|
// Run through the visible items and render any progressive images
|
||||||
|
for (const item of list.visibleItems) {
|
||||||
|
const itemEl = item.elm;
|
||||||
|
if (itemEl) {
|
||||||
|
const progressiveImgs = itemEl.querySelectorAll(
|
||||||
|
`img[${kProgressiveAttr}]`
|
||||||
|
);
|
||||||
|
for (const progressiveImg of progressiveImgs) {
|
||||||
|
const srcValue = progressiveImg.getAttribute(kProgressiveAttr);
|
||||||
|
if (srcValue) {
|
||||||
|
progressiveImg.setAttribute("src", srcValue);
|
||||||
|
}
|
||||||
|
progressiveImg.removeAttribute(kProgressiveAttr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHash() {
|
||||||
|
// Hashes are of the form
|
||||||
|
// #name:value|name1:value1|name2:value2
|
||||||
|
const currentUrl = new URL(window.location);
|
||||||
|
const hashRaw = currentUrl.hash ? currentUrl.hash.slice(1) : undefined;
|
||||||
|
return parseHash(hashRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
const kAnd = "&";
|
||||||
|
const kEquals = "=";
|
||||||
|
|
||||||
|
function parseHash(hash) {
|
||||||
|
if (!hash) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const hasValuesStrs = hash.split(kAnd);
|
||||||
|
const hashValues = hasValuesStrs
|
||||||
|
.map((hashValueStr) => {
|
||||||
|
const vals = hashValueStr.split(kEquals);
|
||||||
|
if (vals.length === 2) {
|
||||||
|
return { name: vals[0], value: vals[1] };
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter((value) => {
|
||||||
|
return value !== undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
const hashObj = {};
|
||||||
|
hashValues.forEach((hashValue) => {
|
||||||
|
hashObj[hashValue.name] = decodeURIComponent(hashValue.value);
|
||||||
|
});
|
||||||
|
return hashObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeHash(obj) {
|
||||||
|
return Object.keys(obj)
|
||||||
|
.map((key) => {
|
||||||
|
return `${key}${kEquals}${obj[key]}`;
|
||||||
|
})
|
||||||
|
.join(kAnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHash(obj) {
|
||||||
|
const hash = makeHash(obj);
|
||||||
|
window.history.pushState(null, null, `#${hash}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPage(listingId, page) {
|
||||||
|
const list = window["quarto-listings"][listingId];
|
||||||
|
if (list) {
|
||||||
|
list.show((page - 1) * list.page + 1, list.page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function activateCategory(category) {
|
||||||
|
// Deactivate existing categories
|
||||||
|
const activeEls = window.document.querySelectorAll(
|
||||||
|
".quarto-listing-category .category.active"
|
||||||
|
);
|
||||||
|
for (const activeEl of activeEls) {
|
||||||
|
activeEl.classList.remove("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate this category
|
||||||
|
const categoryEl = window.document.querySelector(
|
||||||
|
`.quarto-listing-category .category[data-category='${btoa(
|
||||||
|
encodeURIComponent(category)
|
||||||
|
)}']`
|
||||||
|
);
|
||||||
|
if (categoryEl) {
|
||||||
|
categoryEl.classList.add("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter the listings to this category
|
||||||
|
filterListingCategory(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterListingCategory(category) {
|
||||||
|
const listingIds = Object.keys(window["quarto-listings"]);
|
||||||
|
for (const listingId of listingIds) {
|
||||||
|
const list = window["quarto-listings"][listingId];
|
||||||
|
if (list) {
|
||||||
|
if (category === "") {
|
||||||
|
// resets the filter
|
||||||
|
list.filter();
|
||||||
|
} else {
|
||||||
|
// filter to this category
|
||||||
|
list.filter(function (item) {
|
||||||
|
const itemValues = item.values();
|
||||||
|
if (itemValues.categories !== null) {
|
||||||
|
const categories = decodeURIComponent(
|
||||||
|
atob(itemValues.categories)
|
||||||
|
).split(",");
|
||||||
|
return categories.includes(category);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user