From 2e7e741de5f9133ae8fb44ace605352cff88f6e4 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Mon, 15 Dec 2025 12:19:04 +0100 Subject: [PATCH] feat: add release selector for getting-started.md --- docs/css/release-selector.css | 166 +++++++++++++++ docs/documentation/getting-started.md | 63 ++++-- docs/index.md | 29 --- docs/javascripts/release-selector.js | 295 ++++++++++++++++++++++++++ mkdocs.yml | 3 + 5 files changed, 509 insertions(+), 47 deletions(-) create mode 100644 docs/css/release-selector.css create mode 100644 docs/javascripts/release-selector.js diff --git a/docs/css/release-selector.css b/docs/css/release-selector.css new file mode 100644 index 0000000..7fe5dc9 --- /dev/null +++ b/docs/css/release-selector.css @@ -0,0 +1,166 @@ +.release-selector-container { + background: var(--md-default-bg-color); + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 8px; + padding: 1.5rem; + margin: 1rem 0; +} + +.release-selector-container h3 { + margin-top: 0; + margin-bottom: 1rem; + color: var(--md-default-fg-color); +} + +.selector-row { + display: flex; + flex-wrap: wrap; + gap: 1rem; + margin-bottom: 1rem; +} + +.selector-group { + flex: 1; + min-width: 200px; +} + +.selector-group label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + color: var(--md-default-fg-color); +} + +.selector-group select { + width: 100%; + padding: 0.5rem; + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 4px; + background: var(--md-default-bg-color); + color: var(--md-default-fg-color); + font-size: 0.9rem; +} + +.selector-group select:focus { + outline: none; + border-color: var(--md-primary-fg-color); + box-shadow: 0 0 0 2px var(--md-primary-fg-color--light); +} + +.selector-group input[type="checkbox"] { + margin-right: 0.5rem; +} + +#download-results { + margin-top: 1.5rem; +} + +.release-group { + margin-bottom: 1.5rem; + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 6px; + overflow: hidden; +} + +.release-group h4 { + margin: 0; + padding: 0.75rem 1rem; + background: var(--md-default-fg-color--lightest); + color: var(--md-default-fg-color); + font-size: 1rem; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.prerelease-badge { + background: var(--md-accent-fg-color); + color: white; + padding: 0.2rem 0.5rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 500; +} + +.release-date { + margin-left: auto; + font-size: 0.85rem; + opacity: 0.7; +} + +.download-links { + padding: 1rem; +} + +.download-link { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + margin-bottom: 0.5rem; + background: var(--md-code-bg-color); + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 4px; + text-decoration: none; + color: var(--md-default-fg-color); + transition: all 0.2s ease; +} + +.download-link:hover { + background: var(--md-primary-fg-color--light); + border-color: var(--md-primary-fg-color); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.download-link:last-child { + margin-bottom: 0; +} + +.download-icon { + font-size: 1.2rem; +} + +.download-details { + margin-left: auto; + font-size: 0.85rem; + opacity: 0.7; +} + +.no-results { + text-align: center; + padding: 2rem; + color: var(--md-default-fg-color--light); + font-style: italic; +} + +/* Responsive design */ +@media (max-width: 768px) { + .selector-row { + flex-direction: column; + } + + .selector-group { + min-width: unset; + } + + .release-group h4 { + flex-direction: column; + align-items: flex-start; + gap: 0.25rem; + } + + .release-date { + margin-left: 0; + } + + .download-link { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .download-details { + margin-left: 0; + } +} \ No newline at end of file diff --git a/docs/documentation/getting-started.md b/docs/documentation/getting-started.md index 331847d..cf97e8d 100644 --- a/docs/documentation/getting-started.md +++ b/docs/documentation/getting-started.md @@ -1,20 +1,44 @@ -1. [Download the `editor`](https://github.com/godotjs/GodotJS/releases) based on your OS and select an JS engine (we recommend `v8` for a start) and unzip it -2. Rename the downloaded file based on your OS: - - Linux: `godot.linuxbsd.editor.x86_64` ➡️ `godot` - - MacOS: no rename required - - Windows: `godot.windows.editor.x86_64.exe` ➡️ `godot.exe` + +## Download GodotJS +Choose your platform and preferences to download the latest GodotJS release: + +
+ + +> **Note:** The `Godot.app` isn't signed for MacOS you need +> to [allow to open it](https://support.apple.com/en-us/102445#:~:text=If%20you%20want%20to%20open%20an%20app%20that%20hasn%E2%80%99t%20been%20notarized%20or%20is%20from%20an%20unidentified%20developer). + + +### Manual Installation + +If you prefer to browse all releases manually, visit the [GitHub Releases page](https://github.com/godotjs/GodotJS/releases). + +### Installation Instructions + +After downloading: + +1. Extract the downloaded zip file +2. Rename the executable based on your OS: + - **Linux**: `godot.linuxbsd.editor.x86_64` → `godot` + - **macOS**: No rename required + - **Windows**: `godot.windows.editor.x86_64.exe` → `godot.exe` 3. [Add Godot to your PATH](https://docs.godotengine.org/en/stable/tutorials/editor/command_line_tutorial.html#path) - - Linux: `/usr/local/bin` - - MacOS: `echo ~/your-path/Godot.app/Contents/MacOS|sudo tee /etc/paths.d/godot;bash -l;echo $PATH` - - Windows: `setx /M path "%path%;C:\your-path\windows-editor-v8"` -4. Open a terminal -5. Test if you can use Godot via terminal and run: - -```shell -godot --version -``` +4. Test the installation by running `godot --version` in your terminal + +### JS Engine Comparison + +| Engine | Performance | Memory Usage | Platform Support | Recommended For | +|--------------------|-------------|--------------|------------------|--------------------------| +| **V8** | High | Higher | Desktop | Development & Production | +| **QuickJS** | Medium | Lower | All platforms | Mobile & Embedded | +| **JavaScriptCore** | High | Medium | macOS/iOS | Apple platforms | +| **Browser** | High | Lower | Web | Web | + +### Target Types -> **Note:** The `Godot.app` isn't signed for MacOS you need to [allow to open it](https://support.apple.com/en-us/102445#:~:text=If%20you%20want%20to%20open%20an%20app%20that%20hasn%E2%80%99t%20been%20notarized%20or%20is%20from%20an%20unidentified%20developer). +- **Editor**: Full Godot editor with GodotJS support +- **Template**: Export templates for building your games +- **Debug**: Debug versions with additional logging and debugging features ## Create a new project @@ -25,14 +49,16 @@ godot --version 3. Run `cd ` 4. Run `npm i` 5. Run `npm run dev` - this will enable typescript watch mode and opens the editor -6. Inside the editor [install preset files](#install-preset-files) via `Project > Tools > GodotJS > Install Preset files` +6. Inside the editor [install preset files](#install-preset-files) via + `Project > Tools > GodotJS > Install Preset files` 7. Click `OK` to confirm a list of files will be generated in the project. 8. Attach the `example.ts` script to a node and run the project ### Manually 1. Run `godot -p` and create a new project -2. Inside the editor [install preset files](#install-preset-files) via `Project > Tools > GodotJS > Install Preset files` +2. Inside the editor [install preset files](#install-preset-files) via + `Project > Tools > GodotJS > Install Preset files` 3. Click `OK` to confirm a list of files will be generated in the project. 4. Run `cd ` 5. Run `npm i` @@ -69,6 +95,7 @@ npx tsc npx tsc -w ``` -Also, you can simply click the tool button on _GodotJS_ bottom panel in the godot editor. It'll do the same thing for you. +Also, you can simply click the tool button on _GodotJS_ bottom panel in the godot editor. It'll do the same thing for +you. ![TSC Watch](images/tsproj_tsc_watch.png) diff --git a/docs/index.md b/docs/index.md index 4c10443..88d3f70 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,12 +9,6 @@ hide: **_-- TypeScript/JavaScript Support for Godot 4.x by leveraging the high-performance capabilities of V8 to bring the delightful development experience of TypeScript into Godot. --_** -Supports JavaScript engines: - -- V8 -- QuickJS -- JavaScriptCore -- Directly run scripts on the host browser JS VM when porting to web. ![typescript_intellisence](images/typescript_intellisence.png) @@ -34,29 +28,6 @@ Read the [getting-started](documentation/getting-started.md). - [Worker threads](documentation/experimental/worker.md) (limited support) (**experimental**) - Asynchronously loaded modules (limited support) (_temporarily only available in v8.impl, quickjs.impl_) -## Getting the engine - -No installation or setup necessary. -The binaries for download are the complete, usable Godot editor -and engine with JavaScript/TypeScript language support. - -### Binary downloads - -Download the binaries from the [Releases](https://github.com/godotjs/GodotJS/releases). - -### Choose your engine - -Before initiating, make sure to select the JavaScript runtime you prefer between `v8`, `QuickJS` and `Web` (See [Supported Platforms](#supported-platforms)): - -- `v8` is proven to be one of the most powerful and high-performance JavaScript runtimes. -- `QuickJS` is a remarkable and lightweight option. -- `JavaScriptCore` is the built-in JavaScript engine for WebKit and bundled with macOS/iOS. -- `Web` is only suitable when building for Web. All scripts run on the host browser JS VM rather than an additional interpreter. - -### Building from source - -In some cases you want or need to build the engine from source. -Read the [Building from Source](documentation/building-from-source/) documentation in this case. ## Examples diff --git a/docs/javascripts/release-selector.js b/docs/javascripts/release-selector.js new file mode 100644 index 0000000..b03cab5 --- /dev/null +++ b/docs/javascripts/release-selector.js @@ -0,0 +1,295 @@ +class ReleaseSelector { + constructor() { + this.releases = []; + this.assets = []; + this.init(); + + this.osNames = { + windows: "Windows", + linux: "Linux", + macos: "macOS", + android: "Android", + ios: "iOS", + "web-nothreads": "Web (No Threads)", + web: "Web", + }; + + this.engines = { + v8: "V8", + "qjs-ng": "QuickJS NG", + }; + + this.targets = { + editor: "Editor", + "template-release": "Release Template", + "template-debug": "Debug Template", + }; + } + + async init() { + await this.fetchReleases(); + this.renderSelectors(); + this.bindEvents(); + } + + async fetchReleases() { + try { + const response = await fetch( + "https://api.github.com/repos/godotjs/GodotJS/releases", + ); + this.releases = await response.json(); + this.parseAssets(); + } catch (error) { + console.error("Failed to fetch releases:", error); + } + } + + parseAssets() { + this.assets = []; + + this.releases.forEach((release) => { + release.assets.forEach((asset) => { + const os = Object.keys(this.osNames).find((key) => + asset.name.includes(key), + ); + const jsEngine = Object.keys(this.engines).find((key) => + asset.name.includes(key), + ); + const target = Object.keys(this.targets).find((key) => + asset.name.includes(key), + ); + + this.assets.push({ + name: asset.name, + downloadUrl: asset.browser_download_url, + os: os, + target: target, + jsEngine: jsEngine, + releaseTag: release.tag_name, + releaseDate: release.published_at, + isPrerelease: release.prerelease, + }); + }); + }); + } + + getUniqueValues(key, filters = {}) { + const filteredAssets = this.getFilteredAssets(filters); + return [...new Set(filteredAssets.map((asset) => asset[key]))].sort(); + } + + getFilteredAssets(filters) { + return this.assets.filter((asset) => { + return Object.entries(filters).every( + ([key, value]) => !value || asset[key] === value, + ); + }); + } + + renderSelectors() { + const container = document.getElementById("release-selector"); + if (!container) return; + + const osOptions = this.getUniqueValues("os"); + const targetOptions = this.getUniqueValues("target"); + const jsEngineOptions = this.getUniqueValues("jsEngine"); + + container.innerHTML = ` +
+

Download GodotJS

+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ +
+
+ +
+
+ `; + } + + formatOSName(os) { + return this.osNames[os] || os; + } + + formatEngineName(engine) { + return this.engines[engine] || engine; + } + + formatTargetName(target) { + return ( + this.targets[target] || + target.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) + ); + } + + bindEvents() { + const osSelect = document.getElementById("os-select"); + const targetSelect = document.getElementById("target-select"); + const engineSelect = document.getElementById("engine-select"); + const prereleaseCheckbox = document.getElementById("include-prerelease"); + + if (osSelect) { + osSelect.addEventListener("change", () => { + this.updateTargetOptions(); + this.updateResults(); + }); + } + + [targetSelect, engineSelect, prereleaseCheckbox].forEach( + (element) => { + if (element) { + element.addEventListener("change", () => this.updateResults()); + } + }, + ); + + // Set default values + if (osSelect) osSelect.value = this.detectOS(); + this.updateTargetOptions(); + if (targetSelect) targetSelect.value = "editor"; + if (engineSelect) engineSelect.value = "v8"; + + this.updateResults(); + } + + detectOS() { + const userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.includes("win")) return "windows"; + if (userAgent.includes("mac")) return "macos"; + if (userAgent.includes("linux")) return "linux"; + return "windows"; // default + } + + updateTargetOptions() { + const osSelect = document.getElementById("os-select"); + const targetSelect = document.getElementById("target-select"); + + if (!osSelect || !targetSelect) return; + + const selectedOS = osSelect.value; + const currentTarget = targetSelect.value; + + const availableTargets = this.getUniqueValues("target", { os: selectedOS }); + + targetSelect.innerHTML = ` + + ${availableTargets.map((target) => ``).join("")} + `; + + // Restore selection if still available + if (availableTargets.includes(currentTarget)) { + targetSelect.value = currentTarget; + } + } + + updateResults() { + const filters = { + os: document.getElementById("os-select")?.value || "", + target: document.getElementById("target-select")?.value || "", + jsEngine: document.getElementById("engine-select")?.value || "", + }; + + const includePrerelease = + document.getElementById("include-prerelease")?.checked || false; + + let filteredAssets = this.getFilteredAssets(filters); + + if (!includePrerelease) { + filteredAssets = filteredAssets.filter((asset) => !asset.isPrerelease); + } + + // Group by release and sort by date (newest first) + const groupedAssets = {}; + filteredAssets.forEach((asset) => { + if (!groupedAssets[asset.releaseTag]) { + groupedAssets[asset.releaseTag] = []; + } + groupedAssets[asset.releaseTag].push(asset); + }); + + const sortedReleases = Object.keys(groupedAssets).sort((a, b) => { + const releaseA = this.releases.find((r) => r.tag_name === a); + const releaseB = this.releases.find((r) => r.tag_name === b); + return new Date(releaseB.published_at) - new Date(releaseA.published_at); + }); + + this.renderResults(groupedAssets, sortedReleases); + } + + renderResults(groupedAssets, sortedReleases) { + const resultsContainer = document.getElementById("download-results"); + if (!resultsContainer) return; + + if (sortedReleases.length === 0) { + resultsContainer.innerHTML = + '

No releases found matching your criteria.

'; + return; + } + + const html = sortedReleases + .map((releaseTag) => { + const assets = groupedAssets[releaseTag]; + const release = this.releases.find((r) => r.tag_name === releaseTag); + + return ` +
+

+ ${releaseTag} + ${release.prerelease ? 'Pre-release' : ""} + ${new Date(release.published_at).toLocaleDateString()} +

+ +
+ `; + }) + .join(""); + + resultsContainer.innerHTML = html; + } +} + +// Initialize when DOM is loaded +document.addEventListener("DOMContentLoaded", () => { + new ReleaseSelector(); +}); diff --git a/mkdocs.yml b/mkdocs.yml index 41d2509..171b04e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,6 +5,9 @@ repo_url: https://github.com/godotjs/GodotJS site_description: JS/TS language binding for Godot extra_css: - css/extra.css + - css/release-selector.css +extra_javascript: + - javascripts/release-selector.js nav: - Home: index.md - Docs: