diff --git a/blog/2022-1-28-ivorysql-arrived/index.md b/blog/2022-1-28-ivorysql-arrived/index.md index a0bc46a..8500dec 100644 --- a/blog/2022-1-28-ivorysql-arrived/index.md +++ b/blog/2022-1-28-ivorysql-arrived/index.md @@ -4,7 +4,7 @@ title: IvorySQL Has Arrived authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/IvorySQL-has-arrived.png +image: img/blog/covers/ivorysql-arrived.svg tags: [IvorySQL, Welcome, Database, Oracle Compatible, PostgreSQL, Join Us] --- diff --git a/blog/2022-3-25-postgres-world-webinar/index.md b/blog/2022-3-25-postgres-world-webinar/index.md index 579cb2c..24ef218 100644 --- a/blog/2022-3-25-postgres-world-webinar/index.md +++ b/blog/2022-3-25-postgres-world-webinar/index.md @@ -4,7 +4,7 @@ title: PostgresWorld Webinar | A Deep Dive Into IvorySQL authors: [official] authorTwitter: IvorySql category: PostgreSQL -image: img/blog/PostgresWorld-Webinar.png +image: img/blog/covers/pg-webinar.svg tags: [IvorySQL, PostgresWorld, Database, Oracle Compatible, PostgreSQL, Join Us] --- diff --git a/blog/2022-4-18-sv2022/index.md b/blog/2022-4-18-sv2022/index.md index 89085b2..40a4fc2 100644 --- a/blog/2022-4-18-sv2022/index.md +++ b/blog/2022-4-18-sv2022/index.md @@ -4,7 +4,7 @@ title: IvorySQL at PostgresConf SV 2022 authors: [official] authorTwitter: IvorySql category: PostgreSQL -image: img/blog/PostgresConf-SV-2022.png +image: img/blog/covers/pgconf-sv-2022.svg tags: [IvorySQL,PostgresConf SV , Database, Oracle Compatible, PostgreSQL, Join Us] --- diff --git a/blog/2022-5-17-linux/index.md b/blog/2022-5-17-linux/index.md index a3a7fca..8d68722 100644 --- a/blog/2022-5-17-linux/index.md +++ b/blog/2022-5-17-linux/index.md @@ -4,7 +4,7 @@ title: Compiling and Installing IvorySQL on Linux authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/Compiling-and-Installing-IvorySQL-on-Linux.png +image: img/blog/covers/linux-install.svg tags: [IvorySQL, Welcome,Linux, PostgreSQL, Join Us] --- diff --git a/blog/2022-5-27-packages/index.md b/blog/2022-5-27-packages/index.md index bd1705a..6810cba 100644 --- a/blog/2022-5-27-packages/index.md +++ b/blog/2022-5-27-packages/index.md @@ -3,7 +3,7 @@ slug: ivorysql-packages title: Introduction to IvorySQL Packages authors: [Asif] category: IvorySQL -image: img/blog/IvorySQL-packages.png +image: img/blog/covers/ivorysql-packages.svg tags: [IvorySQL, Oracle, Packages, PostgreSQL, Join Us] --- diff --git a/blog/2022-5-6-yum/index.md b/blog/2022-5-6-yum/index.md index 48275fd..8083e06 100644 --- a/blog/2022-5-6-yum/index.md +++ b/blog/2022-5-6-yum/index.md @@ -4,7 +4,7 @@ title: Install software through the YUM source authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/Install-software-through-the-YUM-source.png +image: img/blog/covers/yum-install.svg tags: [IvorySQL, Welcome, YUM, PostgreSQL, Join Us] --- diff --git a/blog/2022-6-2-PGCon2022/index.md b/blog/2022-6-2-PGCon2022/index.md index 24e0bef..208291b 100644 --- a/blog/2022-6-2-PGCon2022/index.md +++ b/blog/2022-6-2-PGCon2022/index.md @@ -4,7 +4,7 @@ title: PGCon2022 meeting review | Technical explanation of IvorySQL project authors: [official] authorTwitter: IvorySql category: PostgreSQL -image: img/blog/PGCon2022-meeting-review.png +image: img/blog/covers/pgcon-2022.svg tags: [IvorySQL,PGCon2022, PostgreSQL, Join Us] --- diff --git a/blog/2024-11-27-ivorysql-high-availability/index.md b/blog/2024-11-27-ivorysql-high-availability/index.md index a65b5fd..f024aa7 100644 --- a/blog/2024-11-27-ivorysql-high-availability/index.md +++ b/blog/2024-11-27-ivorysql-high-availability/index.md @@ -4,7 +4,7 @@ title: IvorySQL High Availability—Zero Loss Logical Replication Slots authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/IvorySQL-High-Availability.png +image: img/blog/covers/ha-replication.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, High Availability] --- diff --git a/blog/2024-12-05-ivorysql-external-storage-manager/index.md b/blog/2024-12-05-ivorysql-external-storage-manager/index.md index cba35e1..e742c23 100644 --- a/blog/2024-12-05-ivorysql-external-storage-manager/index.md +++ b/blog/2024-12-05-ivorysql-external-storage-manager/index.md @@ -4,7 +4,7 @@ title: External Storage Manager in IvorySQL Database authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/External-Storage-Manager.png +image: img/blog/covers/external-storage.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL] --- In general, a database storage system is divided into two parts: memory and external storage. Except for in-memory databases, data is eventually persisted, which means that it needs to be written from the memory buffer to the external storage. This article will discuss the external storage manager in IvorySQL. diff --git a/blog/2025-01-02-ivorysql-upgrade-3.x-to-4.0/index.md b/blog/2025-01-02-ivorysql-upgrade-3.x-to-4.0/index.md index fce0df8..be8f87e 100644 --- a/blog/2025-01-02-ivorysql-upgrade-3.x-to-4.0/index.md +++ b/blog/2025-01-02-ivorysql-upgrade-3.x-to-4.0/index.md @@ -4,7 +4,7 @@ title: IvorySQL Upgrade Guide-A Smooth Transition from 3.x to 4.0 authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/ivorysql-upgrade.png +image: img/blog/covers/upgrade-guide.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL] --- Recently, IvorySQL 4.0 was released, offering full support for PostgreSQL 17 and enhanced compatibility with Oracle. diff --git a/blog/2025-01-09-ivorysql-4.0-package/index.md b/blog/2025-01-09-ivorysql-4.0-package/index.md index 0354743..a3ba230 100644 --- a/blog/2025-01-09-ivorysql-4.0-package/index.md +++ b/blog/2025-01-09-ivorysql-4.0-package/index.md @@ -4,7 +4,7 @@ title: IvorySQL 4.0-Design Insights into Oracle Package Compatibility Feature authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/Oracle-Package-Compatibility.png +image: img/blog/covers/oracle-package.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, Oracle Package, Package] --- diff --git a/blog/2025-03-05-ivorysql-v4-logical-replication-slot/index.md b/blog/2025-03-05-ivorysql-v4-logical-replication-slot/index.md index 4bca5ed..699980f 100644 --- a/blog/2025-03-05-ivorysql-v4-logical-replication-slot/index.md +++ b/blog/2025-03-05-ivorysql-v4-logical-replication-slot/index.md @@ -4,7 +4,7 @@ title: Analysis of the Logical Replication Slot Synchronization Feature in Ivory authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/IvorySQL-Logical-Replication-Slot.png +image: img/blog/covers/logical-replication-slot.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, Logical Replication Slot] --- diff --git a/blog/2025-03-20-ivorySQL-incremental-backup-and-merge-features/index.md b/blog/2025-03-20-ivorySQL-incremental-backup-and-merge-features/index.md index 4132408..2b51d29 100644 --- a/blog/2025-03-20-ivorySQL-incremental-backup-and-merge-features/index.md +++ b/blog/2025-03-20-ivorySQL-incremental-backup-and-merge-features/index.md @@ -4,7 +4,7 @@ title: IvorySQL Incremental Backup and Merge Features authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/IvorySQL-Incremental-Backup.png +image: img/blog/covers/incremental-backup.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, Incremental Backup] --- diff --git a/blog/2025-05-27-ivorysql-wasm/index.md b/blog/2025-05-27-ivorysql-wasm/index.md index e0eba42..509a827 100644 --- a/blog/2025-05-27-ivorysql-wasm/index.md +++ b/blog/2025-05-27-ivorysql-wasm/index.md @@ -4,7 +4,7 @@ title: IvorySQL-WASM, An Exploration Journey of Installation-Free Databases authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/ivorysql-wasm.png +image: img/blog/covers/wasm.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, WasmEdge] --- diff --git a/blog/2025-09-26-Analysis-of-PG-18-Key-New-Features/index.md b/blog/2025-09-26-Analysis-of-PG-18-Key-New-Features/index.md index 6277977..91dd14f 100644 --- a/blog/2025-09-26-Analysis-of-PG-18-Key-New-Features/index.md +++ b/blog/2025-09-26-Analysis-of-PG-18-Key-New-Features/index.md @@ -4,7 +4,7 @@ title: In-Depth Analysis of PostgreSQL 18 Key New Features authors: [official] authorTwitter: IvorySql category: PostgreSQL -image: img/blog/20250926-cover.png +image: img/blog/covers/pg18-features.svg tags: [IvorySQL, Database, UUIDv7, PostgreSQL, I/O, OAuth] --- diff --git a/blog/2025-1-13-ivorysql-4.0-invisible-column/index.md b/blog/2025-1-13-ivorysql-4.0-invisible-column/index.md index a5bd88d..44e7ad8 100644 --- a/blog/2025-1-13-ivorysql-4.0-invisible-column/index.md +++ b/blog/2025-1-13-ivorysql-4.0-invisible-column/index.md @@ -4,7 +4,7 @@ title: Analysis of the Invisible Column Feature in IvorySQL 4.0 authors: [official] authorTwitter: IvorySql category: IvorySQL -image: img/blog/IvorySQL-Invisible-Column.png +image: img/blog/covers/invisible-column.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, Invisible Column] --- diff --git a/blog/2026-02-10-ivorysql-5.0-oracle-to-postgresql-migration/index.md b/blog/2026-02-10-ivorysql-5.0-oracle-to-postgresql-migration/index.md index ae5f5ed..b9c0b17 100644 --- a/blog/2026-02-10-ivorysql-5.0-oracle-to-postgresql-migration/index.md +++ b/blog/2026-02-10-ivorysql-5.0-oracle-to-postgresql-migration/index.md @@ -3,7 +3,7 @@ slug: ivorysql-5.0-oracle-to-postgresql-migration title: IvorySQL 5.0+ - a game changer for Oracle to PostgreSQL transitions authors: [Yasir Hussain Shah] category: IvorySQL -image: img/blog/2026-2-10-cover.png +image: img/blog/covers/oracle-migration.svg tags: [IvorySQL, Database, Oracle Compatible, PostgreSQL, migration] --- diff --git a/src/css/custom.css b/src/css/custom.css index 2efb002..52c85e2 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -3,167 +3,772 @@ flex: 0 0 100% !important; } -.category-nav-container { +/* ── (legacy) keep old classes so nothing else breaks ── */ +.category-nav-container { display: flex; gap: 30px; margin: 10px 0 40px 0; border-bottom: 1px solid #ebedf0; padding-bottom: 15px; } +.category-nav-link { font-weight: bold; font-size: 1.1rem; color: #444; text-decoration: none; } +.active-link { color: var(--ifm-color-primary) !important; border-bottom: 2px solid var(--ifm-color-primary); } +.tag-pill-static { display: inline-flex; align-items: center; background: #f4f4f5; color: #606266; padding: 2px 12px; border-radius: 4px; font-size: 0.8rem; border: 1px solid #e9e9eb; white-space: nowrap; } + +/* ───────────────────────────────────────────────────────── + Blog Page Header +───────────────────────────────────────────────────────── */ +.blog-page-header { display: flex; - gap: 30px; - margin: 10px 0 40px 0; - border-bottom: 1px solid #ebedf0; - padding-bottom: 15px; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + margin-bottom: 32px; + padding-bottom: 28px; + border-bottom: 1px solid #e5e9f2; + flex-wrap: wrap; } -.category-nav-link { - font-weight: bold; - font-size: 1.1rem; - color: #444; - text-decoration: none; +.blog-page-header-inner {} + +.blog-page-title { + font-size: 2rem; + font-weight: 800; + color: #0d1b3e; + margin: 0 0 6px 0; + line-height: 1.2; +} + +.blog-page-subtitle { + font-size: 0.95rem; + color: #64748b; + margin: 0; + line-height: 1.5; +} + +.blog-page-count-badge { + display: inline-flex; + align-items: center; + background: linear-gradient(135deg, #eff4ff 0%, #dbeafe 100%); + border: 1px solid rgba(47, 116, 255, 0.2); + color: #2f74ff; + font-size: 0.82rem; + font-weight: 700; + padding: 4px 14px; + border-radius: 20px; + white-space: nowrap; + flex-shrink: 0; +} + +/* ───────────────────────────────────────────────────────── + Category Filter Bar +───────────────────────────────────────────────────────── */ +.blog-filter-bar { + display: flex; + gap: 4px; + margin-bottom: 16px; + padding: 4px; + background: #f1f5f9; + border-radius: 10px; + width: fit-content; +} + +.blog-cat-btn { + display: inline-flex; + align-items: center; + padding: 7px 20px; + border-radius: 7px; + font-size: 0.88rem; + font-weight: 600; + color: #64748b; + text-decoration: none !important; + transition: all 0.18s; + white-space: nowrap; + border: none; + background: transparent; +} + +.blog-cat-btn:hover { + color: #2f74ff; + background: rgba(255, 255, 255, 0.8); +} + +.blog-cat-btn.active { + background: #fff; + color: #2f74ff; + box-shadow: 0 1px 6px rgba(47, 116, 255, 0.15), 0 0 0 1px rgba(47, 116, 255, 0.12); +} + +/* ───────────────────────────────────────────────────────── + Two-column blog layout +───────────────────────────────────────────────────────── */ +.blog-body-layout { + display: flex; + align-items: flex-start; + gap: 28px; +} + +.blog-main-col { + flex: 1; + min-width: 0; +} + +/* ───────────────────────────────────────────────────────── + Tag Sidebar (right) +───────────────────────────────────────────────────────── */ +.blog-tag-sidebar { + flex: 0 0 220px; + width: 220px; + position: sticky; + top: 80px; + background: #fff; + border: 1px solid #e5e9f2; + border-radius: 12px; + padding: 18px 0 14px; + box-shadow: 0 2px 10px rgba(15, 35, 100, 0.05); +} + +.blog-tag-sidebar-header { + display: flex; + align-items: center; + gap: 7px; + font-size: 0.78rem; + font-weight: 700; + color: #94a3b8; + letter-spacing: 0.06em; + text-transform: uppercase; + padding: 0 18px 12px; + border-bottom: 1px solid #f1f5f9; + margin-bottom: 6px; +} + +.blog-tag-sidebar-list { + list-style: none; + padding: 0; + margin: 0; + max-height: 420px; + overflow-y: auto; +} + +.blog-tag-sidebar-list::-webkit-scrollbar { + width: 4px; +} +.blog-tag-sidebar-list::-webkit-scrollbar-track { + background: transparent; +} +.blog-tag-sidebar-list::-webkit-scrollbar-thumb { + background: #e2e8f0; + border-radius: 2px; +} + +.blog-tag-sidebar-item { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + padding: 7px 18px; + border: none; + background: transparent; + cursor: pointer; + text-align: left; + transition: background 0.15s, color 0.15s; + border-left: 3px solid transparent; +} + +.blog-tag-sidebar-item:hover { + background: #f8faff; + border-left-color: rgba(47, 116, 255, 0.3); +} + +.blog-tag-sidebar-item.active { + background: #eff4ff; + border-left-color: #2f74ff; +} + +.blog-tag-sidebar-item.active .blog-tag-sidebar-label { + color: #2f74ff; + font-weight: 600; } -.active-link { - color: var(--ifm-color-primary) !important; - border-bottom: 2px solid var(--ifm-color-primary); +.blog-tag-sidebar-item.active .blog-tag-sidebar-count { + background: rgba(47, 116, 255, 0.15); + color: #2f74ff; } -.custom-horizontal-card { +.blog-tag-sidebar-label { + font-size: 0.84rem; + color: #475569; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.blog-tag-sidebar-count { + flex-shrink: 0; + min-width: 20px; + height: 20px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 5px; + border-radius: 10px; + background: #f1f5f9; + color: #94a3b8; + font-size: 0.7rem; + font-weight: 700; + margin-left: 8px; +} + +.blog-tag-sidebar-clear { + display: block; + width: calc(100% - 36px); + margin: 10px 18px 0; + padding: 7px 12px; + border-radius: 6px; + border: 1px solid #fecaca; + background: #fff5f5; + color: #dc2626; + font-size: 0.78rem; + font-weight: 600; + cursor: pointer; + text-align: center; + transition: all 0.18s; +} + +.blog-tag-sidebar-clear:hover { + background: #fee2e2; +} + +.blog-tag-sidebar-empty { + padding: 12px 18px; + font-size: 0.82rem; + color: #cbd5e1; + margin: 0; +} + +/* ───────────────────────────────────────────────────────── + Results Bar +───────────────────────────────────────────────────────── */ +.blog-results-bar { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + min-height: 28px; +} + +.blog-results-text { + font-size: 0.85rem; + color: #94a3b8; + display: flex; + align-items: center; + gap: 6px; +} + +.blog-results-tag-label { + color: #2f74ff; + font-weight: 600; +} + +.blog-results-clear { + display: inline-flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + border-radius: 50%; + border: none; + background: #e2e8f0; + color: #64748b; + font-size: 0.65rem; + cursor: pointer; + transition: all 0.18s; + padding: 0; + line-height: 1; +} + +.blog-results-clear:hover { + background: #fecaca; + color: #dc2626; +} + +.blog-results-page { + font-size: 0.82rem; + color: #94a3b8; +} + +/* ───────────────────────────────────────────────────────── + Blog Card (list view) +───────────────────────────────────────────────────────── */ +.blog-card { display: flex !important; flex-direction: row !important; background: #fff; - border: 1px solid #e5e7eb; - border-radius: 12px; - margin-bottom: 30px !important; - height: 220px; + border: 1px solid #e5e9f2; + border-radius: 14px; + margin-bottom: 20px !important; + min-height: 200px; overflow: hidden; - box-shadow: 0 4px 12px rgba(0,0,0,0.05); + box-shadow: 0 2px 10px rgba(15, 35, 100, 0.06); + transition: box-shadow 0.22s, transform 0.22s, border-color 0.22s; } -.card-left-img { - flex: 0 0 350px !important; - background: #f0f2f5; - border-right: 1px solid #eee; +.blog-card:hover { + box-shadow: 0 8px 28px rgba(47, 116, 255, 0.13); + transform: translateY(-2px); + border-color: rgba(47, 116, 255, 0.25); } -.card-left-img img { +/* Cover image */ +.blog-card-img-wrap { + flex: 0 0 300px; + display: block; + overflow: hidden; + background: #f1f5f9; +} + +.blog-card-img { width: 100%; height: 100%; - object-fit: cover; + object-fit: contain; + display: block; + transition: transform 0.4s; +} + +.blog-card:hover .blog-card-img { + transform: scale(1.02); +} + +.blog-card-img-placeholder { + width: 100%; + height: 100%; + min-height: 200px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, #0d1b3e 0%, #1e3a8a 50%, #102268 100%); } -.card-right-content { +/* Card body */ +.blog-card-body { flex: 1; - padding: 24px 30px !important; + padding: 22px 26px; display: flex; flex-direction: column; - justify-content: space-between; + gap: 8px; + min-width: 0; } -.post-item-title { - margin: 0 0 10px 0; - font-size: 1.5rem; +/* Category badge */ +.blog-card-cat { + display: inline-flex; + align-items: center; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.05em; + text-transform: uppercase; + padding: 2px 10px; + border-radius: 20px; + width: fit-content; } -.post-item-title a { - color: var(--ifm-color-primary); - text-decoration: none; +.blog-card-cat--ivorysql { + background: rgba(47, 116, 255, 0.1); + color: #2f74ff; + border: 1px solid rgba(47, 116, 255, 0.2); } -.post-item-date { - color: #666; - font-size: 0.9rem; - margin-bottom: auto; +.blog-card-cat--postgresql { + background: rgba(8, 145, 178, 0.1); + color: #0891b2; + border: 1px solid rgba(8, 145, 178, 0.2); } -.post-item-tags { +/* Title */ +.blog-card-title { + margin: 0 !important; + font-size: 1.1rem !important; + font-weight: 700 !important; + line-height: 1.4 !important; +} + +.blog-card-title a { + color: #1e293b !important; + text-decoration: none !important; + transition: color 0.18s !important; +} + +.blog-card-title a:hover { + color: #2f74ff !important; +} + +/* Date */ +.blog-card-date { display: flex; - width: 100%; + align-items: center; + gap: 5px; + font-size: 0.82rem; + color: #94a3b8; +} + +/* Tags */ +.blog-card-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 2px; } -.tags-list { +/* Authors */ +.blog-card-authors { display: flex; flex-wrap: wrap; - gap: 8px 12px; + gap: 10px; + margin-top: auto; + padding-top: 10px; + border-top: 1px solid #f1f5f9; } -.tag-pill-static { +.blog-author-chip { display: inline-flex; align-items: center; - background: #f4f4f5; - color: #606266; - padding: 2px 12px; - border-radius: 4px; - font-size: 0.8rem; - border: 1px solid #e9e9eb; + gap: 7px; + text-decoration: none !important; + color: #475569 !important; + font-size: 0.82rem; + font-weight: 500; + transition: color 0.18s; +} + +.blog-author-chip:hover { + color: #2f74ff !important; +} + +.blog-author-avatar { + width: 26px; + height: 26px; + border-radius: 50%; + object-fit: cover; + border: 2px solid #e2e8f0; + flex-shrink: 0; +} + +.blog-author-initials { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.65rem; + font-weight: 700; + color: #fff; + letter-spacing: 0.02em; +} + +.blog-author-name { + line-height: 1; +} + +/* ───────────────────────────────────────────────────────── + Clickable Tag Pill (cards + post footer) +───────────────────────────────────────────────────────── */ +.blog-tag-pill { + display: inline-flex; + align-items: center; + padding: 3px 10px; + border-radius: 5px; + background: #f1f5f9; + color: #475569 !important; + font-size: 0.76rem; + font-weight: 500; + border: 1px solid #e2e8f0; + text-decoration: none !important; white-space: nowrap; + transition: all 0.18s; + line-height: 1.4; } +.blog-tag-pill:hover { + background: #eff4ff; + color: #2f74ff !important; + border-color: rgba(47, 116, 255, 0.3); +} + +.blog-tag-more { + display: inline-flex; + align-items: center; + padding: 3px 8px; + border-radius: 5px; + background: #f8faff; + color: #94a3b8; + font-size: 0.76rem; + border: 1px solid #e2e8f0; +} + +/* ───────────────────────────────────────────────────────── + Blog Post Footer (detail page) +───────────────────────────────────────────────────────── */ +.blog-post-footer { + margin-top: 48px; + padding-top: 24px; + border-top: 1px solid #e5e9f2; + display: flex; + flex-direction: column; + gap: 16px; +} + +.blog-post-footer-tags { + display: flex; + align-items: flex-start; + gap: 12px; + flex-wrap: wrap; +} + +.blog-post-footer-tags-label { + font-size: 0.82rem; + font-weight: 600; + color: #94a3b8; + padding-top: 2px; + white-space: nowrap; +} + +.blog-post-footer-tags-list { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.blog-post-footer-edit { + font-size: 0.85rem; +} + +/* ───────────────────────────────────────────────────────── + Pagination +───────────────────────────────────────────────────────── */ .blog-pagination-wrapper { display: flex; justify-content: center; - margin: 50px 0; + margin: 40px 0 20px; width: 100%; } -.custom-pagination { +.blog-pagination { display: flex; align-items: center; - gap: 15px; + gap: 8px; } -.pagination-number-list { +.blog-page-list { display: flex; list-style: none; padding: 0; margin: 0; - gap: 8px; + gap: 4px; } -.pagination-nav-item, .pagination-number-item { +.blog-page-nav { display: inline-flex; align-items: center; - justify-content: center; + gap: 5px; padding: 8px 16px; - border: 1px solid #e5e7eb; - border-radius: 6px; - color: #444; - text-decoration: none !important; - font-size: 0.9rem; + border-radius: 8px; + border: 1px solid #e5e9f2; + background: #fff; + color: #475569; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: all 0.18s; +} + +.blog-page-nav:hover:not(.disabled) { + border-color: #2f74ff; + color: #2f74ff; + background: #eff4ff; +} + +.blog-page-nav.disabled, +.blog-page-nav:disabled { + opacity: 0.38; + cursor: not-allowed; +} + +.blog-page-num { + min-width: 36px; + height: 36px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 7px; + border: 1px solid #e5e9f2; background: #fff; + color: #475569; + font-size: 0.88rem; + font-weight: 500; + cursor: pointer; + transition: all 0.18s; + padding: 0; +} + +.blog-page-num:hover:not(.active) { + border-color: #2f74ff; + color: #2f74ff; + background: #eff4ff; } -.pagination-number-item.active { - background: var(--ifm-color-primary); +.blog-page-num.active { + background: #2f74ff; color: #fff; - border-color: var(--ifm-color-primary); + border-color: #2f74ff; + box-shadow: 0 2px 8px rgba(47, 116, 255, 0.35); } -.pagination-nav-item.disabled { - color: #ccc; - border-color: #f3f4f6; - background: #fafafa; +/* ───────────────────────────────────────────────────────── + Empty state +───────────────────────────────────────────────────────── */ +.blog-empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 20px; + color: #94a3b8; + text-align: center; + gap: 12px; +} + +.blog-empty-state p { + font-size: 0.95rem; + margin: 0; +} + +/* ───────────────────────────────────────────────────────── + Responsive +───────────────────────────────────────────────────────── */ +@media (max-width: 900px) { + .blog-body-layout { + flex-direction: column; + } + + .blog-tag-sidebar { + flex: none; + width: 100%; + position: static; + order: -1; /* show above posts on mobile */ + } + + .blog-tag-sidebar-list { + max-height: none; + display: flex; + flex-wrap: wrap; + gap: 6px; + padding: 6px 18px 2px; + } + + .blog-tag-sidebar-item { + width: auto; + padding: 4px 12px; + border-radius: 20px; + border: 1px solid #e2e8f0; + border-left: 1px solid #e2e8f0; + } + + .blog-tag-sidebar-item:hover, + .blog-tag-sidebar-item.active { + border-color: #2f74ff; + border-left-color: #2f74ff; + } + + .blog-tag-sidebar-clear { + width: calc(100% - 36px); + } } @media (max-width: 768px) { - .custom-horizontal-card { + .blog-page-header { + flex-direction: column; + gap: 12px; + } + + .blog-page-title { + font-size: 1.6rem; + } + + .blog-filter-bar { + width: 100%; + } + + .blog-cat-btn { + flex: 1; + justify-content: center; + padding: 7px 12px; + } + + .blog-card { flex-direction: column !important; - height: auto !important; + min-height: auto; } - .card-left-img { + .blog-card-img-wrap { flex: 0 0 auto !important; - width: 100% !important; - border-right: none !important; - border-bottom: 1px solid #eee; - height: 200px; + height: 180px; } - .card-right-content { - padding: 16px !important; + .blog-card-img-placeholder { + min-height: 180px; } - .post-item-title { - font-size: 1.2rem !important; - margin-bottom: 8px !important; + .blog-card-body { + padding: 16px 18px; } - .post-item-tags { - margin-top: 12px; + .blog-card-title { + font-size: 1rem !important; } -} \ No newline at end of file + + .blog-pagination { + gap: 6px; + } + + .blog-page-nav { + padding: 7px 12px; + font-size: 0.8rem; + } +} + +/* ───────────────────────────────────────────────────────── + IvorySQL Footer Override +───────────────────────────────────────────────────────── */ +.footer--dark { + background: linear-gradient(180deg, #0d1b3e 0%, #091530 100%); + border-top: 1px solid rgba(47, 116, 255, 0.18); +} + +.footer--dark .footer__title { + color: rgba(200, 220, 255, 0.9); + font-weight: 600; + font-size: 0.85rem; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.footer--dark .footer__link-item { + color: rgba(160, 185, 220, 0.65); + font-size: 0.9rem; + line-height: 2; + transition: color 0.18s; +} + +.footer--dark .footer__link-item:hover { + color: #ffffff; + text-decoration: none; +} + +.footer--dark .footer__copyright { + color: rgba(130, 155, 195, 0.45); + font-size: 0.8rem; + border-top: 1px solid rgba(47, 116, 255, 0.12); + padding-top: 24px; + margin-top: 40px; +} + +.footer--dark .footer__logo-link { + opacity: 0.85; + transition: opacity 0.18s; +} + +.footer--dark .footer__logo-link:hover { + opacity: 1; +} diff --git a/src/pages/index.js b/src/pages/index.js index 5fe7fe8..984b120 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,118 +1,552 @@ +import clsx from 'clsx'; import Link from '@docusaurus/Link'; -import Translate from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Layout from '@theme/Layout'; -import clsx from 'clsx'; -import React, { useEffect } from 'react'; -import Slider from "react-slick"; -import RecruitPhone from "../../static/img/index-recruit-phone.jpg"; -import Recruit from "../../static/img/index-recruit.jpg"; -import indexbug from '../../static/img/indexbug.png'; -import indexbugphone from '../../static/img/indexbugphone.png'; -import Elephant from '../../svg/img-elephant-balloon.svg'; -import HOW from '../../static/img/ivorysql-how.jpg'; -import HomepageFeatures from '../components/HomepageFeatures'; +import React, { useEffect, useState } from 'react'; import styles from './index.module.css'; -import SliderIndex from './slider'; -import SliderBug from './slider-bug'; -import SliderBugPhone from './slider-bug-phone'; -import SliderPhoneIndex from './slider-phone'; -import { customFields } from '../../docusaurus.config'; -function HomepageHeader() { - const {siteConfig} = useDocusaurusContext(); - const settings = { - autoplay: true, - autoplaySpeed: 5000, - dots: true, - infinite: true, - slidesToShow: 1, - slidesToScroll: 1, - arrows: false, - }; - const { i18n } = useDocusaurusContext(); - const isEnglish = i18n.currentLocale === 'en'; + +const Icon01 = require('../../svg/icon-01.svg').default; +const Icon02 = require('../../svg/icon-02.svg').default; +const Icon03 = require('../../svg/icon-03.svg').default; +const Icon04 = require('../../svg/icon-04.svg').default; +const Icon05 = require('../../svg/icon-05.svg').default; +const Icon06 = require('../../svg/icon-06.svg').default; +const HeroElephant = require('../../svg/img-elephant-balloon.svg').default; + +const CoreAdvantageIcon = Icon01; +const ScenarioIcon = Icon03; +const EcosystemIcon = Icon02; +const CertificateIcon = Icon05; +const InstallDeployIcon = Icon04; + +const CORE_CARD_ICONS = [Icon01, Icon03, Icon04, Icon02, Icon05, Icon06, Icon01, Icon03]; +const SCENARIO_CARD_ICONS = [Icon04, Icon02, Icon06, Icon01, Icon05]; +const INSTALL_CARD_ICONS = [Icon04, Icon01, Icon06]; + +const RELEASES_URL = 'https://github.com/IvorySQL/IvorySQL/releases'; +const ONLINE_TRIAL_URL = 'https://trial.ivorysql.org/'; + +/* Trusted-by customer list — logo path optional; nameZh shown in zh locale */ +const TRUSTED_CUSTOMERS = [ + { name: 'Highgo', nameZh: '瀚高软件', logo: '/img/partners/highgo.png', logoZh: 'https://2025.pgconf.dev/static/logo/highgo.png', logoHeight: 36 }, + { name: 'Data Bene', logo: '/img/partners/databene.png' }, + { name: 'Ongres', logo: '/img/partners/ongres.png', logoHeight: 18 }, + { name: 'State Grid Corporation', nameZh: '国家电网', logo: '/img/partners/state-grid.png', logoHeight: 28 }, + { name: 'Zhongtai Securities', nameZh: '中泰证券', logo: '/img/partners/zhongtai-securities.png' }, + { name: 'Goldwind', nameZh: '金风科技', logo: '/img/partners/goldwind.png' }, +]; +const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/IvorySQL/IvorySQL/releases/latest'; +const LATEST_VERSION_CACHE_KEY = 'ivorysql_latest_release_label'; +const LATEST_VERSION_CACHE_TTL = 6 * 60 * 60 * 1000; + +// Tool metadata: description + homepage URL for hover tooltips (bilingual) +const TOOL_META = { + // Data Access Middleware + 'pgpool-II': { desc: 'Middleware proxy for PostgreSQL: connection pooling, load balancing, and automatic failover.', descZh: 'PostgreSQL 中间件代理,提供连接池、负载均衡和自动故障转移能力。', url: 'https://www.pgpool.net/' }, + 'pgBouncer': { desc: 'Ultra-lightweight connection pooler for PostgreSQL, minimizing connection overhead.', descZh: '超轻量级 PostgreSQL 连接池,大幅降低连接建立开销。', url: 'https://www.pgbouncer.org/' }, + 'odyssey': { desc: 'Advanced multi-threaded PostgreSQL connection pooler by Yandex, designed for high concurrency.', descZh: 'Yandex 开发的高性能多线程 PostgreSQL 连接池,专为高并发场景设计。', url: 'https://github.com/yandex/odyssey' }, + 'HAProxy': { desc: 'High-performance TCP/HTTP load balancer widely used for PostgreSQL read/write splitting.', descZh: '高性能 TCP/HTTP 负载均衡器,常用于 PostgreSQL 读写分离架构。', url: 'https://www.haproxy.org/' }, + 'ShardingSphere': { desc: 'Apache distributed database ecosystem providing sharding, scaling, and encryption for PostgreSQL.', descZh: 'Apache 分布式数据库生态,为 PostgreSQL 提供分库分表、弹性伸缩和数据加密能力。', url: 'https://shardingsphere.apache.org/' }, + 'Citus': { desc: 'Distributed PostgreSQL extension that horizontally scales your database across multiple nodes.', descZh: 'PostgreSQL 分布式扩展,通过水平分片将数据库扩展到多个节点。', url: 'https://www.citusdata.com/' }, + 'vip-manager': { desc: 'Manages virtual IP addresses for PostgreSQL HA clusters, ensuring seamless failover.', descZh: '为 PostgreSQL 高可用集群管理虚拟 IP,确保故障切换时业务无感知。', url: 'https://github.com/Cybertec-PostgreSQL/vip-manager' }, + // ORM + 'MyBatis': { desc: 'Java SQL mapping framework that eliminates boilerplate JDBC code with flexible SQL control.', descZh: 'Java SQL 映射框架,以灵活的 SQL 控制方式消除繁琐的 JDBC 样板代码。', url: 'https://mybatis.org/' }, + 'Hibernate': { desc: 'Powerful Java ORM framework with full PostgreSQL and JPQL support.', descZh: '强大的 Java ORM 框架,全面支持 PostgreSQL 和 JPQL 查询语言。', url: 'https://hibernate.org/' }, + // Standard SQL & Drivers + 'libpq': { desc: 'Official C client library for PostgreSQL, the foundation for most language drivers.', descZh: 'PostgreSQL 官方 C 客户端库,是大多数语言驱动的底层基础。', url: 'https://www.postgresql.org/docs/current/libpq.html' }, + 'JDBC': { desc: 'Official Java Database Connectivity driver for PostgreSQL (pgjdbc).', descZh: 'PostgreSQL 官方 Java 数据库连接驱动(pgjdbc)。', url: 'https://jdbc.postgresql.org/' }, + 'ODBC': { desc: 'psqlODBC — official PostgreSQL ODBC driver for Windows and Linux applications.', descZh: 'psqlODBC — 适用于 Windows 和 Linux 应用程序的官方 PostgreSQL ODBC 驱动。', url: 'https://odbc.postgresql.org/' }, + 'psycopg2': { desc: 'Most popular PostgreSQL adapter for Python, featuring full async support.', descZh: '最流行的 Python PostgreSQL 适配器,支持完整的异步操作。', url: 'https://www.psycopg.org/' }, + 'ADO.NET': { desc: 'Npgsql — high-performance .NET data provider for PostgreSQL with EF Core support.', descZh: 'Npgsql — 高性能 .NET PostgreSQL 数据提供器,支持 Entity Framework Core。', url: 'https://www.npgsql.org/' }, + 'lib/pq': { desc: 'Pure Go PostgreSQL driver (legacy), compatible with database/sql standard interface.', descZh: '纯 Go 实现的 PostgreSQL 驱动(经典版),兼容 database/sql 标准接口。', url: 'https://github.com/lib/pq' }, + 'pgx': { desc: 'High-performance PostgreSQL driver for Go with low-level protocol access.', descZh: '高性能 Go 语言 PostgreSQL 驱动,支持底层协议直接访问。', url: 'https://github.com/jackc/pgx' }, + 'Ruby': { desc: 'pg gem — the official Ruby interface to PostgreSQL.', descZh: 'pg gem — Ruby 访问 PostgreSQL 的官方接口库。', url: 'https://github.com/ged/ruby-pg' }, + 'Rust': { desc: 'rust-postgres — native PostgreSQL driver for Rust, with tokio async support.', descZh: 'rust-postgres — 原生 Rust PostgreSQL 驱动,支持 tokio 异步运行时。', url: 'https://github.com/sfackler/rust-postgres' }, + // Client Tools + 'DBeaver': { desc: 'Universal multi-database GUI management tool with ERD, SQL editor, and data export.', descZh: '通用多数据库 GUI 管理工具,内置 ER 图、SQL 编辑器和数据导出功能。', url: 'https://dbeaver.io/' }, + 'pgAdmin': { desc: 'Official open-source PostgreSQL administration and management web application.', descZh: 'PostgreSQL 官方开源管理工具,提供完整的数据库管理与监控功能。', url: 'https://www.pgadmin.org/' }, + 'Navicat': { desc: 'Professional GUI tool for PostgreSQL with visual query builder and data modeling.', descZh: '专业的 PostgreSQL GUI 工具,提供可视化查询构建器和数据建模功能。', url: 'https://www.navicat.com/' }, + 'Navicat Premium': { desc: 'Multi-connection GUI tool supporting PostgreSQL, MySQL, Oracle, and more simultaneously.', descZh: '多连接 GUI 工具,可同时管理 PostgreSQL、MySQL、Oracle 等多种数据库。', url: 'https://www.navicat.com/en/products/navicat-premium' }, + // Backup & HA + 'pg_rman': { desc: 'Online backup and recovery manager for PostgreSQL with PITR support.', descZh: 'PostgreSQL 在线备份与恢复管理器,支持时间点恢复(PITR)。', url: 'https://github.com/ossc-db/pg_rman' }, + 'WAL-G': { desc: 'Fast cloud-native backup tool using cloud storage (S3, GCS, Azure) with delta compression.', descZh: '云原生备份工具,支持 S3/GCS/Azure 存储,具备增量压缩能力。', url: 'https://github.com/wal-g/wal-g' }, + 'pg_probackup': { desc: 'Backup and recovery solution for PostgreSQL with parallel processing and incremental backups.', descZh: 'PostgreSQL 备份与恢复方案,支持并行处理和增量备份。', url: 'https://github.com/postgrespro/pg_probackup' }, + 'pgBackRest': { desc: 'Reliable, feature-rich backup solution with parallel restore and cloud storage support.', descZh: '功能丰富的可靠备份方案,支持并行恢复和云存储对接。', url: 'https://pgbackrest.org/' }, + // Cluster Management + 'Patroni': { desc: 'HA template for PostgreSQL using DCS (etcd/Consul/ZooKeeper) for automatic failover.', descZh: '基于 DCS(etcd/Consul/ZooKeeper)的 PostgreSQL 高可用模板,实现自动故障转移。', url: 'https://patroni.readthedocs.io/' }, + 'repmgr': { desc: 'Replication manager for PostgreSQL: manages streaming replication and switchover.', descZh: 'PostgreSQL 复制管理器,负责流复制管理和主从切换。', url: 'https://repmgr.org/' }, + 'Pacemaker Corosync': { desc: 'Open-source cluster resource manager providing HA for PostgreSQL and other services.', descZh: '开源集群资源管理器,为 PostgreSQL 等服务提供高可用保障。', url: 'https://clusterlabs.org/' }, + // Monitoring + 'Prometheus': { desc: 'Open-source monitoring and alerting toolkit; pairs with pg_exporter for PostgreSQL metrics.', descZh: '开源监控与告警工具包,配合 pg_exporter 采集 PostgreSQL 指标。', url: 'https://prometheus.io/' }, + 'Alertmanager': { desc: 'Handles alerts from Prometheus, routing notifications to email, Slack, PagerDuty, etc.', descZh: '处理 Prometheus 告警,将通知路由至邮件、Slack、PagerDuty 等渠道。', url: 'https://prometheus.io/docs/alerting/latest/alertmanager/' }, + 'pgMonitor': { desc: 'Pre-configured PostgreSQL monitoring stack by Crunchy Data using Prometheus and Grafana.', descZh: 'Crunchy Data 提供的预配置 PostgreSQL 监控方案,基于 Prometheus 和 Grafana。', url: 'https://github.com/CrunchyData/pgmonitor' }, + 'Grafana': { desc: 'Observability and data visualization platform for dashboards and alerting.', descZh: '可观测性与数据可视化平台,用于构建监控大屏和告警规则。', url: 'https://grafana.com/' }, + 'PoWA': { desc: 'PostgreSQL Workload Analyzer — query performance insights with historical data.', descZh: 'PostgreSQL 工作负载分析器,基于历史数据提供查询性能洞察。', url: 'https://powa.readthedocs.io/' }, + // Heterogeneous Access + 'Debezium': { desc: 'CDC platform for capturing row-level database change events in real time.', descZh: '变更数据捕获(CDC)平台,实时捕获数据库行级变更事件。', url: 'https://debezium.io/' }, + 'pglogical': { desc: 'Logical replication extension for PostgreSQL supporting selective table replication.', descZh: 'PostgreSQL 逻辑复制扩展,支持按需选择性地复制指定表。', url: 'https://github.com/2ndQuadrant/pglogical' }, + 'mysql_fdw': { desc: 'PostgreSQL Foreign Data Wrapper for accessing MySQL tables directly from PostgreSQL.', descZh: 'PostgreSQL 外部数据包装器,可直接在 PostgreSQL 中查询 MySQL 表。', url: 'https://github.com/EnterpriseDB/mysql_fdw' }, + 'oracle_fdw': { desc: 'PostgreSQL Foreign Data Wrapper for querying Oracle databases transparently.', descZh: 'PostgreSQL 外部数据包装器,透明访问 Oracle 数据库中的数据。', url: 'https://github.com/laurenz/oracle_fdw' }, + // Multi-Model + 'TimescaleDB': { desc: 'Time-series database built on PostgreSQL with automatic partitioning and compression.', descZh: '基于 PostgreSQL 的时序数据库,具备自动分区和数据压缩能力。', url: 'https://www.timescale.com/' }, + 'DocumentDB': { desc: 'Open-source document database compatible with MongoDB wire protocol, built on PostgreSQL.', descZh: '开源文档数据库,兼容 MongoDB 协议,以 PostgreSQL 为存储引擎。', url: 'https://github.com/microsoft/documentdb' }, + 'PostgreSQL AGE': { desc: 'Apache AGE — graph database extension for PostgreSQL supporting openCypher queries.', descZh: 'Apache AGE — PostgreSQL 图数据库扩展,支持 openCypher 图查询语言。', url: 'https://age.apache.org/' }, + 'FerretDB': { desc: 'MongoDB-compatible backend using PostgreSQL for storage, enabling Mongo drivers to work.', descZh: '以 PostgreSQL 为存储层的 MongoDB 兼容后端,让 Mongo 驱动开箱即用。', url: 'https://www.ferretdb.com/' }, + // Geospatial + 'PostGIS': { desc: 'Adds spatial and geographic object support to PostgreSQL, the gold standard for GIS.', descZh: '为 PostgreSQL 添加空间与地理对象支持,是 GIS 领域的事实标准。', url: 'https://postgis.net/' }, + 'pgRouting': { desc: 'Geospatial routing extension extending PostGIS for path-finding and network analysis.', descZh: '扩展 PostGIS 的地理路由插件,支持最短路径与网络分析。', url: 'https://pgrouting.org/' }, + // ML & AI + 'pgvector': { desc: 'Open-source vector similarity search for PostgreSQL, ideal for AI embeddings and RAG.', descZh: '开源 PostgreSQL 向量相似度搜索扩展,专为 AI 嵌入和 RAG 场景设计。', url: 'https://github.com/pgvector/pgvector' }, + 'MADlib': { desc: 'Apache MADlib — in-database machine learning library for scalable analytics.', descZh: 'Apache MADlib — 数据库内机器学习库,支持大规模分析计算。', url: 'https://madlib.apache.org/' }, + // DDL & Loading + 'pg_bulkload': { desc: 'High-speed data loading tool for PostgreSQL, bypassing WAL for maximum throughput.', descZh: '高速 PostgreSQL 数据加载工具,绕过 WAL 日志以获得最大吞吐量。', url: 'https://github.com/ossc-db/pg_bulkload' }, + 'ddlx': { desc: 'PostgreSQL extension to extract clean, executable DDL scripts from database objects.', descZh: 'PostgreSQL 扩展,从数据库对象中提取干净、可执行的 DDL 脚本。', url: 'https://github.com/lacanoid/pgddl' }, + // Online Demo + 'postgres-wasm': { desc: 'PostgreSQL compiled to WebAssembly — run a full database in your browser, zero install.', descZh: 'PostgreSQL 的 WebAssembly 编译版本,无需安装即可在浏览器中运行完整数据库。', url: 'https://github.com/snaplet/postgres-wasm' }, + // Job Scheduling + 'pg_cron': { desc: 'Cron-based job scheduler for PostgreSQL, running SQL commands on a schedule inside the DB.', descZh: '基于 Cron 的 PostgreSQL 作业调度器,可在数据库内部按计划执行 SQL 命令。', url: 'https://github.com/citusdata/pg_cron' }, + 'pgAgent': { desc: 'Job scheduling agent for PostgreSQL integrated with pgAdmin for scheduled tasks.', descZh: 'PostgreSQL 作业调度代理,与 pgAdmin 深度集成,方便管理定时任务。', url: 'https://www.pgadmin.org/docs/pgadmin4/latest/pgagent.html' }, + // Ecosystem Partnerships + 'StackGres': { desc: 'Production-grade PostgreSQL on Kubernetes with automated ops, monitoring, and backups.', descZh: '生产级 Kubernetes 上的 PostgreSQL 方案,自动化运维、监控和备份一体化。', url: 'https://stackgres.io/' }, + 'Databene': { desc: 'Database testing and synthetic data generation framework for regression and performance tests.', descZh: '数据库测试与合成数据生成框架,用于回归测试和性能基准测试。', url: 'https://databene.org/' }, + // Migration + 'Ora2Pg': { desc: 'Free open-source tool for migrating Oracle database schemas and data to PostgreSQL.', descZh: '免费开源的 Oracle 到 PostgreSQL 迁移工具,支持 Schema 和数据全量迁移。', url: 'https://ora2pg.darold.net/' }, + // Cloud + 'Docker Compose': { desc: 'Define and run multi-container applications; official IvorySQL Docker images available.', descZh: '多容器应用编排工具,IvorySQL 官方提供 Docker 镜像支持。', url: 'https://docs.docker.com/compose/' }, + 'Podman': { desc: 'Daemonless, rootless container engine fully compatible with Docker images and compose files.', descZh: '无守护进程、无 root 权限的容器引擎,完全兼容 Docker 镜像和 Compose 文件。', url: 'https://podman.io/' }, + 'Docker Swarm': { desc: 'Native Docker clustering for deploying IvorySQL in a replicated, highly available setup.', descZh: 'Docker 原生集群方案,用于以高可用、多副本方式部署 IvorySQL。', url: 'https://docs.docker.com/engine/swarm/' }, +}; + +const ECOSYSTEM_TOOL_STATUS = { + progress: new Set(['citus', 'pg_ai_query', 'stackgres', 'databene', 'madlib']), + planned: new Set(['shardingsphere', 'pacemaker corosync', 'postgresql age', 'yukon', 'powa']), + proprietary: new Set(['ivymigration', 'ivyevaluation', 'ivorysql serverless']), +}; + +function normalizeToolName(toolName) { + return toolName.replace(/\u200c/g, '').toLowerCase().trim(); +} + +function getEcosystemToolTone(toolName) { + const normalizedName = normalizeToolName(toolName); + if (ECOSYSTEM_TOOL_STATUS.proprietary.has(normalizedName)) { + return 'proprietary'; + } + if (ECOSYSTEM_TOOL_STATUS.progress.has(normalizedName)) { + return 'progress'; + } + if (ECOSYSTEM_TOOL_STATUS.planned.has(normalizedName)) { + return 'planned'; + } + return 'supported'; +} + +function formatLatestReleaseLabel(release, fallbackLabel) { + const source = `${release?.name || ''} ${release?.tag_name || ''}`; + const versionMatch = source.match(/(\d+(?:\.\d+){1,2})/); + if (versionMatch) { + return `IvorySQL ${versionMatch[1]}`; + } + const cleaned = (release?.name || release?.tag_name || '').trim(); + return cleaned || fallbackLabel; +} + +function readLatestVersionFromCache() { + if (typeof window === 'undefined') { + return null; + } + + try { + const rawCache = window.localStorage.getItem(LATEST_VERSION_CACHE_KEY); + if (!rawCache) { + return null; + } + const parsedCache = JSON.parse(rawCache); + if (!parsedCache?.label || !parsedCache?.time) { + return null; + } + if (Date.now() - parsedCache.time > LATEST_VERSION_CACHE_TTL) { + return null; + } + return parsedCache.label; + } catch { + return null; + } +} + +function writeLatestVersionToCache(label) { + if (typeof window === 'undefined') { + return; + } + + try { + window.localStorage.setItem( + LATEST_VERSION_CACHE_KEY, + JSON.stringify({ + label, + time: Date.now(), + }), + ); + } catch { + // Ignore storage failures in private mode / restricted environments. + } +} + +const CONTENT = { + zh: { + slogan: '一款开源的兼容 Oracle 的 PostgreSQL', + intro: + 'IvorySQL 是一款先进、功能齐全的开源 Oracle 兼容 PostgreSQL,致力于保持高兼容性,并可作为最新 PostgreSQL 的完全替代品。通过 compatible_mode 开关可在 Oracle 与 PostgreSQL 兼容模式间切换,PL/iSQL 支持 Oracle PL/SQL 语法及 Oracle 风格包(Packages)。', + heroBadges: ['Oracle 兼容', 'Apache 2.0 开源', '基于 PostgreSQL 内核'], + latestVersionPrefix: '最新版本', + latestVersionLabel: 'IvorySQL 5.1', + actions: [ + { label: '免费下载', to: '/releases-page', ariaLabel: '免费下载 IvorySQL' }, + { label: '在线体验', href: ONLINE_TRIAL_URL, ariaLabel: '在线体验 IvorySQL' }, + { label: '最新活动', to: '/webinars-page', ariaLabel: '查看 IvorySQL 最新活动' }, + ], + heroTrustLabel: '受到众多企业信赖', + statsItems: [ + { value: 'PostgreSQL 18', label: '内核版本' }, + { value: 'Apache 2.0', label: '开源协议' }, + { value: '55+', label: '生态工具' }, + { value: 'Oracle 兼容', label: '无缝迁移' }, + ], + oracleShowcase: { + title: '让 Oracle 代码直接运行', + subtitle: '深度 Oracle 兼容', + points: [ + 'PL/iSQL 支持 Oracle PL/SQL 过程语言语法', + 'ivorysql_ora 插件提供 Oracle 内置函数', + 'compatible_mode 开关随时切换兼容模式', + '支持 Oracle 风格的 Package 包体结构', + ], + cta: '查看迁移指南', + ctaTo: 'https://docs.ivorysql.org/en/ivorysql-doc/v5.3/4.5', + }, + coreTitle: 'IvorySQL 核心优势', + coreDesc: '从内核兼容到生态扩展,提供面向企业生产环境的数据库能力。', + coreItems: [ + { + title: '核心开源', + description: '采用 Apache 2.0 协议开源,无厂商限制,代码透明且支持定制化开发。', + }, + { + title: '深度 Oracle 兼容', + description: '通过 PL/iSQL 过程语言和 ivorysql_ora 插件实现 PL/SQL 语法兼容,支持 Oracle 数据库迁移。', + }, + { + title: '国产化全平台兼容', + description: '全面兼容国内外主流软硬件,兼容国产芯片架构和操作系统,提供全平台介质包确保便捷部署。', + }, + { + title: '云原生支持', + description: '容器化方案覆盖 Docker Compose/Swarm、K8S Operator 及云服务平台。', + }, + { + title: '企业级支持', + description: '由瀚高股份提供技术支持,并在多个企业生产环境落地。', + }, + { + title: '生态融合', + description: '继承 PostgreSQL 完整 SQL 能力、可靠性和丰富生态组件。', + }, + { + title: '场景覆盖广', + description: '覆盖企业数据库、LBS、数据仓库、建站开发、数据库迁移等核心场景。', + }, + { + title: '易用性强', + description: '降低系统管理成本,提供开发者友好接口和第三方工具集成能力。', + }, + ], + scenariosTitle: 'IvorySQL 应用场景', + scenariosDesc: '覆盖从交易系统到分析平台的典型数据库工作负载。', + scenarioItems: [ + { + title: '企业数据库', + description: '适用于 ERP、交易系统、财务系统等对高可用和复杂业务逻辑有要求的场景。', + }, + { + title: 'LBS 应用', + description: '支持地理空间查询(如 O2O、游戏地图),通过 PostGIS 实现位置服务。', + }, + { + title: '数据仓库 / 大数据', + description: '利用丰富数据类型和计算能力搭建分析平台。', + }, + { + title: '建站 / App 开发', + description: '依托高性能能力提升网站与应用效率。', + }, + { + title: '数据库迁移', + description: '支持将 Oracle 数据库迁移到 IvorySQL。', + }, + ], + installTitle: 'IvorySQL 安装部署', + installDesc: + '结合官网文档与版本发布信息,提供从快速上手到生产部署的清晰路径,可按环境选择包安装、源码构建或容器化部署。', + installItems: [ + { + title: '快速安装(推荐)', + description: '通过官方安装文档完成依赖准备、实例初始化和服务启动,适合首次体验与标准化部署。', + action: { label: '查看安装文档', to: '/docs-installation' }, + }, + { + title: '版本与介质包安装', + description: '在 Releases 页面查看当前稳定版本与历史版本,并根据系统环境选择对应安装介质包。', + action: { label: '查看 Releases', to: '/releases-page' }, + }, + { + title: '容器化部署', + description: '基于官方 Docker 仓库进行镜像部署,便于在开发测试、CI/CD 与云原生环境中快速落地。', + action: { label: '查看 Docker 仓库', href: 'https://github.com/IvorySQL/docker_library' }, + }, + ], + ecosystemTitle: 'IvorySQL 及周边工具生态', + ecosystemDesc: + '社区提供丰富的生态工具:客户端工具、高可用工具、云原生工具、监控运维工具、备份恢复工具、地理信息工具等。', + ecosystemGroups: [ + { title: '数据访问中间件', items: ['pgpool-II', 'pgBouncer', 'odyssey', 'HAProxy', 'ShardingSphere', 'Citus', 'vip-manager'], wide: true }, + { title: 'ORM', items: ['Go', 'NodeJS', 'MyBatis', 'Hibernate'] }, + { title: '标准 SQL 及驱动', items: ['libpq', 'JDBC', 'ODBC', 'NodeJS', 'psycopg2', 'Go', 'Python', 'Rust', 'Ruby', 'ADO.NET', 'lib/pq', 'pgx'], wide: true }, + { title: '客户端工具', items: ['DBeaver', 'pgAdmin', 'Navicat', 'Navicat Premium'] }, + { title: '内核扩展', items: ['Oracle 兼容', 'PG 兼容及跟进'] }, + { title: '高可靠', items: ['pg_rman', 'WAL-G', 'pg_probackup', 'pgBackRest'] }, + { title: '集群工具', items: ['Patroni', 'repmgr', 'Pacemaker Corosync'] }, + { title: '监控运维', items: ['Prometheus', 'Alertmanager', 'pgMonitor', 'Grafana', 'PoWA'] }, + { title: '异构数据库访问工具', items: ['Debezium', 'pglogical', 'mysql_fdw', 'oracle_fdw'] }, + { title: '多模数据库', items: ['TimescaleDB', 'DocumentDB', 'PostgreSQL AGE', 'FerretDB'] }, + { title: '地理信息', items: ['PostGIS', 'pgRouting'] }, + { title: '机器学习及 AI', items: ['pgvector', 'MADlib', 'pg_ai_query'] }, + { title: 'DDL 及数据加载工具', items: ['pg_bulkload', 'ddlx'] }, + { title: '在线体验平台', items: ['postgres-wasm', 'IVYOnlineTrial'] }, + { title: '定时任务工具', items: ['pg_cron', 'pgAgent', 'pg_jobs'] }, + { title: '生态合作', items: ['Yukon', 'StackGres', 'Databene', 'WhaleOps'] }, + { title: '迁移/评估工具', items: ['Ora2Pg', 'ivyMigration', 'ivyEvaluation'] }, + { + title: '云生态', + items: ['Docker Compose', 'Podman', 'Docker Swarm', 'IvorySQL Cloud', 'IvorySQL Operator', 'IvorySQL Serverless'], + }, + ], + ecosystemCategories: [ + { title: '连接与分发层', desc: '连接池、负载均衡与水平分片', accent: 'blue', tools: ['pgpool-II', 'pgBouncer', 'odyssey', 'HAProxy', 'ShardingSphere', 'Citus', 'vip-manager'] }, + { title: '高可用与备份', desc: '集群管理、自动故障转移与时间点恢复', accent: 'teal', tools: ['Patroni', 'repmgr', 'Pacemaker Corosync', 'StackGres', 'pg_rman', 'WAL-G', 'pg_probackup', 'pgBackRest', 'Docker Compose', 'Podman', 'Docker Swarm'] }, + { title: '开发者工具与驱动', desc: '图形客户端、ORM 框架与多语言驱动', accent: 'indigo', tools: ['DBeaver', 'pgAdmin', 'Navicat', 'Navicat Premium', 'MyBatis', 'Hibernate', 'libpq', 'JDBC', 'ODBC', 'psycopg2', 'pgx', 'ADO.NET', 'lib/pq', 'Ruby', 'Rust', 'Go', 'NodeJS', 'Python'] }, + { title: '监控与运维', desc: '指标采集、可视化大屏与查询性能分析', accent: 'amber', tools: ['Prometheus', 'Alertmanager', 'pgMonitor', 'Grafana', 'PoWA', 'pg_cron', 'pgAgent', 'pg_jobs'] }, + { title: '数据集成与迁移', desc: 'CDC 变更捕获、异构数据访问与 Oracle 迁移', accent: 'purple', tools: ['Debezium', 'pglogical', 'mysql_fdw', 'oracle_fdw', 'Ora2Pg', 'ivyMigration', 'ivyEvaluation', 'pg_bulkload', 'ddlx', 'Yukon', 'Databene', 'WhaleOps'] }, + { title: 'AI、地理与多模型', desc: '向量检索、时序、地理空间与图数据库扩展', accent: 'rose', tools: ['pgvector', 'MADlib', 'pg_ai_query', 'PostGIS', 'pgRouting', 'TimescaleDB', 'DocumentDB', 'PostgreSQL AGE', 'FerretDB'] }, + ], + ecosystemFooters: [ + '操作系统(windows / CentOS / Redhat / ubuntu / openEuler / 银河麒麟 / 统信 UOS 等)', + 'x86、鲲鹏、龙芯、兆芯、申威、海光、飞腾、MIPS、RISC-V', + ], + ecosystemLegend: [ + { label: '已支持', tone: 'supported' }, + { label: '正在支持', tone: 'progress' }, + { label: '未来支持', tone: 'planned' }, + { label: '闭源产品', tone: 'proprietary' }, + ], + compatibilityTitle: 'IvorySQL 兼容认证', + compatibilityDesc: '更多兼容认证与生态合作信息,请查看合作伙伴页面。', + }, + en: { + slogan: 'The Open-Source PostgreSQL for Seamless Oracle Compatibility.', + intro: + 'Bridge the gap between Oracle and PostgreSQL with IvorySQL. Experience a robust, open-source database that combines the power of PostgreSQL with native Oracle syntax support, PL/SQL compatibility, and enterprise-grade performance. Migrate faster, lower costs, and scale with confidence.', + heroBadges: ['Oracle Compatibility', 'Apache 2.0 Open-Source', 'Built on PostgreSQL'], + latestVersionPrefix: 'Latest Version', + latestVersionLabel: 'IvorySQL 5.1', + actions: [ + { label: 'Free Download', to: '/releases-page', ariaLabel: 'Free Download IvorySQL' }, + { label: 'Online Trial', href: ONLINE_TRIAL_URL, ariaLabel: 'Try IvorySQL Online' }, + { label: 'Latest Webinars', to: '/webinars-page', ariaLabel: 'View Latest IvorySQL Webinars' }, + ], + heroTrustLabel: 'Trusted by enterprises worldwide', + statsItems: [ + { value: 'PostgreSQL 18', label: 'Kernel Base' }, + { value: 'Apache 2.0', label: 'Open Source' }, + { value: '55+', label: 'Ecosystem Tools' }, + { value: 'Oracle SQL', label: 'Natively Compatible' }, + ], + oracleShowcase: { + title: 'Run Oracle Code. No Rewrite.', + subtitle: 'Oracle Compatibility', + points: [ + 'PL/iSQL supports Oracle PL/SQL procedural syntax natively', + 'ivorysql_ora plugin provides Oracle built-in functions', + 'compatible_mode switch toggles compatibility on the fly', + 'Oracle-style Package structures supported out of the box', + ], + cta: 'View Migration Guide', + ctaTo: 'https://docs.ivorysql.org/en/ivorysql-doc/v5.3/4.5', + }, + coreTitle: 'Core Advantages', + coreDesc: 'From kernel compatibility to ecosystem integration, built for production workloads.', + coreItems: [ + { + title: 'Open Source Core', + description: 'Apache 2.0 licensed with no vendor lock-in, transparent code, and easy customization.', + }, + { + title: 'Deep Oracle Compatibility', + description: 'PL/iSQL and the ivorysql_ora extension provide strong PL/SQL compatibility for Oracle migrations.', + }, + { + title: 'Full-Platform Compatibility', + description: 'Compatible with mainstream hardware and operating systems, including domestic chip architectures.', + }, + { + title: 'Cloud-Native Support', + description: 'Container-ready support across Docker Compose/Swarm, K8S Operator, and cloud platforms.', + }, + { + title: 'Enterprise Support', + description: 'Backed by HighGo and validated in production-grade enterprise deployments.', + }, + { + title: 'Ecosystem Integration', + description: 'Inherits PostgreSQL SQL completeness, reliability, and ecosystem extensibility.', + }, + { + title: 'Broad Scenario Coverage', + description: 'Covers enterprise workloads, LBS, data warehousing, web/app development, and migrations.', + }, + { + title: 'Easy to Use', + description: 'Reduces management overhead with developer-friendly interfaces and third-party integration.', + }, + ], + scenariosTitle: 'Application Scenarios', + scenariosDesc: 'Supports mainstream database workloads from OLTP systems to analytical platforms.', + scenarioItems: [ + { + title: 'Enterprise Databases', + description: 'Fits ERP, transaction systems, and finance systems requiring high availability and complex logic.', + }, + { + title: 'LBS Applications', + description: 'Supports geospatial workloads such as O2O and game maps through PostGIS.', + }, + { + title: 'Data Warehouse / Big Data', + description: 'Build analytical platforms with rich data types and robust processing capabilities.', + }, + { + title: 'Websites / App Development', + description: 'Improves website and application efficiency with high-performance database capabilities.', + }, + { + title: 'Database Migration', + description: 'Enables direct migration paths from Oracle databases to IvorySQL.', + }, + ], + installTitle: 'IvorySQL Installation & Deployment', + installDesc: + 'Based on official docs and release resources, choose package installation, source build, or container deployment to match your environment.', + installItems: [ + { + title: 'Quick Installation (Recommended)', + description: + 'Follow the official installation guide to prepare dependencies, initialize clusters, and start services quickly.', + action: { label: 'Installation Guide', to: '/docs-installation' }, + }, + { + title: 'Packages & Releases', + description: + 'Use the Releases page to check stable/historical versions and pick proper installation packages for your platform.', + action: { label: 'View Releases', to: '/releases-page' }, + }, + { + title: 'Container Deployment', + description: + 'Use the official Docker repository for fast setup in development, CI/CD pipelines, and cloud-native environments.', + action: { label: 'Docker Repository', href: 'https://github.com/IvorySQL/docker_library' }, + }, + ], + ecosystemTitle: 'IvorySQL Ecosystem & Tools', + ecosystemDesc: + 'The community provides a rich ecosystem of tools, including client tools, high availability tools, cloud-native tools, monitoring and operations tools, backup and recovery tools, and geospatial tools.', + ecosystemGroups: [ + { + title: 'Data Access Middleware', + items: ['pgpool-II', 'pgBouncer', 'odyssey', 'HAProxy', 'ShardingSphere', 'Citus', 'vip-manager'], + wide: true, + }, + { title: 'ORM', items: ['Go', 'NodeJS', 'MyBatis', 'Hibernate'] }, + { + title: 'Standard SQL & Drivers', + items: ['libpq', 'JDBC', 'ODBC', 'NodeJS', 'psycopg2', 'Go', 'Python', 'Rust', 'Ruby', 'ADO.NET', 'lib/pq', 'pgx'], + wide: true, + }, + { title: 'Client Tools', items: ['DBeaver', 'pgAdmin', 'Navicat', 'Navicat Premium'] }, + { title: 'Core Extensions', items: ['Oracle Compatibility', 'PG Compatibility & Upstream Tracking'] }, + { title: 'High Availability', items: ['pg_rman', 'WAL-G', 'pg_probackup', 'pgBackRest'] }, + { title: 'Cluster Management Tools', items: ['Patroni', 'repmgr', 'Pacemaker Corosync'] }, + { title: 'Monitoring & Operations', items: ['Prometheus', 'Alertmanager', 'pgMonitor', 'Grafana', 'PoWA'] }, + { title: 'Heterogeneous Access Tools', items: ['Debezium', 'pglogical', 'mysql_fdw', 'oracle_fdw'] }, + { title: 'Multi-Model Database', items: ['TimescaleDB', 'DocumentDB', 'PostgreSQL AGE', 'FerretDB'] }, + { title: 'Geospatial', items: ['PostGIS', 'pgRouting'] }, + { title: 'Machine Learning & AI', items: ['pgvector', 'MADlib', 'pg_ai_query'] }, + { title: 'DDL & Data Loading Tools', items: ['pg_bulkload', 'ddlx'] }, + { title: 'Online Demo Platform', items: ['postgres-wasm', 'IVYOnlineTrial'] }, + { title: 'Job Scheduling Tools', items: ['pg_cron', 'pgAgent', 'pg_jobs'] }, + { title: 'Ecosystem Partnerships', items: ['Yukon', 'StackGres', 'Databene', 'WhaleOps'] }, + { title: 'Migration & Assessment Tools', items: ['Ora2Pg', 'ivyMigration', 'ivyEvaluation'] }, + { + title: 'Cloud Ecosystem', + items: ['Docker Compose', 'Podman', 'Docker Swarm', 'IvorySQL Cloud', 'IvorySQL Operator', 'IvorySQL Serverless'], + }, + ], + ecosystemCategories: [ + { title: 'Connectivity & Pooling', desc: 'Connection pooling, load balancing & horizontal sharding', accent: 'blue', tools: ['pgpool-II', 'pgBouncer', 'odyssey', 'HAProxy', 'ShardingSphere', 'Citus', 'vip-manager'] }, + { title: 'High Availability & Backup', desc: 'Cluster management, automatic failover & point-in-time recovery', accent: 'teal', tools: ['Patroni', 'repmgr', 'Pacemaker Corosync', 'StackGres', 'pg_rman', 'WAL-G', 'pg_probackup', 'pgBackRest', 'Docker Compose', 'Podman', 'Docker Swarm'] }, + { title: 'Developer Tools & Drivers', desc: 'GUI clients, ORM frameworks & multi-language database drivers', accent: 'indigo', tools: ['DBeaver', 'pgAdmin', 'Navicat', 'Navicat Premium', 'MyBatis', 'Hibernate', 'libpq', 'JDBC', 'ODBC', 'psycopg2', 'pgx', 'ADO.NET', 'lib/pq', 'Ruby', 'Rust', 'Go', 'NodeJS', 'Python'] }, + { title: 'Monitoring & Operations', desc: 'Metrics collection, dashboards & query performance analysis', accent: 'amber', tools: ['Prometheus', 'Alertmanager', 'pgMonitor', 'Grafana', 'PoWA', 'pg_cron', 'pgAgent', 'pg_jobs'] }, + { title: 'Data Integration & Migration', desc: 'CDC, heterogeneous access & Oracle-to-PostgreSQL migration', accent: 'purple', tools: ['Debezium', 'pglogical', 'mysql_fdw', 'oracle_fdw', 'Ora2Pg', 'ivyMigration', 'ivyEvaluation', 'pg_bulkload', 'ddlx', 'Yukon', 'Databene', 'WhaleOps'] }, + { title: 'AI, Geo & Multi-Model', desc: 'Vector search, time-series, geospatial & graph extensions', accent: 'rose', tools: ['pgvector', 'MADlib', 'pg_ai_query', 'PostGIS', 'pgRouting', 'TimescaleDB', 'DocumentDB', 'PostgreSQL AGE', 'FerretDB'] }, + ], + ecosystemFooters: [ + 'Operating System (windows / CentOS / Redhat / ubuntu / openEuler / kylin OS / UnionTech OS)', + 'x86 / Kunpeng / LoongArch / Zhaoxin / Sunway / Hygon / Phytium / MIPS / RISC-V', + ], + ecosystemLegend: [ + { label: 'Supported', tone: 'supported' }, + { label: 'Support In Progress', tone: 'progress' }, + { label: 'Support Planned', tone: 'planned' }, + { label: 'Proprietary Software', tone: 'proprietary' }, + ], + compatibilityTitle: 'IvorySQL Compatibility Certificates', + compatibilityDesc: 'See more compatibility certificates and ecosystem partnerships on the partners page.', + }, +}; + +function ActionLink({ action, className }) { + if (action.href) { + return ( + + {action.label} + + ); + } return ( -
- - {/* HOW 大会宣传,根据中英版显示不同图片及链接*/} -
- - IvorySQL Banner - -
- {/* 页面一 */} -
-
-
-
- {/* */} -
-
-
-

IvorySQL

-

Open Source Oracle Compatible PostgreSQL

-
- - Online Trial - - - Learn More - -
-
-
- - {/* */} -
-
-
-
-
- {/* 页面二 */} -
-
- - -
-
- - -
-
-
-
+ + {action.label} + ); } function ChatWidget() { - const {siteConfig:{customFields}} = useDocusaurusContext(); - + const { + siteConfig: { customFields }, + } = useDocusaurusContext(); + useEffect(() => { - // 创建外部 script 标签加载 SDK const script = document.createElement('script'); - script.src = "https://lf-cdn.coze.cn/obj/unpkg/flow-platform/chat-app-sdk/1.1.0-beta.3/libs/cn/index.js"; + script.src = 'https://lf-cdn.coze.cn/obj/unpkg/flow-platform/chat-app-sdk/1.1.0-beta.3/libs/cn/index.js'; script.async = true; - // 当脚本加载完成后调用初始化代码 script.onload = () => { if (window.CozeWebSDK && window.CozeWebSDK.WebChatClient) { new window.CozeWebSDK.WebChatClient({ @@ -122,43 +556,477 @@ function ChatWidget() { componentProps: { title: 'IvorySQL Chatroom', icon: 'https://raw.githubusercontent.com/IvorySQL/Ivory-www/main/static/img/ivory-black.png', - }, auth: { - type: "token", + type: 'token', token: customFields.patToken, - onRefreshToken: function () { + onRefreshToken() { return customFields.patToken; - } - } + }, + }, }); } else { - console.error('CozeWebSDK 未加载成功!'); + console.error('Failed to load CozeWebSDK.'); } }; - // 将 script 标签添加到 body 中 document.body.appendChild(script); - - // 可选:组件卸载时清除 script 标签 return () => { document.body.removeChild(script); }; - }, []); + }, [customFields.botId, customFields.patToken]); + + return null; +} - return null; // 该组件不需要渲染任何内容 +function SectionTitle({ title, Icon }) { + return ( +
+
+ {Icon ? ( + + ) : null} +

{title}

+
+
+ ); } export default function Home() { - const {siteConfig} = useDocusaurusContext(); + const { siteConfig, i18n } = useDocusaurusContext(); + const isZh = i18n.currentLocale.toLowerCase().startsWith('zh'); + const content = isZh ? CONTENT.zh : CONTENT.en; + const [latestVersionLabel, setLatestVersionLabel] = useState(content.latestVersionLabel); + const certImages = [ + '/img/partners/cert1.jpg', + '/img/partners/cert2.jpg', + '/img/partners/cert3.jpg', + '/img/partners/cert4.jpg', + '/img/partners/cert5.png', + ]; + const certCarouselImages = [...certImages, ...certImages]; + + // Scroll-triggered reveal via IntersectionObserver + useEffect(() => { + const elements = document.querySelectorAll('[data-reveal]'); + if (!elements.length) return; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + entry.target.dataset.revealed = 'true'; + observer.unobserve(entry.target); + } + }); + }, + { threshold: 0.12, rootMargin: '0px 0px -80px 0px' }, + ); + + elements.forEach((el) => observer.observe(el)); + return () => observer.disconnect(); + }, []); + + useEffect(() => { + let cancelled = false; + + setLatestVersionLabel(content.latestVersionLabel); + + const cacheLabel = readLatestVersionFromCache(); + if (cacheLabel) { + setLatestVersionLabel(cacheLabel); + return () => { + cancelled = true; + }; + } + + const updateLatestVersion = async () => { + try { + const response = await fetch(LATEST_RELEASE_API_URL, { + headers: { + Accept: 'application/vnd.github+json', + }, + }); + + if (!response.ok) { + return; + } + + const release = await response.json(); + const label = formatLatestReleaseLabel(release, content.latestVersionLabel); + + if (!cancelled && label) { + setLatestVersionLabel(label); + writeLatestVersionToCache(label); + } + } catch { + // Keep default label when request fails. + } + }; + + updateLatestVersion(); + + return () => { + cancelled = true; + }; + }, [content.latestVersionLabel]); + return ( - + - -
- +
+
+
+
+
+ {content.heroBadges.map((badge) => ( + {badge} + ))} +
+

IvorySQL

+

{content.slogan}

+
+ {content.actions.map((action) => ( + + ))} +
+
+ {content.latestVersionPrefix}: + + {latestVersionLabel} + +
+
+ +
+ + {/* Trusted-by customer bar */} +
+ {content.heroTrustLabel} +
    + {TRUSTED_CUSTOMERS.map((c) => { + const displayName = isZh && c.nameZh ? c.nameZh : c.name; + return ( +
  • + {c.logo + ? {displayName} + : {displayName} + } +
  • + ); + })} +
+
+
+ +
+
+
+ {content.statsItems.map((stat) => ( +
+ {stat.value} + {stat.label} +
+ ))} +
+
+
+ +
+
+
+
+ {content.oracleShowcase.subtitle} +

{content.oracleShowcase.title}

+
    + {content.oracleShowcase.points.map((pt) => ( +
  • + + {pt} +
  • + ))} +
+ + {content.oracleShowcase.cta} + +
+
+
+ + + + {isZh ? 'Oracle 语法 → IvorySQL' : 'Oracle syntax → IvorySQL'} +
+
+
{isZh ? '-- Oracle Package 结构' : '-- Oracle Package syntax'}
+
CREATE OR REPLACE PACKAGE hr_pkg AS
+
FUNCTION get_salary(emp_id NUMBER)
+
RETURN NUMBER;
+
END;
+
/
+
+
{isZh ? '-- Oracle 内置函数' : '-- Oracle built-in functions'}
+
SELECT NVL(salary, 0),
+
TO_DATE('2024-01-01', 'YYYY-MM-DD'),
+
DECODE(dept_id, 10, 'HR', 'Other')
+
FROM employees;
+
+
{isZh ? '与 Oracle 100% 语法兼容' : '100% Oracle syntax compatible'}
+
+
+
+
+
+ +
+
+ +

{content.coreDesc}

+
+ {content.coreItems.map((item, index) => { + const CardIcon = CORE_CARD_ICONS[index % CORE_CARD_ICONS.length]; + return ( +
+ +
+

{item.title}

+

{item.description}

+
+
+ ); + })} +
+
+
+ +
+
+ +

{content.scenariosDesc}

+
+ {content.scenarioItems.map((item, index) => { + const CardIcon = SCENARIO_CARD_ICONS[index % SCENARIO_CARD_ICONS.length]; + return ( +
+
+ + + +

{item.title}

+
+

{item.description}

+
+ ); + })} +
+
+
+ +
+
+ +

{content.installDesc}

+
+ {content.installItems.map((item, index) => { + const CardIcon = INSTALL_CARD_ICONS[index % INSTALL_CARD_ICONS.length]; + return ( +
+
+ + + +

{item.title}

+
+

{item.description}

+ +
+ ); + })} +
+
+
+ +
+
+ +

{content.ecosystemDesc}

+ + {/* 6 category spotlight cards */} +
+ {content.ecosystemCategories.map((cat, idx) => { + const CatIcon = [Icon01, Icon02, Icon03, Icon04, Icon05, Icon06][idx % 6]; + return ( +
+
+ +
+

{cat.title}

+

{cat.desc}

+
+
+
+ {cat.tools.map((item) => { + const tone = getEcosystemToolTone(item); + const meta = TOOL_META[item]; + const tooltipDesc = meta && (isZh ? (meta.descZh || meta.desc) : meta.desc); + return ( + + {item} + {meta && ( + + {tooltipDesc} + {meta.url && ( + + {isZh ? '访问官网 →' : 'Visit homepage →'} + + )} + + )} + + ); + })} +
+
+ ); + })} +
+ + {/* Platform coverage bar */} +
+ {content.ecosystemFooters.map((line) => ( +

{line}

+ ))} +
+ + {/* Legend */} +
+ {content.ecosystemLegend.map((legend) => ( + +