diff --git a/.github/workflows/update-quick-start-module.yml b/.github/workflows/update-quick-start-module.yml
index bf6956011c9f..63ff008c38e1 100644
--- a/.github/workflows/update-quick-start-module.yml
+++ b/.github/workflows/update-quick-start-module.yml
@@ -7,16 +7,22 @@ on:
paths:
- .github/workflows/update-quick-start-module.yml
- scripts/gen_quick_start_module.py
+ - scripts/gen_additional_platform.py
- _includes/quick-start-module.js
- _includes/quick_start_local.html
+ - _includes/quick-start-additional-platform.js
+ - _additional_platform/*.json
push:
branches:
site
paths:
- .github/workflows/update-quick-start-module.yml
- scripts/gen_quick_start_module.py
+ - scripts/gen_additional_platform.py
- _includes/quick-start-module.js
- _includes/quick_start_local.html
+ - _includes/quick-start-additional-platform.js
+ - _additional_platform/*.json
workflow_dispatch:
jobs:
@@ -116,3 +122,40 @@ jobs:
body: >
This PR is auto-generated. It updates Getting Started page
labels: automated pr
+
+ update-additional-platform:
+ needs: [linux-nightly-matrix, windows-nightly-matrix, macos-arm64-nightly-matrix,
+ linux-release-matrix, windows-release-matrix, macos-arm64-release-matrix]
+ runs-on: "ubuntu-latest"
+ environment: pytorchbot-env
+ steps:
+ - name: Checkout pytorch.github.io
+ uses: actions/checkout@v2
+ - name: Setup Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.9
+ architecture: x64
+ - name: Generate quick-start-additional-platform.js
+ shell: bash
+ run: |
+ set -ex
+ python3 ./scripts/gen_additional_platform.py
+ - name: Create Issue if failed
+ uses: dacbd/create-issue-action@main
+ if: ${{ failure() }}
+ with:
+ title: Updating additional platform quick start module failed
+ token: ${{secrets.PYTORCHBOT_TOKEN}}
+ assignees: ${{github.actor}}
+ labels: bug
+ body: Updating additional platform quick start module failed, please fix the update script or check JSON files
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v3
+ with:
+ token: ${{ secrets.PYTORCHBOT_TOKEN }}
+ commit-message: Update quick-start-additional-platform.js
+ title: '[Additional Platform] Update quick-start-additional-platform.js'
+ body: >
+ This PR is auto-generated. It updates the Additional Platform Getting Started page
+ labels: automated pr
diff --git a/_get_started/get-started-additional-platform.md b/_get_started/get-started-additional-platform.md
new file mode 100644
index 000000000000..297019c671c7
--- /dev/null
+++ b/_get_started/get-started-additional-platform.md
@@ -0,0 +1,27 @@
+---
+layout: get_started
+title: Additional Platform
+permalink: /get-started/additional-platform/
+background-class: get-started-background
+body-class: get-started
+order: 1
+published: true
+get-started-additional: true
+---
+
+
+
+
+ {% include quick_start_additional_platform.html %}
+
+
+
+
+---
+
+
+
+
+
+
+
diff --git a/_get_started/get-started-locally.md b/_get_started/get-started-locally.md
index 6a95566a3946..361e9bffd244 100644
--- a/_get_started/get-started-locally.md
+++ b/_get_started/get-started-locally.md
@@ -20,6 +20,8 @@ redirect_from: "/get-started/"
+Could not find the right platform for your hardware? See the PyTorch Additional Platform page.
+
---
{% capture mac %}
diff --git a/_includes/quick-start-additional-platform.js b/_includes/quick-start-additional-platform.js
new file mode 100644
index 000000000000..d2bbd0fe64b5
--- /dev/null
+++ b/_includes/quick-start-additional-platform.js
@@ -0,0 +1,267 @@
+// =====================================================
+// Additional Platform Quick Start Module
+// =====================================================
+
+// Platform data loaded from JSON files (generated by gen_additional_platform.py)
+var ecosystemPlatformData = {{ platformData }};
+
+// HTML content loaded from _get_started/additional_platform/ directory
+// (pre-converted by Python script with syntax highlighting)
+var ecosystemHtmlContent = {{ markdownContent }};
+
+// Get platform IDs from loaded data
+var ecosystemPlatformIds = Object.keys(ecosystemPlatformData);
+
+// Ecosystem platform selections - simplified (no pm, no version)
+var ecosystemOpts = {
+ build: 'stable',
+ os: 'linux',
+ platform: null
+};
+
+// Parse URL parameters for pre-selection
+function parseUrlParams() {
+ var params = new URLSearchParams(window.location.search);
+ var platform = params.get('platform');
+ var build = params.get('build') || 'stable';
+ var os = params.get('os') || 'linux';
+
+ return {
+ platform: platform,
+ build: build,
+ os: os
+ };
+}
+
+// Apply URL parameter selections
+function applyUrlSelections() {
+ var urlParams = parseUrlParams();
+
+ // Apply build selection
+ if (urlParams.build && ecosystemOpts.build !== urlParams.build) {
+ ecosystemOpts.build = urlParams.build;
+ $('.pytorch-build > .option').removeClass('selected');
+ $('.pytorch-build > .option#' + urlParams.build).addClass('selected');
+ }
+
+ // Apply OS selection
+ if (urlParams.os && ecosystemOpts.os !== urlParams.os) {
+ ecosystemOpts.os = urlParams.os;
+ $('.os-ecosystem > .option').removeClass('selected');
+ $('.os-ecosystem > .option#' + urlParams.os).addClass('selected');
+ }
+
+ // Apply platform selection
+ if (urlParams.platform && ecosystemPlatformData[urlParams.platform]) {
+ ecosystemOpts.platform = urlParams.platform;
+ $('.compute-platform > .option').removeClass('selected');
+ $('.compute-platform > .option#' + urlParams.platform).addClass('selected');
+ updateEcosystemCommand();
+ updatePlatformContentDisplay();
+ }
+}
+
+// Initialize additional platform when document is ready
+$(function() {
+ initPlatformContentContainer();
+ initAdditionalPlatform();
+ initAdditionalPlatformButtons();
+ updatePlatformButtonStates();
+ syncComputePlatformHeight();
+ initPlatformContentDisplay();
+
+ // Apply URL parameter selections after initialization
+ applyUrlSelections();
+});
+
+// Initialize platform content container - dynamically create divs for each platform
+function initPlatformContentContainer() {
+ var container = $('#additional-platform-installation');
+ if (!container.length) return;
+
+ // Clear any existing static content
+ container.empty();
+
+ // Create platform content divs dynamically based on HTML content
+ ecosystemPlatformIds.forEach(function(platformId) {
+ if (ecosystemHtmlContent[platformId]) {
+ var contentDiv = $('');
+ // HTML content is already pre-converted with syntax highlighting
+ contentDiv.html(ecosystemHtmlContent[platformId]);
+ container.append(contentDiv);
+ }
+ });
+}
+
+// Note: Markdown is pre-converted to HTML by Python script (gen_additional_platform.py)
+// using markdown library with codehilite extension for syntax highlighting.
+// No need for client-side markdown parsing.
+
+// Initialize platform content display - hide all initially
+function initPlatformContentDisplay() {
+ $('#additional-platform-installation .platform-content').hide();
+}
+
+// Sync left heading height with right compute platform buttons height
+function syncComputePlatformHeight() {
+ var rightHeight = $('.compute-platform').outerHeight();
+ if (rightHeight > 0) {
+ $('.compute-platform-heading').css('min-height', rightHeight + 'px');
+ }
+}
+
+// Populate compute platform buttons
+function initAdditionalPlatformButtons() {
+ var platformRow = $('.compute-platform');
+ if (!platformRow.length) return;
+
+ // Generate platform buttons
+ ecosystemPlatformIds.forEach(function(platformId) {
+ var platform = ecosystemPlatformData[platformId];
+ if (!platform) return;
+ var displayName = platform.name;
+ var btn = $('');
+ platformRow.append(btn);
+ });
+
+ // Sync height after buttons are generated
+ syncComputePlatformHeight();
+
+ // Bind platform button click
+ $('.compute-platform > .option').on('click', function() {
+ var platformId = this.id;
+ var platform = ecosystemPlatformData[platformId];
+ if (!platform) return;
+
+ // Check if supported on current OS
+ var supportedOS = getSupportedOS(platformId);
+ if (!supportedOS.includes(ecosystemOpts.os)) {
+ $('#command').html('' + platform.name + ' is not supported on ' + ecosystemOpts.os + '');
+ return;
+ }
+
+ // Select this platform
+ $('.compute-platform > .option').removeClass('selected');
+ $(this).addClass('selected');
+ ecosystemOpts.platform = platformId;
+
+ updateEcosystemCommand();
+ updatePlatformContentDisplay();
+ });
+}
+
+// Get supported OS list from platform data structure
+function getSupportedOS(platformId) {
+ var platform = ecosystemPlatformData[platformId];
+ if (!platform) return [];
+
+ var osSet = new Set();
+ ['stable', 'preview'].forEach(function(build) {
+ if (platform[build]) {
+ Object.keys(platform[build]).forEach(function(os) {
+ osSet.add(os);
+ });
+ }
+ });
+ return Array.from(osSet);
+}
+
+// Update platform button states (disabled/enabled) based on OS
+function updatePlatformButtonStates() {
+ $('.compute-platform > .option').each(function() {
+ var platformId = this.id;
+ if (!platformId) return;
+
+ var supportedOS = getSupportedOS(platformId);
+ var isSupported = supportedOS.includes(ecosystemOpts.os);
+
+ if (isSupported) {
+ $(this).css('text-decoration', '');
+ } else {
+ $(this).css('text-decoration', 'line-through');
+ }
+ });
+
+ // If currently selected platform is not supported on new OS, deselect it
+ if (ecosystemOpts.platform) {
+ var supportedOS = getSupportedOS(ecosystemOpts.platform);
+ if (!supportedOS.includes(ecosystemOpts.os)) {
+ ecosystemOpts.platform = null;
+ $('.compute-platform > .option').removeClass('selected');
+ $('#command').html('Select a compute platform to see the installation command.');
+ updatePlatformContentDisplay();
+ }
+ }
+}
+
+// Update platform content display based on selected platform
+function updatePlatformContentDisplay() {
+ // Hide all platform content first
+ $('#additional-platform-installation .platform-content').hide();
+
+ // Show selected platform content
+ if (ecosystemOpts.platform) {
+ $('#additional-platform-installation .platform-content.' + ecosystemOpts.platform).show();
+ }
+}
+
+// Initialize all click events for build/os blocks
+function initAdditionalPlatform() {
+ // PyTorch Build
+ $('.pytorch-build > .option').on('click', function() {
+ $('.pytorch-build > .option').removeClass('selected');
+ $(this).addClass('selected');
+ ecosystemOpts.build = this.id;
+ updateEcosystemCommand();
+ });
+
+ // OS - with platform support check
+ $('.os-ecosystem > .option').on('click', function() {
+ $('.os-ecosystem > .option').removeClass('selected');
+ $(this).addClass('selected');
+ ecosystemOpts.os = this.id;
+
+ updatePlatformButtonStates();
+ updateEcosystemCommand();
+ });
+}
+
+// Update ecosystem command based on selections - simplified
+function updateEcosystemCommand() {
+ if (!ecosystemOpts.platform) {
+ $('#command').html('Select a compute platform to see the installation command.');
+ return;
+ }
+
+ var platform = ecosystemPlatformData[ecosystemOpts.platform];
+ if (!platform) {
+ $('#command').html('Loading platform data...');
+ return;
+ }
+
+ // Check if OS is supported
+ var supportedOS = getSupportedOS(ecosystemOpts.platform);
+ if (!supportedOS.includes(ecosystemOpts.os)) {
+ $('#command').html('' + platform.name + ' is not supported on ' + ecosystemOpts.os + '');
+ return;
+ }
+
+ // Get command directly from platform[build][os]
+ try {
+ var buildData = platform[ecosystemOpts.build];
+ if (!buildData || !buildData[ecosystemOpts.os]) {
+ $('#command').html('Configuration not available for this combination');
+ return;
+ }
+
+ var cmd = buildData[ecosystemOpts.os];
+
+ if (cmd) {
+ $('#command').html('' + cmd + '
');
+ } else {
+ $('#command').html('Configuration not available for this combination');
+ }
+ } catch (e) {
+ $('#command').html('Configuration not available for this combination');
+ }
+}
diff --git a/_includes/quick_start_additional_platform.html b/_includes/quick_start_additional_platform.html
new file mode 100644
index 000000000000..14f704c28b1a
--- /dev/null
+++ b/_includes/quick_start_additional_platform.html
@@ -0,0 +1,64 @@
+In the selector below, you will find compute platforms and configurations provided by our partners and community members. Choose your preferences and run the provided install command.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Select a compute platform to see the installation command.
+
+
+
+
diff --git a/_sass/get-started.scss b/_sass/get-started.scss
index ca3c335c41fe..a46dcd88614b 100644
--- a/_sass/get-started.scss
+++ b/_sass/get-started.scss
@@ -65,12 +65,12 @@
}
.get-started-nav-link {
- padding-left: rem(20px);
- padding-right: rem(20px);
+ padding-left: rem(10px);
+ padding-right: rem(10px);
@include desktop {
- padding-left: rem(30px);
- padding-right: rem(30px);
+ padding-left: rem(10px);
+ padding-right: rem(10px);
}
}
diff --git a/scripts/gen_additional_platform.py b/scripts/gen_additional_platform.py
new file mode 100644
index 000000000000..093d516c91f1
--- /dev/null
+++ b/scripts/gen_additional_platform.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+"""
+Generates additional platform quick start module for
+https://pytorch.org/get-started/additional-platform/ page.
+
+This script reads all JSON files from _additional_platform/ directory,
+combines them, and generates the quick-start-additional-platform.js file.
+It also reads markdown files from _get_started/additional_platform/ directory
+and embeds them for dynamic content loading.
+
+Usage:
+ python3 scripts/gen_additional_platform.py
+
+The script will:
+1. Read all JSON files from _additional_platform/ directory
+2. Read all MD files from _get_started/additional_platform/ directory
+3. Combine platform data into a single object (keyed by filename)
+4. Replace template placeholders in _includes/quick-start-additional-platform.js
+5. Output the result to assets/quick-start-additional-platform.js
+"""
+
+import json
+from pathlib import Path
+from typing import Dict, Any
+import markdown
+from markdown.extensions.codehilite import CodeHiliteExtension
+import re
+
+BASE_DIR = Path(__file__).parent.parent
+ADDITIONAL_PLATFORM_DIR = BASE_DIR / "_additional_platform"
+MARKDOWN_DIR = BASE_DIR / "_get_started" / "additional_platform"
+INCLUDES_DIR = BASE_DIR / "_includes"
+ASSETS_DIR = BASE_DIR / "assets"
+
+
+def read_platform_json_files() -> Dict[str, Any]:
+ """Read all JSON files from _additional_platform directory."""
+ platform_data = {}
+
+ if not ADDITIONAL_PLATFORM_DIR.exists():
+ print(f"Warning: {ADDITIONAL_PLATFORM_DIR} does not exist")
+ return platform_data
+
+ for json_file in ADDITIONAL_PLATFORM_DIR.glob("*.json"):
+ try:
+ content = json_file.read_text()
+ data = json.loads(content)
+ # Use filename (without .json) as platform_id
+ platform_id = json_file.stem
+ platform_data[platform_id] = data
+ print(f"Loaded platform: {platform_id} from {json_file.name}")
+ except json.JSONDecodeError as e:
+ print(f"Error parsing {json_file.name}: {e}")
+
+ return platform_data
+
+
+def convert_markdown_to_html(markdown_text: str) -> str:
+ """Convert markdown to HTML with syntax highlighting.
+
+ Uses Python markdown library with codehilite extension for syntax highlighting.
+ This produces HTML similar to Jekyll's markdownify filter.
+ """
+ # Remove Jekyll/Kramdown special syntax (e.g., {:.no_toc}, {: #id})
+ html_text = re.sub(r'\{:[^}]*\}', '', markdown_text)
+
+ # Convert markdown to HTML with codehilite extension
+ # Codehilite uses Pygments for syntax highlighting (similar to Rouge used by Jekyll)
+ md = markdown.Markdown(extensions=[
+ CodeHiliteExtension(
+ css_class='highlight',
+ guess_lang=False,
+ linenums=False
+ ),
+ 'fenced_code',
+ 'tables',
+ 'toc'
+ ])
+
+ html = md.convert(html_text)
+ return html
+
+
+def read_markdown_files() -> Dict[str, str]:
+ """Read all markdown files from _get_started/additional_platform directory
+ and convert them to HTML with syntax highlighting."""
+ html_content = {}
+
+ if not MARKDOWN_DIR.exists():
+ print(f"Warning: {MARKDOWN_DIR} does not exist")
+ return html_content
+
+ for md_file in MARKDOWN_DIR.glob("*.md"):
+ try:
+ content = md_file.read_text()
+ # Use filename (without .md) as platform_id
+ platform_id = md_file.stem
+ # Convert markdown to HTML with syntax highlighting
+ html = convert_markdown_to_html(content)
+ html_content[platform_id] = html
+ print(f"Loaded and converted markdown: {platform_id} from {md_file.name}")
+ except Exception as e:
+ print(f"Error reading {md_file.name}: {e}")
+
+ return html_content
+
+
+def read_template() -> str:
+ """Read the JS template file."""
+ template_path = INCLUDES_DIR / "quick-start-additional-platform.js"
+ if not template_path.exists():
+ raise FileNotFoundError(f"Template file not found: {template_path}")
+ return template_path.read_text()
+
+
+def generate_js_output(platform_data: Dict[str, Any], markdown_content: Dict[str, str]) -> str:
+ """Generate the final JS file by replacing template placeholders."""
+ template = read_template()
+
+ # Replace placeholders
+ template = template.replace("{{ platformData }}", json.dumps(platform_data, indent=2))
+ # Now embedding pre-converted HTML content instead of raw markdown
+ template = template.replace("{{ markdownContent }}", json.dumps(markdown_content, indent=2))
+
+ return template
+
+
+def write_output(content: str) -> None:
+ """Write the generated JS to assets directory."""
+ output_path = ASSETS_DIR / "quick-start-additional-platform.js"
+ output_path.write_text(content)
+ print(f"Generated: {output_path}")
+
+
+def main():
+ """Main entry point."""
+ print("Generating additional platform quick start module...")
+
+ # Read all platform JSON files
+ platform_data = read_platform_json_files()
+
+ if not platform_data:
+ print("No platform data found. Creating empty output.")
+ platform_data = {}
+
+ # Read all markdown files
+ markdown_content = read_markdown_files()
+
+ if not markdown_content:
+ print("No markdown content found.")
+ markdown_content = {}
+
+ # Generate JS output
+ js_content = generate_js_output(platform_data, markdown_content)
+
+ # Write to assets directory
+ write_output(js_content)
+
+ print("Done!")
+
+
+if __name__ == "__main__":
+ main()