diff --git a/docusaurus.config.js b/docusaurus.config.js index 2a6c311..2bfb813 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -104,6 +104,11 @@ deploymentBranch: 'gh-pages', position: 'left', label: 'الدروس', }, + { + to: '/download', + position: 'left', + label: 'تنزيل', + }, // {to: '/blog', label: 'المدونة', position: 'left'}, { href: 'https://github.com/daadLang', diff --git a/src/css/custom.css b/src/css/custom.css index 951974b..0a638cc 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -4,6 +4,38 @@ * work well for content-centric websites. */ +@font-face { + font-family: 'DG Heaven'; + src: url('../../static/font/DG-Heaven-Thin.ttf') format('truetype'); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: 'DG Heaven'; + src: url('../../static/font/DG-Heaven-Thin.ttf') format('truetype'); + font-style: normal; + font-weight: 700; + font-display: swap; +} + +@font-face { + font-family: 'TheYearofTheCamel'; + src: url('../../static/font/TheYearofTheCamel-Regular.otf') format('opentype'); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: 'TheYearofTheCamel'; + src: url('../../static/font/TheYearofTheCamel-Regular.otf') format('opentype'); + font-style: normal; + font-weight: 700; + font-display: swap; +} + /* You can override the default Infima variables here. */ :root { --ifm-color-primary: #2e8555; @@ -15,6 +47,9 @@ --ifm-color-primary-lightest: #3cad6e; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + --ifm-font-family-base: 'TheYearofTheCamel', 'Segoe UI', Tahoma, sans-serif; + --ifm-heading-font-family: 'DG Heaven', 'Segoe UI', Tahoma, sans-serif; + --ifm-font-family-monospace: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace; } /* For readability concerns, you should choose a lighter palette in dark mode. */ @@ -33,6 +68,30 @@ html, body { direction: rtl !important; text-align: right; + font-family: 'TheYearofTheCamel', 'Segoe UI', Tahoma, sans-serif; +} + +body, +button, +input, +textarea, +select, +p, +a, +li, +label, +span, +div { + font-family: 'TheYearofTheCamel', 'Segoe UI', Tahoma, sans-serif; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: 'DG Heaven', 'Segoe UI', Tahoma, sans-serif; } /* Ensure code blocks preserve direction where needed */ @@ -118,4 +177,4 @@ pre, code, .markdown, .theme-doc-markdown { text-align: center; gap: 0.5rem; } -} \ No newline at end of file +} diff --git a/src/pages/download.js b/src/pages/download.js index 788fe5a..d8b6af6 100644 --- a/src/pages/download.js +++ b/src/pages/download.js @@ -1,244 +1,588 @@ -import React, {useMemo, useState, useEffect} from 'react'; +import React, {useEffect, useMemo, useState} from 'react'; import Layout from '@theme/Layout'; -import useBaseUrl from '@docusaurus/useBaseUrl'; import Link from '@docusaurus/Link'; +import styles from './download.module.css'; -// A modern download page: latest release summary, release selector, platform cards - -const EXAMPLE_RELEASES = [ - { - id: 1, - tag_name: 'v0.2.0', - name: 'إصدار 0.2.0', - published_at: '2026-01-15', - assets: [ - { name: 'daad-0.2.0-windows-installer.exe', browser_download_url: 'https://example.com/downloads/daad-0.2.0-windows-installer.exe' }, - { name: 'daad-0.2.0-mac.dmg', browser_download_url: 'https://example.com/downloads/daad-0.2.0-mac.dmg' }, - { name: 'daad-0.2.0-linux.AppImage', browser_download_url: 'https://example.com/downloads/daad-0.2.0-linux.AppImage' }, - { name: 'daad-0.2.0-lang.zip', browser_download_url: 'https://example.com/downloads/daad-0.2.0-lang.zip' }, - { name: 'daad-0.2.0-ide.zip', browser_download_url: 'https://example.com/downloads/daad-0.2.0-ide.zip' }, - ], - }, - { - id: 2, - tag_name: 'v0.1.0', - name: 'الإصدار التجريبي 0.1.0', - published_at: '2025-12-01', - assets: [ - { name: 'daad-0.1.0.zip', browser_download_url: 'https://example.com/downloads/daad-0.1.0.zip' }, - ], - }, +const GITHUB_API = { + language: 'https://api.github.com/repos/daadLang/daad/releases/latest', + editor: 'https://api.github.com/repos/daadLang/d-editor/releases/latest', +}; + +const RELEASE_LINKS = { + languageAll: 'https://github.com/daadLang/daad/releases', + editorAll: 'https://github.com/daadLang/d-editor/releases', +}; + +const OS_LIST = [ + {key: 'windows', label: 'ويندوز'}, + {key: 'macos', label: 'ماك'}, + {key: 'linux', label: 'لينكس'}, + {key: 'android', label: 'أندرويد'}, + {key: 'ios', label: 'iOS'}, ]; -function detectPlatform() { - if (typeof navigator === 'undefined') return 'linux'; - const p = navigator.platform.toLowerCase(); - if (p.includes('win')) return 'windows'; - if (p.includes('mac') || p.includes('darwin')) return 'mac'; - if (p.includes('linux')) return 'linux'; - return 'linux'; +const DESKTOP_OS_KEYS = new Set(['windows', 'macos', 'linux']); +const MOBILE_OS_KEYS = new Set(['android', 'ios']); + +function prioritizeDetectedOS(osList, detectedKey) { + if (!detectedKey || detectedKey === 'unknown') return osList; + const detected = osList.find((os) => os.key === detectedKey); + if (!detected) return osList; + return [detected, ...osList.filter((os) => os.key !== detectedKey)]; +} + +const OS_TECH_LABEL = { + windows: 'Windows', + macos: 'macOS', + linux: 'Linux', + android: 'Android', + ios: 'iOS', + unknown: 'Unknown', +}; + +function isMobileOS(os) { + return os === 'android' || os === 'ios'; +} + +function normalizePlatform(raw) { + const value = String(raw || '').toLowerCase(); + if (value.includes('win')) return 'windows'; + if (value.includes('mac') || value.includes('darwin')) return 'macos'; + if (value.includes('android')) return 'android'; + if (value.includes('iphone') || value.includes('ipad') || value.includes('ipod') || value.includes('ios')) return 'ios'; + if (value.includes('linux') || value.includes('x11')) return 'linux'; + return 'unknown'; +} + +function normalizeArch(raw) { + const value = String(raw || '').toLowerCase(); + if (value.includes('arm64') || value.includes('aarch64')) return 'arm64'; + if (value.includes('arm')) return 'arm'; + if (value.includes('x64') || value.includes('x86_64') || value.includes('amd64') || value.includes('win64')) return 'x64'; + if (value.includes('x86') || value.includes('i386') || value.includes('i686') || value.includes('win32')) return 'x86'; + return 'unknown'; +} + +function detectClient() { + if (typeof navigator === 'undefined') { + return {os: 'unknown', arch: 'unknown'}; + } + + const osSource = navigator.userAgentData?.platform || `${navigator.platform} ${navigator.userAgent}`; + const archSource = navigator.userAgentData?.architecture || `${navigator.platform} ${navigator.userAgent}`; + + return { + os: normalizePlatform(osSource), + arch: normalizeArch(archSource), + }; +} + +function stageLabel(tag) { + const t = String(tag || '').toLowerCase(); + if (t.includes('beta')) return 'Beta'; + if (t.includes('alpha')) return 'Alpha'; + if (t.includes('rc')) return 'RC'; + return 'Stable'; +} + +function archLabel(value) { + if (value === 'x64') return 'x64'; + if (value === 'x86') return 'x86'; + if (value === 'arm64') return 'ARM64'; + if (value === 'arm') return 'ARM'; + return 'Universal'; +} + +function detectArchFromName(name) { + const n = String(name || '').toLowerCase(); + if (/(x64|x86_64|amd64)/.test(n)) return 'x64'; + if (/(x86|i386|i686)/.test(n)) return 'x86'; + if (/(arm64|aarch64)/.test(n)) return 'arm64'; + if (/\barm\b/.test(n)) return 'arm'; + return 'unknown'; +} + +function fileTypeLabel(name) { + const n = name.toLowerCase(); + if (n.endsWith('.appimage')) return 'AppImage'; + if (n.endsWith('.apk')) return 'APK (Alpine)'; + if (n.endsWith('.deb')) return 'DEB'; + if (n.endsWith('.rpm')) return 'RPM'; + if (n.endsWith('.tar.gz')) return 'TAR.GZ'; + if (n.endsWith('.tar.xz')) return 'TAR.XZ'; + if (n.endsWith('.exe')) return 'EXE'; + if (n.endsWith('.msi')) return 'MSI'; + if (n.endsWith('.dmg')) return 'DMG'; + if (n.endsWith('.pkg')) return 'PKG'; + if (n.endsWith('.ipa')) return 'IPA'; + if (n.endsWith('.zip')) return 'ZIP'; + return 'File'; +} + +function hasAny(text, patterns) { + return patterns.some((p) => text.includes(p)); +} + +function detectAssetPlatform(name) { + const n = name.toLowerCase(); + if (hasAny(n, ['windows_', 'windows-', '_windows', '-windows', 'win-'])) return 'windows'; + if (hasAny(n, ['darwin_', 'darwin-', '_darwin', '-darwin', 'mac', 'osx'])) return 'macos'; + if (hasAny(n, ['linux_', 'linux-', '_linux', '-linux'])) return 'linux'; + if (hasAny(n, ['android', 'aab', '.apk']) && !hasAny(n, ['linux_', 'linux-'])) return 'android'; + if (hasAny(n, ['ios', 'iphone', 'ipad', '.ipa'])) return 'ios'; + return 'unknown'; +} + +function isCompatibleEditorAsset(assetName, os) { + const n = assetName.toLowerCase(); + const platform = detectAssetPlatform(assetName); + + if (/sha256|checksums?|\.sig$|\.txt$/.test(n)) return false; + + if (os === 'windows') return platform === 'windows' && (n.endsWith('.exe') || n.endsWith('.msi')); + + if (os === 'macos') { + return platform === 'macos' && (n.endsWith('.dmg') || n.endsWith('.pkg') || n.endsWith('.zip') || n.endsWith('.tar.gz')); + } + + if (os === 'linux') { + return platform === 'linux' && (n.endsWith('.appimage') || n.endsWith('.deb') || n.endsWith('.rpm') || n.endsWith('.tar.gz') || n.endsWith('.tar.xz')); + } + + if (os === 'android') return platform === 'android' && (n.endsWith('.apk') || n.endsWith('.aab')); + + if (os === 'ios') return platform === 'ios' && n.endsWith('.ipa'); + + return false; +} + +function isCompatibleCliAsset(name, os) { + const n = name.toLowerCase(); + if (/sha256|checksums?|\.sig$|\.txt$/.test(n)) return false; + const platform = detectAssetPlatform(name); + + if (os === 'windows') return platform === 'windows' && n.endsWith('.zip'); + if (os === 'macos') return platform === 'macos' && (n.endsWith('.tar.gz') || n.endsWith('.zip') || n.endsWith('.tar.xz')); + if (os === 'linux') return platform === 'linux' && (n.endsWith('.apk') || n.endsWith('.deb') || n.endsWith('.rpm') || n.endsWith('.tar.gz') || n.endsWith('.tar.xz')); + if (os === 'android') return platform === 'android' && (n.endsWith('.apk') || n.endsWith('.aab')); + if (os === 'ios') return platform === 'ios' && n.endsWith('.ipa'); + + return false; +} + +function archScore(name, arch) { + const n = name.toLowerCase(); + if (arch === 'x64' && /(x64|x86_64|amd64)/.test(n)) return 3; + if (arch === 'x86' && /(x86|i386|i686)/.test(n)) return 3; + if (arch === 'arm64' && /(arm64|aarch64)/.test(n)) return 3; + if (arch === 'arm' && /\barm\b/.test(n)) return 3; + return 0; +} + +function typePriority(name, os) { + const n = name.toLowerCase(); + + if (os === 'windows') { + if (n.endsWith('.exe')) return 12; + if (n.endsWith('.msi')) return 10; + } + + if (os === 'macos') { + if (n.endsWith('.dmg')) return 12; + if (n.endsWith('.pkg')) return 10; + } + + if (os === 'linux') { + if (n.endsWith('.appimage')) return 12; + if (n.endsWith('.deb')) return 10; + if (n.endsWith('.rpm')) return 9; + if (n.endsWith('.apk')) return 9; + if (n.endsWith('.tar.gz')) return 8; + if (n.endsWith('.tar.xz')) return 7; + } + + if (os === 'android' && n.endsWith('.apk')) return 12; + if (os === 'ios' && n.endsWith('.ipa')) return 12; + + return 1; +} + +function collectEditorAssets(release, os, arch) { + if (!release?.assets?.length) return []; + + return release.assets + .filter((asset) => isCompatibleEditorAsset(asset.name, os)) + .map((asset) => { + const detectedArch = detectArchFromName(asset.name); + return { + name: asset.name, + url: asset.browser_download_url, + type: fileTypeLabel(asset.name), + arch: detectedArch !== 'unknown' ? detectedArch : arch, + score: typePriority(asset.name, os) + archScore(asset.name, arch), + }; + }) + .sort((a, b) => b.score - a.score); +} + +function collectCliAssets(release, os, arch) { + if (!release?.assets?.length) return []; + + return release.assets + .filter((asset) => isCompatibleCliAsset(asset.name, os)) + .map((asset) => { + return { + name: asset.name, + url: asset.browser_download_url, + type: fileTypeLabel(asset.name), + arch: detectArchFromName(asset.name), + score: typePriority(asset.name, os) + archScore(asset.name, arch), + }; + }) + .sort((a, b) => b.score - a.score); } -function pickAsset(release, pattern) { - if (!release || !release.assets) return null; - const found = release.assets.find(a => a.name.toLowerCase().includes(pattern)); - return found || null; +async function fetchLatestRelease(url) { + const res = await fetch(url, { + headers: { + Accept: 'application/vnd.github+json', + }, + }); + + if (!res.ok) { + throw new Error(`GitHub API error: ${res.status}`); + } + + const data = await res.json(); + return { + html_url: data.html_url, + tag_name: data.tag_name, + assets: Array.isArray(data.assets) ? data.assets : [], + }; } -function PlatformCard({platform, release, recommended}) { - const primary = pickAsset(release, platform) || pickAsset(release, 'installer') || release?.assets?.[0]; - const lang = pickAsset(release, 'lang') || pickAsset(release, '.zip') || null; - const ide = pickAsset(release, 'ide') || null; +function buildPlan(os, arch, releases) { + const target = os; + + if (target === 'unknown') { + return { + os: 'unknown', + osTechLabel: OS_TECH_LABEL.unknown, + version: releases.editor?.tag_name || releases.language?.tag_name || null, + stage: 'Stable', + editorOptions: [], + cliOptions: [], + editorPrimary: null, + cliPrimary: null, + hasEditorInstall: false, + hasCli: false, + packageMeta: null, + editorTag: releases.editor?.tag_name || null, + languageTag: releases.language?.tag_name || null, + loading: releases.loading, + error: releases.error, + }; + } + + const editorSource = isMobileOS(target) ? releases.language : releases.editor; + + const editorOptions = collectEditorAssets(editorSource, target, arch); + const cliOptions = collectCliAssets(releases.language, target, arch); + + const editorPrimary = editorOptions[0] || null; + const cliPrimary = cliOptions[0] || null; + + const version = editorSource?.tag_name || releases.editor?.tag_name || releases.language?.tag_name || null; + const stage = stageLabel(version); + + return { + os: target, + osTechLabel: OS_TECH_LABEL[target] || OS_TECH_LABEL.unknown, + version, + stage, + editorOptions, + cliOptions, + editorPrimary, + cliPrimary, + hasEditorInstall: editorOptions.length > 0, + hasCli: cliOptions.length > 0, + packageMeta: editorPrimary ? `${editorPrimary.type} • ${archLabel(editorPrimary.arch)} • ${stage}` : null, + editorTag: releases.editor?.tag_name || null, + languageTag: releases.language?.tag_name || null, + loading: releases.loading, + error: releases.error, + }; +} + +function LinuxPackagePicker({options, label, buttonLabel, idPrefix, buttonVariant = 'primary'}) { + const [selectedIndex, setSelectedIndex] = useState(0); + const selected = options[selectedIndex] || null; + + useEffect(() => { + setSelectedIndex(0); + }, [options]); + + const selectId = `${idPrefix}-package`; + const buttonClass = buttonVariant === 'secondary' ? 'button button--secondary button--md' : 'button button--primary button--md'; return ( -
-

{platform}

-

حزمة مُختارة لنظام {platform}.

- -
- {primary ? ( - تنزيل مُوصى به — {primary.name} - ) : ( - تنزيل (غير متوفر) - )} - -
- {lang ? اللغة فقط : null} - {ide ? IDE فقط : null} -
-
+
+ + + + + {buttonLabel} +
); } +function OSCard({os, detected, plan}) { + const isDetected = detected === os.key; + const mobile = isMobileOS(os.key); + const description = mobile + ? 'نسخة خفيفة لتجربة اللغة ومراجعة الأكواد.' + : 'بيئة التطوير المتكاملة (IDE) وأدوات البناء.'; + const editorLabel = mobile ? 'تحميل التطبيق' : 'تحميل المحرر'; + const cliLabel = mobile ? 'نواة اللغة فقط' : 'نواة اللغة (CLI)'; + const mobileUnavailable = mobile && !plan.hasEditorInstall; + + return ( +
+
+

{os.label}

+ {isDetected ? النظام الحالي : null} +
+ +

{description}

+ + {mobileUnavailable ? ( +
+ + يتوفر قريباً إن شاء الله + +
+ ) : ( +
+ {plan.hasEditorInstall ? ( + os.key === 'linux' ? ( + + ) : ( + + {editorLabel} + + ) + ) : ( + يتوفر قريباً إن شاء الله + )} + + {plan.hasCli ? ( + os.key === 'linux' ? ( + + ) : ( + + {cliLabel} + + ) + ) : ( + {`${cliLabel} تتوفر قريباً`} + )} +
+ )} +
+ ); +} + export default function DownloadPage() { - const [releases] = useState(EXAMPLE_RELEASES); - const [selected, setSelected] = useState(releases[0]); - const [platform] = useState(() => detectPlatform()); - const [versions, setVersions] = useState(null); - - useEffect(() => { - // Try to load Docusaurus versions.json (native versioning). If present, - // use it to provide version choices. This is client-side only. - async function loadVersions() { - try { - const res = await fetch('/versions.json'); - if (!res.ok) return; - const data = await res.json(); - if (Array.isArray(data) && data.length) { - setVersions(data); - // If a version matches a release tag, select it - const match = data.find(v => releases.some(r => r.tag_name === v)); - if (match) { - const rel = releases.find(r => r.tag_name === match); - if (rel) setSelected(rel); - } - } - } catch (e) { - // ignore - fallback to example data - } - } - loadVersions(); - }, [releases]); + const [client, setClient] = useState({os: 'unknown', arch: 'unknown'}); + const [releases, setReleases] = useState({ + loading: true, + error: null, + editor: null, + language: null, + }); useEffect(() => { - // placeholder: later we could fetch real releases here and setSelected accordingly + setClient(detectClient()); }, []); - const platforms = useMemo(() => ['windows', 'mac', 'linux'], []); + useEffect(() => { + let cancelled = false; + + async function load() { + try { + const [editor, language] = await Promise.all([ + fetchLatestRelease(GITHUB_API.editor), + fetchLatestRelease(GITHUB_API.language), + ]); + + if (cancelled) return; + setReleases({loading: false, error: null, editor, language}); + } catch { + if (cancelled) return; + setReleases({loading: false, error: 'تعذر جلب أحدث الإصدارات الآن.', editor: null, language: null}); + } + } + + load(); + + return () => { + cancelled = true; + }; + }, []); + + const detectedPlan = useMemo(() => buildPlan(client.os, client.arch, releases), [client.os, client.arch, releases]); + const versionLabel = detectedPlan.version || 'v-'; return ( - -
-
-
-
-

تنزيل ض — {selected.name}

-

تاريخ الإصدار: {selected.published_at}

-
+ +
+
+
+
+

بيئة تطوير لغة "ض"

+

نسخة متوافقة مع {detectedPlan.osTechLabel}

+ +
+ {detectedPlan.hasEditorInstall ? ( + + {`تحميل الحزمة (${versionLabel})`} + + ) : ( + يتوفر قريباً إن شاء الله + )} + + {detectedPlan.cliPrimary ? ( + + نواة اللغة (CLI) + + ) : null} +
-
- - {versions ? ( -
- {versions.map(v => ( - - ))} -
- ) : ( -
- {releases.map(r => ( - - ))} -
- )} + {detectedPlan.hasEditorInstall && detectedPlan.packageMeta ? ( +

{detectedPlan.packageMeta}

+ ) : null} + + {detectedPlan.loading ?

جارِ التحقق من آخر الإصدارات...

: null} + {detectedPlan.error ?

{detectedPlan.error}

: null} + {!detectedPlan.loading && !detectedPlan.error ? ( +

+ آخر إصدار للمحرر: {detectedPlan.editorTag || '-'} | آخر إصدار للغة: {detectedPlan.languageTag || '-'} +

+ ) : null}
+
-
-

اختر نظام التشغيل

-
- {platforms.map((p) => ( - - ))} -
-
- -
-

جميع الإصدارات (مثال)

-

قائمة إصدارات من المثال. لاحقاً يمكن سحب هذه القائمة مباشرة من GitHub Releases عبر API.

-
- {releases.map((r) => ( -
-
-
- {r.name} -
تاريخ النشر: {r.published_at}
-
-
- {r.assets.map((a) => ( - تنزيل {a.name} - ))} -
-
-
- ))} +
+
+

إعداد بيئة العمل

+ +
+
+ 1 +

التحقق التلقائي

+

تم تحديد النسخة الأنسب لنظام تشغيلك آلياً.

+
+ +
+ 2 +

الحصول على الحزمة

+

حمّل ملف التثبيت المتكامل (المحرر + اللغة).

+
+ +
+ 3 +

التثبيت والانطلاق

+

شغّل الملف وابدأ رحلتك البرمجية فوراً.

+
-
-
-
-
- ); -} +
+ التوثيق والدروس + أرشيف المحرر + أرشيف اللغة +
+
+ -// ----------------------------- -// Releases list (example data) -// ----------------------------- - -function ReleasesList() { - // Example data — replace with a real fetch to the GitHub Releases API later. - const exampleReleases = [ - { - id: 1, - tag_name: 'v0.2.0', - name: 'إصدار 0.2.0', - published_at: '2026-01-15', - assets: [ - { name: 'daad-0.2.0-windows-installer.exe', browser_download_url: 'https://example.com/downloads/daad-0.2.0-windows-installer.exe' }, - { name: 'daad-0.2.0-mac.dmg', browser_download_url: 'https://example.com/downloads/daad-0.2.0-mac.dmg' }, - { name: 'daad-0.2.0-linux.AppImage', browser_download_url: 'https://example.com/downloads/daad-0.2.0-linux.AppImage' }, - ], - }, - { - id: 2, - tag_name: 'v0.1.0', - name: 'الإصدار التجريبي 0.1.0', - published_at: '2025-12-01', - assets: [ - { name: 'daad-0.1.0.zip', browser_download_url: 'https://example.com/downloads/daad-0.1.0.zip' }, - ], - }, - ]; - - // Clicking an asset should start download — we'll navigate the browser to the asset URL. - function download(url) { - // create an and click it so the browser treats it as a download/navigation. - const a = document.createElement('a'); - a.href = url; - a.rel = 'noopener noreferrer'; - // If same-origin and served with Content-Disposition attachment the download will start. - a.click(); - } +
+
+

التحميل اليدوي للمنصات

- return ( -
-

الإصدارات

-

قائمة إصدارات من المثال. لاحقاً يمكن سحب هذه القائمة مباشرة من GitHub Releases عبر API.

- -
- {exampleReleases.map((r) => ( -
-
-
- {r.name} -
تاريخ النشر: {r.published_at}
+
+

منصات سطح المكتب

+
+ {prioritizeDetectedOS( + OS_LIST.filter((os) => DESKTOP_OS_KEYS.has(os.key)), + client.os, + ).map((os) => { + const plan = buildPlan(os.key, client.arch, releases); + return ; + })}
-
- {r.assets.map((a) => ( - - ))} +
+ +
+

منصات الهاتف

+
+ {prioritizeDetectedOS( + OS_LIST.filter((os) => MOBILE_OS_KEYS.has(os.key)), + client.os, + ).map((os) => { + const plan = buildPlan(os.key, client.arch, releases); + return ; + })}
- ))} -
-
+
+
+
); } - diff --git a/src/pages/download.module.css b/src/pages/download.module.css new file mode 100644 index 0000000..0ef5aec --- /dev/null +++ b/src/pages/download.module.css @@ -0,0 +1,284 @@ +.page { + background: linear-gradient(180deg, rgba(52, 182, 226, 0.06), transparent 28%); +} + +.heroSection, +.stepsSection, +.platformSection { + padding: 2.2rem 0; +} + +.heroCard, +.stepCard, +.osCard { + background: var(--card-bg); + border: 1px solid var(--border-soft); + border-radius: 14px; + box-shadow: 0 10px 30px rgba(2, 6, 23, 0.06); +} + +.heroCard { + padding: clamp(1rem, 2.4vw, 1.8rem); + overflow-wrap: anywhere; +} + +.heroCard h1 { + margin: 0; + font-size: clamp(1.6rem, 4vw, 2.35rem); + line-height: 1.2; + color: var(--text-main); +} + +.subhead { + margin: 0.7rem 0 0; + color: var(--text-muted); + font-size: 1.02rem; +} + +.heroButtonRow { + margin-top: 1.1rem; + display: flex; + flex-wrap: wrap; + gap: 0.7rem; +} + +.heroButtonRow :global(.button) { + max-width: 100%; + white-space: normal; + overflow-wrap: anywhere; +} + +.heroComingSoon { + display: inline-block; + border: 1px dashed var(--border-soft); + background: rgba(148, 163, 184, 0.12); + color: var(--text-muted); + border-radius: 10px; + padding: 0.8rem 1rem; + font-weight: 600; +} + +.packageMeta { + margin: 0.55rem 0 0; + color: var(--text-muted); + font-size: 0.9rem; + letter-spacing: 0.01em; +} + +.releaseMeta { + margin: 0.55rem 0 0; + color: var(--text-muted); + font-size: 0.9rem; + overflow-wrap: anywhere; +} + +.releaseError { + margin: 0.55rem 0 0; + color: #b91c1c; + font-size: 0.9rem; +} + +.sectionTitle { + margin: 0; + color: var(--text-main); + font-size: clamp(1.35rem, 3vw, 1.9rem); +} + +.stepsGrid { + margin-top: 1rem; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.9rem; +} + +.stepCard { + padding: 1rem; + min-width: 0; +} + +.stepNum { + display: inline-flex; + width: 1.95rem; + height: 1.95rem; + align-items: center; + justify-content: center; + border-radius: 999px; + background: var(--ifm-color-primary); + color: #fff; + font-weight: 700; + margin-bottom: 0.55rem; +} + +.stepCard h3 { + margin: 0; + color: var(--text-main); + font-size: 1.05rem; + line-height: 1.45; +} + +.stepCard p { + margin: 0.45rem 0 0; + color: var(--text-muted); + line-height: 1.7; +} + +.supportLinks { + margin-top: 1rem; + display: flex; + gap: 1rem; + flex-wrap: wrap; +} + +.supportLinks a { + color: var(--ifm-color-primary); + text-decoration: none; + font-weight: 600; + overflow-wrap: anywhere; +} + +.supportLinks a:hover, +.supportLinks a:focus { + text-decoration: underline; +} + +.osGrid { + margin-top: 1rem; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 0.9rem; +} + +.platformGroup { + margin-top: 1rem; +} + +.groupTitle { + margin: 0; + color: var(--text-main); + font-size: 1.05rem; +} + +.osCard { + padding: 1rem; + min-width: 0; + display: flex; + flex-direction: column; +} + +.osCardActive { + border-color: var(--ifm-color-primary); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--ifm-color-primary) 20%, transparent); +} + +.osHeader { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.6rem; +} + +.osHeader h3 { + margin: 0; + color: var(--text-main); + font-size: 1.05rem; +} + +.badge { + border-radius: 999px; + background: rgba(46, 133, 85, 0.16); + color: var(--ifm-color-primary-darkest); + font-size: 0.75rem; + font-weight: 700; + padding: 0.2rem 0.55rem; +} + +.cardDescription { + margin: 0.6rem 0; + color: var(--text-muted); + line-height: 1.6; +} + +.cardButtons { + margin-top: auto; + display: grid; + gap: 0.5rem; +} + +.cardButtons :global(.button) { + width: 100%; + max-width: 100%; + white-space: normal; + overflow-wrap: anywhere; + text-align: center; +} + +.linuxPicker { + display: grid; + gap: 0.55rem; +} + +.linuxPicker label { + color: var(--text-main); + font-weight: 600; +} + +.linuxPicker select { + max-width: 100%; + min-width: 0; + width: 100%; + border: 1px solid var(--border-soft); + border-radius: 8px; + background: var(--card-bg); + color: var(--text-main); + padding: 0.5rem; +} + +.comingSoon, +.cliUnavailable { + border: 1px dashed var(--border-soft); + background: rgba(148, 163, 184, 0.12); + color: var(--text-muted); + border-radius: 10px; + padding: 0.8rem; + text-align: center; + font-weight: 600; +} + +.singleComingSoonButton { + width: 100%; + text-align: center; + pointer-events: none; + opacity: 0.92; + background: #334155; + border-color: #334155; + color: #f8fafc; +} + +.singleComingSoonButton:hover, +.singleComingSoonButton:focus { + background: #334155; + border-color: #334155; + color: #f8fafc; +} + +@media (max-width: 960px) { + .stepsGrid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 700px) { + .heroSection, + .stepsSection, + .platformSection { + padding: 1.3rem 0; + } + + .heroButtonRow :global(.button) { + width: 100%; + } + + .supportLinks { + gap: 0.7rem; + } +} diff --git a/src/pages/index.js b/src/pages/index.js index 4222d8c..4e05840 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -16,7 +16,7 @@ function Hero() { const { siteConfig } = useDocusaurusContext(); const docsHome = useBaseUrl('/docs/home'); const tutorialUrl = useBaseUrl('/docs/tutorial/intro'); - const downloadUrl = useBaseUrl('/simple_download'); + const downloadUrl = useBaseUrl('/download'); const logoSrc = useBaseUrl('/img/logo.svg'); const logoDark = useBaseUrl('/img/logo-dark.svg'); diff --git a/src/pages/simple_download.js b/src/pages/simple_download.js index c07afff..a47fa27 100644 --- a/src/pages/simple_download.js +++ b/src/pages/simple_download.js @@ -1,72 +1 @@ -import React from 'react'; -import Layout from '@theme/Layout'; -import Link from '@docusaurus/Link'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -export default function SimpleDownload() { - const releasesUrl = 'https://github.com/daadLang/website/releases'; - const languageReleases = 'https://github.com/daadLang/daad/releases'; - const editorReleases = 'https://github.com/daadLang/d-editor/releases'; - const advanced = useBaseUrl('/download'); - - return ( - -
-
-
-

تنزيل ض

-

- اختر ما تريد تنزيله من الروابط الرسمية على GitHub — الحزم الرسمية والـ installers للمشاريع. -

-
- -
- - تحميل اللغة — ض - - - - تحميل المحرر - - - -
- -
- -
-

معلومة :

-

- هذا المشروع لا يزال قيد التطوير. سنكون سعداء بتلقي ملاحظاتك — يرجى التواصل معنا إذا واجهت أي مشاكل أو كانت لديك اقتراحات. -

- -
- -
- ملاحظة : -

- تأكد دوماً من تنزيل الملفات من صفحة الإصدارات الرسمية وتحقق من توقيع الإصدار - إذا كان متوفراً. -

-
- - - -
-
-
- - ); -} +export {default} from './download'; diff --git a/static/font/DG-Heaven-Thin.ttf b/static/font/DG-Heaven-Thin.ttf new file mode 100644 index 0000000..6d42055 Binary files /dev/null and b/static/font/DG-Heaven-Thin.ttf differ diff --git a/static/font/TheYearofTheCamel-Regular.otf b/static/font/TheYearofTheCamel-Regular.otf new file mode 100644 index 0000000..bd14a02 Binary files /dev/null and b/static/font/TheYearofTheCamel-Regular.otf differ