Skip to content

Commit

Permalink
Merge pull request #75 from Ladysnake/dev/cca-version-select
Browse files Browse the repository at this point in the history
add version selector for CCA developer wiki
  • Loading branch information
Pyrofab authored Dec 31, 2023
2 parents ae35533 + 5b47b3f commit c342bca
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 14 deletions.
35 changes: 22 additions & 13 deletions _includes/tabbed.liquid
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: '&lt;VERSION&gt;', '<span class="mod-version">&lt;VERSION&gt;</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>
7 changes: 7 additions & 0 deletions _sass/parts/buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@ textarea {
color: inherit;
}

select {
padding: 0.2em 1.2em;
background-color: var(--button-background);
border: 0.14em solid var(--button-outline);
border-radius: 0.5em;
}

button.rounded {
border-radius: 0.6em;
}
158 changes: 158 additions & 0 deletions scripts/modrinth-api.js
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();
});
}
11 changes: 10 additions & 1 deletion wiki/cardinal-components-api/dev-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ mechanism provided by the Fabric toolchain to include Cardinal Components in you

Unless specified otherwise, the following block must be added to your `build.gradle` **after** the relevant `repositories` block:

<label for="select-mcversion">Select a Minecraft Version:</label>
<select id="select-mcversion" class="mc-version-select" name="select-mcversion" disabled>
<option>Loading...</option>
</select>
<script type="module">
import * as ModrinthApi from '/scripts/modrinth-api.js';
ModrinthApi.setUpSmartBuildscript("K01OU20C");
</script>

{% capture groovy %}
`gradle.properties`:
```properties
Expand Down Expand Up @@ -157,4 +166,4 @@ as an *embedded library* of your project, for documentation purposes and to make

Modrinth is also a platform for distributing mods to users, which can also be used as a maven repository by following [the instructions on their website](https://docs.modrinth.com/docs/tutorials/maven/).

Same as with Curseforge, you are encouraged to declare [Cardinal Components API](https://modrinth.com/mod/cardinal-components-api/) as an "Embedded" dependency.
Same as with Curseforge, you are encouraged to declare [Cardinal Components API](https://modrinth.com/mod/cardinal-components-api/) as an "Embedded" dependency.

0 comments on commit c342bca

Please sign in to comment.