-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from Ladysnake/dev/cca-version-select
add version selector for CCA developer wiki
- Loading branch information
Showing
4 changed files
with
197 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,26 @@ | ||
{% capture tabbed_id %}tabbed{% increment tabbed_id %}-{{ include.key }}{% endcapture %} | ||
<fieldset id="{{ tabbed_id }}" class="tabbed" role="tablist" data-tabbed-key="{{ include.key }}" style="grid-template-areas: '{% for tab in include.tabs %}tab{{ forloop.index }} {% endfor %}' '{% for tab in include.tabs %}content {% endfor %}'"> | ||
{% for tab in include.tabs %} | ||
{%- assign tab_name = include.tab_names[forloop.index0] | markdownify | remove: '<p>' | remove: '</p>' %} | ||
{%- capture panel_id %}{{ tabbed_id }}-panel{{ forloop.index }}{% endcapture %} | ||
<input type="radio" name="{{ tabbed_id }}" id="{{ tabbed_id }}-tab{{ forloop.index }}" role="tab" aria-controls="{{ panel_id }}" value="{{ tab_name | strip_html | slugify }}" tabindex="0" {% if forloop.first %}checked{% endif %}> | ||
<label for="{{ tabbed_id }}-tab{{ forloop.index }}" style="grid-area: tab{{ forloop.index }}">{{ tab_name }}</label> | ||
<div id="{{ panel_id }}" role="tabpanel"> | ||
{{ tab | markdownify }} | ||
</div> | ||
{% endfor %} | ||
<fieldset | ||
id="{{ tabbed_id }}" | ||
class="tabbed" | ||
data-tabbed-key="{{ include.key }}" | ||
style="grid-template-areas: '{% for tab in include.tabs %}tab{{ forloop.index }} {% endfor %}' '{% for tab in include.tabs %}content {% endfor %}'"> | ||
{% for tab in include.tabs %} | ||
{%- assign tab_name = include.tab_names[forloop.index0] | markdownify | remove: '<p>' | remove: '</p>' %} | ||
{%- capture panel_id %}{{ tabbed_id }}-panel{{ forloop.index }}{% endcapture %} | ||
<input | ||
type="radio" | ||
name="{{ tabbed_id }}" | ||
id="{{ tabbed_id }}-tab{{ forloop.index }}" | ||
value="{{ tab_name | strip_html | slugify }}" | ||
tabindex="0" | ||
{% if forloop.first %}checked{% endif %}> | ||
<label for="{{ tabbed_id }}-tab{{ forloop.index }}" style="grid-area: tab{{ forloop.index }}">{{ tab_name }}</label> | ||
<div id="{{ panel_id }}" role="tabpanel"> | ||
{{ tab | markdownify | replace: '<VERSION>', '<span class="mod-version"><VERSION></span>' }} | ||
</div> | ||
{% endfor %} | ||
</fieldset> | ||
<script type="module"> | ||
import { init } from '/scripts/tabbed.mjs'; | ||
init(document.getElementById("{{ tabbed_id }}")); | ||
import { init } from '/scripts/tabbed.mjs'; | ||
init(document.getElementById("{{ tabbed_id }}")); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
function handleRequestTask(req) { | ||
return new Promise((resolve, reject) => { | ||
req.then(response => { | ||
if (response.ok) { | ||
resolve(response.json()); | ||
} else { | ||
reject(response); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* @typedef {Object} ModrinthVersion | ||
* @property {string} name | ||
* @property {string} version_number | ||
* @property {?string} changelog | ||
* @property {Object[]} dependencies | ||
* @property {string[]} game_versions | ||
* @property {string} version_type | ||
* @property {string[]} loaders | ||
* @property {boolean} featured | ||
* @property {string} id | ||
*/ | ||
/** | ||
* @typedef {Object} ModVersion | ||
* @property {string} name | ||
* @property {string} version | ||
* @property {string} modrinthId | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} McVersion | ||
* @property {string} id | ||
* @property {Date} releaseTime | ||
* @property {boolean} isSnapshot | ||
* @property {ModVersion[]} versions | ||
*/ | ||
/** | ||
* @param {string} modrinthProjectId | ||
* @returns {Promise<McVersion[]>} | ||
*/ | ||
async function getVersions(modrinthProjectId) { | ||
|
||
// start both requests in parallel for extra speed | ||
const pistonMetaTask = fetch('https://piston-meta.mojang.com/mc/game/version_manifest_v2.json'); | ||
const modrinthTask = fetch(`https://api.modrinth.com/v2/project/${modrinthProjectId}/version`); | ||
|
||
const modrinth = await handleRequestTask(modrinthTask); | ||
// sort versions by release date. this is probably™ fine as we split by MC version later | ||
modrinth.sort((a, b) => new Date(b.date_published) - new Date(a.date_published)); | ||
|
||
const pistonMeta = await handleRequestTask(pistonMetaTask).then(obj => { | ||
const map = new Map(); | ||
obj.versions.forEach(version => { | ||
map.set(version.id, version); | ||
}); | ||
return map; | ||
}); | ||
|
||
const versions = new Map(); | ||
modrinth.forEach(modrinthVersion => { | ||
modrinthVersion.game_versions.forEach(gameVersion => { | ||
if (!versions.has(gameVersion)) | ||
versions.set(gameVersion, { | ||
versions: [], | ||
}); | ||
|
||
const data = versions.get(gameVersion); | ||
|
||
data.versions.push({ version: modrinthVersion.version_number, name: modrinthVersion.name, modrinthId: modrinthVersion.id }); | ||
}); | ||
}); | ||
|
||
const versionsArray = Array.from(versions, ([id, data]) => ({ | ||
id, | ||
releaseTime: new Date(pistonMeta.get(id)?.releaseTime || 0), | ||
isSnapshot: pistonMeta.get(id)?.type !== 'release', | ||
versions: data.versions, | ||
})); | ||
|
||
versionsArray.sort((a, b) => b.releaseTime - a.releaseTime); | ||
return versionsArray; | ||
} | ||
|
||
/** | ||
* | ||
* @param versions | ||
* @returns {McVersion|undefined} | ||
*/ | ||
function pickDefaultVersion(versions) { | ||
const pinned = new URL(window.location.href).searchParams.get('version'); | ||
if (pinned) { | ||
const pinnedVersion = versions.find((v) => v.id === pinned); | ||
if (pinnedVersion) return pinnedVersion; | ||
} | ||
|
||
return versions[0]; | ||
} | ||
|
||
/** | ||
* | ||
* @param {string} modrinthProjectId | ||
* @returns {Promise<void>} | ||
*/ | ||
export async function setUpSmartBuildscript(modrinthProjectId) { | ||
function doReplace(version = 'VERSION') { | ||
document.querySelectorAll('.mod-version').forEach(e => { | ||
e.innerText = version; | ||
}); | ||
} | ||
getVersions(modrinthProjectId).then(versions => { | ||
const versionSelects = document.getElementsByClassName('mc-version-select'); | ||
function selectVersion(version, pin) { | ||
// update the window URL to include the selected version | ||
const state = history.state; | ||
const title = document.title; | ||
if (pin) { | ||
const url = new URL(window.location.href); | ||
url.searchParams.set('version', version.id); | ||
history.replaceState(state, title, url); | ||
} | ||
|
||
// replace the version in the buildscript | ||
doReplace(version?.versions[0]?.name); | ||
} | ||
for (const versionSelect of versionSelects) { | ||
versionSelect.addEventListener('change', () => { | ||
const version = versions.find(v => v.id === versionSelect.value); | ||
if (version) { | ||
selectVersion(version, true); | ||
} | ||
}); | ||
} | ||
function update() { | ||
const showPreReleases = document.getElementById('include-prereleases')?.checked || false; | ||
const validVersions = versions.filter(v => showPreReleases || !v.isSnapshot); | ||
|
||
const selectedVersion = pickDefaultVersion(validVersions); | ||
if (selectedVersion) { | ||
selectVersion(selectedVersion); | ||
} | ||
for (const versionSelect of versionSelects) { | ||
versionSelect.value = selectedVersion?.id; | ||
versionSelect.disabled = !selectedVersion; | ||
versionSelect.replaceChildren(...validVersions.map(v => { | ||
const option = document.createElement('option'); | ||
option.value = v.id; | ||
option.innerText = `Minecraft ${v.id}`; | ||
option.selected = v.id === selectedVersion?.id; | ||
return option; | ||
})); | ||
} | ||
} | ||
|
||
update(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters