commit 49190feab6268d64bbb16e332f53d2a66f387d14 Author: TypeFlu Date: Thu Sep 4 15:07:40 2025 +0530 Squashed 'Website/' content from commit 820a8fc4 git-subtree-dir: Website git-subtree-split: 820a8fc4c609fa2281312a6a75491add1c280711 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..301e9783 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'weekly' diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f8a3ec80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,89 @@ +node_modules +pnpm-lock.yaml +package-lock.json +yarn.lock +.wrangler +.DS_Store +.vscode +.idea +.vite_opt_cache + +# Build artifacts +docs/.vitepress/dist/ +docs/.vitepress/cache/ +docs/.vitepress/.temp/ +dist/ + +# Generated files +docs/public/sw.js +docs/public/favicon*.png +docs/public/favicon.ico +docs/public/android-chrome-*.png +docs/public/apple-touch-icon*.png +docs/public/safari-pinned-tab.svg +docs/public/browserconfig.xml +docs/public/site.webmanifest +docs/public/manifest.webmanifest +docs/public/mstile-*.png +docs/public/favicons.html +favicon-data.json + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ +*.lcov + +# Dependency directories +.pnpm-store/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..fb24b31b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +# Build artifacts +node_modules/ +dist/ +docs/.vitepress/cache/ +docs/.vitepress/dist/ + +# Logs +*.log + +# Lockfiles backup +pnpm-debug.log* + +# Generated +.DS_Store diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..09e3f0eb --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "singleQuote": true, + "semi": false, + "trailingComma": "es5", + "printWidth": 100, + "tabWidth": 2, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/README.md b/README.md new file mode 100644 index 00000000..2b07cf16 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# SukiSU-Ultra Documentation + +[![Website](https://img.shields.io/website?url=https%3A%2F%2Fsukisu.org&logo=Cloudflare&label=Cloudflare%20Pages&style=flat-square)](https://sukisu.org) +[![VitePress](https://img.shields.io/badge/VitePress-2.0.0--alpha.12-646cff?logo=vite&logoColor=white&style=flat-square)](https://vitepress.dev) +[![License](https://img.shields.io/badge/License-Multiple-blue?style=flat-square)](/docs/guide/license.md) +[![Last Commit](https://img.shields.io/github/last-commit/typeflu/website?style=flat-square)](https://github.com/sukisu-ultra/website/commits/main) +[![Repo Size](https://img.shields.io/github/repo-size/sukisu-ultra/website?style=flat-square)](https://github.com/sukisu-ultra/website) +[![GitHub Stars](https://img.shields.io/github/stars/sukisu-ultra/website?style=flat-square)](https://github.com/sukisu-ultra/website/stargazers) diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..74434ed4 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,18 @@ +/coverage +/src/client/shared.ts +/src/node/shared.ts +*.log +*.tgz +.DS_Store +.idea +.temp +.vite_opt_cache +.vscode +dist +cache +temp +examples-temp +node_modules +pnpm-global +TODOs.md +*.timestamp-*.mjs \ No newline at end of file diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts new file mode 100644 index 00000000..594435a8 --- /dev/null +++ b/docs/.vitepress/config.ts @@ -0,0 +1,248 @@ +import { defineConfig } from 'vitepress' +import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons' +import { + GitChangelog, + GitChangelogMarkdownSection, +} from '@nolebase/vitepress-plugin-git-changelog/vite' + +import footnote from 'markdown-it-footnote' +import mark from 'markdown-it-mark' +import sub from 'markdown-it-sub' +import taskLists from 'markdown-it-task-lists' + +export default defineConfig({ + title: 'SukiSU-Ultra', + description: 'Next-Generation Android root solution.', + + lastUpdated: true, + cleanUrls: true, + metaChunk: true, + + // Global performance optimizations + cacheDir: './.vitepress/cache', + ignoreDeadLinks: false, + + // Enhanced markdown with performance focus + markdown: { + math: true, + config(md) { + md.use(groupIconMdPlugin) + md.use(footnote) + md.use(mark) + md.use(sub) + md.use(taskLists) + }, + linkify: true, + typographer: true, + lineNumbers: true, + image: { + lazyLoading: true, + }, + toc: { + level: [1, 2, 3], + }, + theme: { + light: 'github-light', + dark: 'github-dark', + }, + }, + sitemap: { + hostname: 'https://sukisu.org', + transformItems(items) { + return items + .filter((item) => !item.url.includes('404')) + .map((item) => ({ + ...item, + changefreq: + item.url === '/' ? 'daily' : item.url.includes('/guide/') ? 'weekly' : 'monthly', + priority: item.url === '/' ? 1.0 : item.url.includes('/guide/') ? 0.9 : 0.7, + })) + }, + }, + + // Critical performance transformations + transformPageData(pageData) { + const canonicalUrl = `https://sukisu.org${pageData.relativePath}` + .replace(/index\.md$/, '') + .replace(/\.md$/, '') + + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push( + ['link', { rel: 'canonical', href: canonicalUrl }], + ['meta', { property: 'og:url', content: canonicalUrl }], + ['link', { rel: 'preload', href: '/logo.svg', as: 'image' }] + ) + + return pageData + }, + + head: [ + // Critical resource hints for global performance + ['link', { rel: 'dns-prefetch', href: '//github.com' }], + ['link', { rel: 'dns-prefetch', href: '//t.me' }], + ['link', { rel: 'dns-prefetch', href: '//sukisu.org' }], + + // Essential favicon setup - synced from /favicon during build/dev + ['link', { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }], + ['link', { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }], + ['link', { rel: 'icon', type: 'image/png', sizes: '96x96', href: '/favicon-96x96.png' }], + ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }], + ['link', { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#64edff' }], + // (Removed msapplication meta to avoid referencing non-existent files) + + // Web App Manifest + ['link', { rel: 'manifest', href: '/site.webmanifest' }], + + // Theme and app configuration + ['meta', { name: 'theme-color', content: '#64edff' }], + ['meta', { name: 'application-name', content: 'SukiSU-Ultra' }], + ['meta', { name: 'apple-mobile-web-app-title', content: 'SukiSU-Ultra' }], + ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], + ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'default' }], + + // Viewport and mobile optimization + [ + 'meta', + { name: 'viewport', content: 'width=device-width, initial-scale=1.0, viewport-fit=cover' }, + ], + ['meta', { name: 'format-detection', content: 'telephone=no' }], + ['meta', { property: 'og:type', content: 'website' }], + ['meta', { property: 'og:site_name', content: 'SukiSU-Ultra' }], + ['meta', { property: 'og:url', content: 'https://sukisu.org/' }], + ['meta', { property: 'og:locale', content: 'en_US' }], + ['meta', { property: 'og:locale:alternate', content: 'zh_CN' }], + + // Twitter optimization for global audience + ['meta', { property: 'twitter:card', content: 'summary_large_image' }], + ['meta', { property: 'twitter:site', content: '@sukisu_ultra' }], + ['meta', { property: 'twitter:creator', content: '@sukisu_ultra' }], + // (Removed Twitter image as no PNG social image is provided) + + // Additional SEO optimizations + [ + 'meta', + { + name: 'robots', + content: 'index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1', + }, + ], + ['meta', { name: 'bingbot', content: 'index, follow' }], + ['meta', { name: 'referrer', content: 'strict-origin-when-cross-origin' }], + + // Global SEO optimization + [ + 'meta', + { + name: 'keywords', + content: + 'Android root, KernelSU, SukiSU-Ultra, Android kernel, root management, 安卓 root, カーネル, рут', + }, + ], + ['meta', { name: 'author', content: 'SukiSU-Ultra Team' }], + + // Enhanced structured data for global search engines + [ + 'script', + { type: 'application/ld+json' }, + JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + name: 'SukiSU-Ultra', + description: 'Next-Generation Android Root Solution', + applicationCategory: 'SystemApplication', + operatingSystem: 'Android', + url: 'https://sukisu.org', + downloadUrl: 'https://github.com/sukisu-ultra/sukisu-ultra/releases', + supportingData: { + '@type': 'DataCatalog', + name: 'Compatibility Database', + }, + offers: { + '@type': 'Offer', + price: '0', + priceCurrency: 'USD', + }, + author: { + '@type': 'Organization', + name: 'SukiSU-Ultra Team', + url: 'https://github.com/sukisu-ultra', + }, + }), + ], + + // PWA optimization for global mobile users (manifest declared above) + ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], + ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' }], + ['meta', { name: 'apple-mobile-web-app-title', content: 'SukiSU-Ultra' }], + + // Cloudflare Web Analytics + [ + 'script', + { + defer: '', + src: 'https://static.cloudflareinsights.com/beacon.min.js', + 'data-cf-beacon': '{"token": "dcc5feef58bf4c56a170a99f4cec4798"}', + }, + ], + ], + + themeConfig: { + logo: { src: '/logo.svg', width: 24, height: 24 }, + + socialLinks: [ + { icon: 'github', link: 'https://github.com/sukisu-ultra/sukisu-ultra' }, + { + icon: { + svg: '', + }, + link: 'https://t.me/sukiksu', + }, + ], + search: { + provider: 'local', + }, + }, + + rewrites: { + 'en/:rest*': ':rest*', + }, + + locales: { + root: { + label: 'English', + }, + zh: { + label: '简体中文', + link: '/zh/', + }, + }, + + vite: { + plugins: [ + groupIconVitePlugin({ + customIcon: { + bash: '', + }, + }), + GitChangelog({ repoURL: () => 'https://github.com/SukiSU-Ultra/Website' }), + GitChangelogMarkdownSection({ + exclude: (id) => id.endsWith('index.md'), + sections: { disableContributors: true }, + }), + ], + build: { + minify: 'terser', + chunkSizeWarningLimit: 800, + assetsInlineLimit: 8192, + target: 'esnext', + cssCodeSplit: true, + sourcemap: false, + }, + + server: { + fs: { + allow: ['..'], + }, + }, + }, +}) diff --git a/docs/.vitepress/theme/components/ArticleShare.vue b/docs/.vitepress/theme/components/ArticleShare.vue new file mode 100644 index 00000000..14559a9b --- /dev/null +++ b/docs/.vitepress/theme/components/ArticleShare.vue @@ -0,0 +1,195 @@ + + + + + diff --git a/docs/.vitepress/theme/components/Confetti.vue b/docs/.vitepress/theme/components/Confetti.vue new file mode 100644 index 00000000..f3bcc630 --- /dev/null +++ b/docs/.vitepress/theme/components/Confetti.vue @@ -0,0 +1,12 @@ + diff --git a/docs/.vitepress/theme/components/backtotop.vue b/docs/.vitepress/theme/components/backtotop.vue new file mode 100644 index 00000000..aee9d6aa --- /dev/null +++ b/docs/.vitepress/theme/components/backtotop.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 00000000..c1c4868d --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,33 @@ +// .vitepress/theme/index.ts +import DefaultTheme from 'vitepress/theme' +import { NolebaseGitChangelogPlugin } from '@nolebase/vitepress-plugin-git-changelog/client' +import 'virtual:group-icons.css' +import { h, onMounted } from 'vue' +import './style/style.css' +import ArticleShare from './components/ArticleShare.vue' +import backtotop from './components/backtotop.vue' +import '@nolebase/vitepress-plugin-git-changelog/client/style.css' + +export default { + extends: DefaultTheme, + Layout: () => { + return h(DefaultTheme.Layout, null, { + 'aside-outline-before': () => h(ArticleShare), + 'doc-footer-before': () => h(backtotop), + }) + }, + enhanceApp({ app }) { + app.use(NolebaseGitChangelogPlugin) + + // Register service worker in production for offline support and caching + if ( + typeof window !== 'undefined' && + 'serviceWorker' in navigator && + (import.meta as any).env?.PROD + ) { + onMounted(() => { + navigator.serviceWorker.register('/sw.js').catch(() => {}) + }) + } + }, +} diff --git a/docs/.vitepress/theme/style/custom-block.css b/docs/.vitepress/theme/style/custom-block.css new file mode 100644 index 00000000..5b253a2d --- /dev/null +++ b/docs/.vitepress/theme/style/custom-block.css @@ -0,0 +1,192 @@ +/* .vitepress/theme/style/custom-block.css */ +/* 深浅色卡 */ +:root { + --custom-block-info-left: #cccccc; + --custom-block-info-bg: #fafafa; + + --custom-block-tip-left: #009400; + --custom-block-tip-bg: #e6f6e6; + + --custom-block-warning-left: #e6a700; + --custom-block-warning-bg: #fff8e6; + + --custom-block-danger-left: #e13238; + --custom-block-danger-bg: #ffebec; + + --custom-block-note-left: #4cb3d4; + --custom-block-note-bg: #eef9fd; + + --custom-block-important-left: #a371f7; + --custom-block-important-bg: #f4eefe; + + --custom-block-caution-left: #e0575b; + --custom-block-caution-bg: #fde4e8; +} + +.dark { + --custom-block-info-left: #cccccc; + --custom-block-info-bg: #474748; + + --custom-block-tip-left: #009400; + --custom-block-tip-bg: #003100; + + --custom-block-warning-left: #e6a700; + --custom-block-warning-bg: #4d3800; + + --custom-block-danger-left: #e13238; + --custom-block-danger-bg: #4b1113; + + --custom-block-note-left: #4cb3d4; + --custom-block-note-bg: #193c47; + + --custom-block-important-left: #a371f7; + --custom-block-important-bg: #230555; + + --custom-block-caution-left: #e0575b; + --custom-block-caution-bg: #391c22; +} + +/* 标题字体大小 */ +.custom-block-title { + font-size: 16px; +} + +/* info容器:背景色、左侧 */ +.custom-block.info { + border-left: 5px solid var(--custom-block-info-left); + background-color: var(--custom-block-info-bg); +} + +/* info容器:svg图 */ +.custom-block.info [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z' fill='%23ccc'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -1px; +} + +/* 提示容器:边框色、背景色、左侧 */ +.custom-block.tip { + /* border-color: var(--custom-block-tip); */ + border-left: 5px solid var(--custom-block-tip-left); + background-color: var(--custom-block-tip-bg); +} + +/* 提示容器:svg图 */ +.custom-block.tip [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23009400' d='M7.941 18c-.297-1.273-1.637-2.314-2.187-3a8 8 0 1 1 12.49.002c-.55.685-1.888 1.726-2.185 2.998H7.94zM16 20v1a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-1h8zm-3-9.995V6l-4.5 6.005H11v4l4.5-6H13z'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -2px; +} + +/* 警告容器:背景色、左侧 */ +.custom-block.warning { + border-left: 5px solid var(--custom-block-warning-left); + background-color: var(--custom-block-warning-bg); +} + +/* 警告容器:svg图 */ +.custom-block.warning [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M576.286 752.57v-95.425q0-7.031-4.771-11.802t-11.3-4.772h-96.43q-6.528 0-11.3 4.772t-4.77 11.802v95.424q0 7.031 4.77 11.803t11.3 4.77h96.43q6.528 0 11.3-4.77t4.77-11.803zm-1.005-187.836 9.04-230.524q0-6.027-5.022-9.543-6.529-5.524-12.053-5.524H456.754q-5.524 0-12.053 5.524-5.022 3.516-5.022 10.547l8.538 229.52q0 5.023 5.022 8.287t12.053 3.265h92.913q7.032 0 11.803-3.265t5.273-8.287zM568.25 95.65l385.714 707.142q17.578 31.641-1.004 63.282-8.538 14.564-23.354 23.102t-31.892 8.538H126.286q-17.076 0-31.892-8.538T71.04 866.074q-18.582-31.641-1.004-63.282L455.75 95.65q8.538-15.57 23.605-24.61T512 62t32.645 9.04 23.605 24.61z' fill='%23e6a700'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; +} + +/* 危险容器:背景色、左侧 */ +.custom-block.danger { + border-left: 5px solid var(--custom-block-danger-left); + background-color: var(--custom-block-danger-bg); +} + +/* 危险容器:svg图 */ +.custom-block.danger [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2c5.523 0 10 4.477 10 10v3.764a2 2 0 0 1-1.106 1.789L18 19v1a3 3 0 0 1-2.824 2.995L14.95 23a2.5 2.5 0 0 0 .044-.33L15 22.5V22a2 2 0 0 0-1.85-1.995L13 20h-2a2 2 0 0 0-1.995 1.85L9 22v.5c0 .171.017.339.05.5H9a3 3 0 0 1-3-3v-1l-2.894-1.447A2 2 0 0 1 2 15.763V12C2 6.477 6.477 2 12 2zm-4 9a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4z' fill='%23e13238'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -1px; +} + +/* 提醒容器:背景色、左侧 */ +.custom-block.note { + border-left: 5px solid var(--custom-block-note-left); + background-color: var(--custom-block-note-bg); +} + +/* 提醒容器:svg图 */ +.custom-block.note [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z' fill='%234cb3d4'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -1px; +} + +/* 重要容器:背景色、左侧 */ +.custom-block.important { + border-left: 5px solid var(--custom-block-important-left); + background-color: var(--custom-block-important-bg); +} + +/* 重要容器:svg图 */ +.custom-block.important [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M512 981.333a84.992 84.992 0 0 1-84.907-84.906h169.814A84.992 84.992 0 0 1 512 981.333zm384-128H128v-42.666l85.333-85.334v-256A298.325 298.325 0 0 1 448 177.92V128a64 64 0 0 1 128 0v49.92a298.325 298.325 0 0 1 234.667 291.413v256L896 810.667v42.666zm-426.667-256v85.334h85.334v-85.334h-85.334zm0-256V512h85.334V341.333h-85.334z' fill='%23a371f7'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -1px; +} + +/* 注意容器:背景色、左侧 */ +.custom-block.caution { + border-left: 5px solid var(--custom-block-caution-left); + background-color: var(--custom-block-caution-bg); +} + +/* 注意容器:svg图 */ +.custom-block.caution [class*='custom-block-title']::before { + content: ''; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2c5.523 0 10 4.477 10 10v3.764a2 2 0 0 1-1.106 1.789L18 19v1a3 3 0 0 1-2.824 2.995L14.95 23a2.5 2.5 0 0 0 .044-.33L15 22.5V22a2 2 0 0 0-1.85-1.995L13 20h-2a2 2 0 0 0-1.995 1.85L9 22v.5c0 .171.017.339.05.5H9a3 3 0 0 1-3-3v-1l-2.894-1.447A2 2 0 0 1 2 15.763V12C2 6.477 6.477 2 12 2zm-4 9a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4z' fill='%23e13238'/%3E%3C/svg%3E"); + width: 20px; + height: 20px; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 4px; + left: -5px; + top: -1px; +} diff --git a/docs/.vitepress/theme/style/doc-fade-in.css b/docs/.vitepress/theme/style/doc-fade-in.css new file mode 100644 index 00000000..1e5742bd --- /dev/null +++ b/docs/.vitepress/theme/style/doc-fade-in.css @@ -0,0 +1,125 @@ +#app a:focus-visible, +#app button:focus-visible, +#app input[type='checkbox']:focus-visible { + --at-apply: outline-1 outline-primary ring-2 ring-primary; +} + +.VPSidebar::-webkit-scrollbar { + background: transparent; + height: 8px; + width: 8px; + margin-right: 8px; +} + +#app > div > div.VPLocalNav > div > div > div.outline { + outline-style: none !important; +} + +.vp-doc .color-swatch { + display: inline-block; + width: 0.85em; + height: 0.85em; + min-width: 12px; + min-height: 12px; + font-size: inherit; + border: 0; + border-radius: 2px; + margin: 0 3px 0 6px; + cursor: pointer; +} + +.medium-zoom-overlay { + z-index: 20; +} + +.medium-zoom-image { + z-index: 21; +} + +@keyframes slide-enter { + 0% { + transform: translateY(10px); + opacity: 0; + } + + to { + transform: translateY(0); + opacity: 100; + } +} + +@media (prefers-reduced-motion: no-preference) { + html:not(.no-sliding) [slide-enter], + html:not(.no-sliding) .slide-enter, + html:not(.no-sliding) .main > div > *, + html:not(.no-sliding) #VPContent > div > div.VPFeatures.VPHomeFeatures > *, + html:not(.no-sliding) .TeamPage > *, + html:not(.no-sliding) .VPHomeHero > * { + --enter-stage: 0; + --enter-step: 90ms; + --enter-initial: 0ms; + animation: slide-enter 1s both 1; + animation-delay: calc(var(--enter-initial) + var(--enter-stage) * var(--enter-step)); + } + + .main > div > *:nth-child(1) { + --enter-stage: 1; + } + .main > div > *:nth-child(2) { + --enter-stage: 2; + } + .main > div > *:nth-child(3) { + --enter-stage: 3; + } + .main > div > *:nth-child(4) { + --enter-stage: 4; + } + .main > div > *:nth-child(5) { + --enter-stage: 5; + } + .main > div > *:nth-child(6) { + --enter-stage: 6; + } + .main > div > *:nth-child(7) { + --enter-stage: 7; + } + .main > div > *:nth-child(8) { + --enter-stage: 8; + } + .main > div > *:nth-child(9) { + --enter-stage: 9; + } + .main > div > *:nth-child(10) { + --enter-stage: 10; + } + .main > div > *:nth-child(11) { + --enter-stage: 11; + } + .main > div > *:nth-child(12) { + --enter-stage: 12; + } + .main > div > *:nth-child(13) { + --enter-stage: 13; + } + .main > div > *:nth-child(14) { + --enter-stage: 14; + } + .main > div > *:nth-child(15) { + --enter-stage: 15; + } + .main > div > *:nth-child(16) { + --enter-stage: 16; + } + .main > div > *:nth-child(17) { + --enter-stage: 17; + } + .main > div > *:nth-child(18) { + --enter-stage: 18; + } + .main > div > *:nth-child(19) { + --enter-stage: 19; + } + .main > div > *:nth-child(20) { + --enter-stage: 20; + } +} diff --git a/docs/.vitepress/theme/style/style.css b/docs/.vitepress/theme/style/style.css new file mode 100644 index 00000000..4780d3db --- /dev/null +++ b/docs/.vitepress/theme/style/style.css @@ -0,0 +1,158 @@ +@import './custom-block.css'; +@import './doc-fade-in.css'; + +:root:where(:lang(fa)) { + --vp-font-family-base: + 'Vazirmatn', 'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff); + --vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%); + --vp-home-hero-image-filter: blur(44px); + + /* Enhanced brand color for better contrast */ + --vp-c-brand-1: #1e40af; + --vp-c-brand-2: #2563eb; + --vp-c-brand-3: #3b82f6; + --vp-c-brand-soft: rgba(30, 64, 175, 0.14); + + /* Button contrast improvements */ + --vp-button-brand-bg: #1e40af; + --vp-button-brand-text: #ffffff; + --vp-button-brand-hover-bg: #1d4ed8; + --vp-button-brand-hover-text: #ffffff; + --vp-button-brand-active-bg: #1e3a8a; + --vp-button-brand-active-text: #ffffff; +} + +/* Dark mode color overrides for better contrast */ +.dark:root { + --vp-c-brand-1: #60a5fa; + --vp-c-brand-2: #3b82f6; + --vp-c-brand-3: #2563eb; + --vp-c-brand-soft: rgba(96, 165, 250, 0.16); + + --vp-button-brand-bg: #3b82f6; + --vp-button-brand-text: #000000; + --vp-button-brand-hover-bg: #60a5fa; + --vp-button-brand-hover-text: #000000; + --vp-button-brand-active-bg: #2563eb; + --vp-button-brand-active-text: #000000; +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(68px); + } +} + +.VPHero .VPImage { + filter: drop-shadow(-2px 4px 6px rgba(0, 0, 0, 0.2)); + padding: 18px; +} + +/* used in reference/default-theme-search */ +img[src='/search.png'] { + width: 100%; + aspect-ratio: 1 / 1; +} + +/* Enhanced button contrast for accessibility */ +.VPButton.brand { + background-color: var(--vp-button-brand-bg) !important; + color: var(--vp-button-brand-text) !important; + border: none; + font-weight: 600; + text-shadow: none; +} + +.VPButton.brand:hover { + background-color: var(--vp-button-brand-hover-bg) !important; + color: var(--vp-button-brand-hover-text) !important; + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(30, 64, 175, 0.4); +} + +.VPButton.brand:active { + background-color: var(--vp-button-brand-active-bg) !important; + color: var(--vp-button-brand-active-text) !important; + transform: translateY(0); +} + +/* Dark mode support for buttons */ +.dark .VPButton.brand { + background-color: #3b82f6 !important; + color: #000000 !important; +} + +.dark .VPButton.brand:hover { + background-color: #60a5fa !important; + color: #000000 !important; + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); +} + +.dark .VPButton.brand:active { + background-color: #2563eb !important; + color: #000000 !important; +} + +/* Ensure proper contrast for all text elements */ +.VPButton.brand .text { + color: inherit !important; +} + +/* Focus states for accessibility */ +.VPButton.brand:focus-visible { + outline: 2px solid #ffffff; + outline-offset: 2px; +} + +.dark .VPButton.brand:focus-visible { + outline: 2px solid #000000; + outline-offset: 2px; +} + +@font-face { + font-family: 'HarmonyOS Sans SC'; + src: url('/HarmonyOS_Sans_SC.ttf') format('truetype'); +} + +body { + font-family: 'HarmonyOS Sans SC', sans-serif; + line-height: 1.8; + letter-spacing: 0.05em; + word-spacing: 0.05em; +} + +p, +li, +a, +span, +div, +h1, +h2, +h3, +h4, +h5, +h6 { + word-break: break-word; + text-justify: inter-ideograph; + -ms-text-autospace: ideograph-alpha; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +pre, +code { + letter-spacing: normal; + word-spacing: normal; +} diff --git a/docs/config.ts b/docs/config.ts new file mode 100644 index 00000000..f3b8b41e --- /dev/null +++ b/docs/config.ts @@ -0,0 +1,101 @@ +import { defineConfig, type DefaultTheme } from 'vitepress' +import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons' + +export default defineConfig({ + lang: 'en-US', + description: + 'Next-Generation Android Root Solution - Advanced kernel-based root management for Android devices with KernelSU integration', + + themeConfig: { + nav: nav(), + + sidebar: { + '/': { base: '/', items: sidebar() }, + }, + + search: { options: searchOptions() }, + editLink: { + pattern: 'https://github.com/sukisu-ultra/sukisu-ultra/edit/main/docs/:path', + text: 'Edit this page on GitHub', + }, + + docFooter: { + prev: 'Previous', + next: 'Next', + }, + + outline: { + label: 'On this page', + }, + + lastUpdated: { + text: 'Last updated', + }, + + notFound: { + title: 'Page Not Found', + quote: "Sorry, we couldn't find what you're looking for.", + linkLabel: 'Go to home', + linkText: 'Take me home', + }, + + langMenuLabel: 'Languages', + returnToTopLabel: 'Return to top', + sidebarMenuLabel: 'Menu', + darkModeSwitchLabel: 'Theme', + lightModeSwitchTitle: 'Switch to light theme', + darkModeSwitchTitle: 'Switch to dark theme', + skipToContentLabel: 'Skip to content', + }, +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { text: 'Home', link: '/' }, + { + text: 'Getting Started', + items: [ + { text: 'Introduction', link: '/guide/' }, + { text: 'Installation', link: '/guide/installation' }, + { text: 'Compatibility', link: '/guide/compatibility' }, + { text: 'Links', link: '/guide/links' }, + { text: 'license', link: '/guide/license' }, + ], + }, + ] +} + +function sidebar(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Getting Started', + items: [ + { text: 'Introduction', link: '/guide/' }, + { text: 'Installation', link: '/guide/installation' }, + { text: 'Compatibility', link: '/guide/compatibility' }, + { text: 'Links', link: '/guide/links' }, + { text: 'license', link: '/guide/license' }, + ], + }, + ] +} + +function searchOptions(): Partial { + return { + translations: { + button: { + buttonText: 'Search docs', + buttonAriaLabel: 'Search docs', + }, + modal: { + noResultsText: 'No results found', + resetButtonTitle: 'Clear query', + footer: { + selectText: 'Select', + navigateText: 'Navigate', + closeText: 'Close', + }, + }, + }, + } +} diff --git a/docs/en/guide/compatibility.md b/docs/en/guide/compatibility.md new file mode 100644 index 00000000..7da4a6b2 --- /dev/null +++ b/docs/en/guide/compatibility.md @@ -0,0 +1,23 @@ +# Compatibility Status + +::: info KernelSU +KernelSU (versions prior to v0.9.5) officially supports Android GKI 2.0 devices (kernel 5.10+) +::: + +::: warning Legacy Kernel Support +Older kernels (4.4+) are also compatible, but the kernel must be built manually +::: + +::: tip Extended Compatibility +SukiSu-Ultra can support 3.x kernels (3.4-3.18) through additional back ports +::: + +## Architecture Support + +Currently supports the following processor architectures: + +| Architecture | Support Level | Notes | +| --------------- | ------------------ | --------------------------- | +| **arm64-v8a** | ✅ Full Support | Primary target architecture | +| **armeabi-v7a** | ✅ Basic Support | Bare minimum functionality | +| **X86_64** | 🟡 Partial Support | Some devices supported | diff --git a/docs/en/guide/index.md b/docs/en/guide/index.md new file mode 100644 index 00000000..782df9e0 --- /dev/null +++ b/docs/en/guide/index.md @@ -0,0 +1,85 @@ +# Introduction + +Welcome to SukiSU-Ultra, the next-generation Android root solution that provides advanced kernel-based root management for Android devices. + +## What is SukiSU-Ultra? + +SukiSU-Ultra is a modern, secure, and powerful root solution designed specifically for Android devices. It offers kernel-level root access management with enhanced security features and improved compatibility. + +## Key Features + +### 🔒 Kernel-based su and root access management + +Secure root access management at the kernel level, providing better security and performance compared to traditional solutions. + +### 🚫 Not based on OverlayFS module system + +Built on Magic Mount technology from 5ec1cff, offering a more stable and reliable foundation. + +### 📱 App Profile + +Advanced application profiling system that allows you to lock root privileges in a controlled environment. + +### 🔧 Enhanced Device Support + +Bringing back support for non-GKI/GKI 1.0 devices, ensuring compatibility with older Android devices. + +### ⚙️ Extensive Customization + +Comprehensive customization options to tailor the root experience to your specific needs. + +### 🔌 KPM Kernel Module Support + +Full KernelPatch Module (KPM) functionality for advanced kernel modifications and enhancements. + +## Why Choose SukiSU-Ultra? + +- **Security First**: Advanced security features protect your device and data +- **Modern Architecture**: Built with modern Android security models in mind +- **Wide Compatibility**: Supports both GKI and non-GKI devices +- **Active Development**: Continuously updated with latest Android versions +- **Community Driven**: Open source with active community support + +## Getting Started + +Ready to get started with SukiSU-Ultra? Follow our step-by-step guide: + +1. **[Installation](./installation)** - Learn how to install SukiSU-Ultra on your device +2. **[Compatibility](./compatibility)** - Check device compatibility requirements +3. **[Links](./links)** - Find additional resources and downloads + +## System Requirements + +Before installing SukiSU-Ultra, ensure your device meets these requirements: + +- **Android Version**: Android 8.0 (API 26) or higher +- **Bootloader**: Unlocked bootloader +- **Recovery**: Custom recovery (TWRP recommended) +- **Storage**: At least 100MB free space +- **Knowledge**: Basic understanding of Android modding + +## Safety Notice + +::: danger Important +⚠️ **Rooting your device can void your warranty and may cause permanent damage if done incorrectly.** + +Always: + +- Create a full backup before proceeding +- Ensure your device is compatible +- Follow instructions carefully +- Have a recovery plan ready + ::: + +## Support + +Need help? We're here to assist: + +- **📖 Documentation**: Comprehensive guides and tutorials +- **💬 Community**: Active community forums and chat +- **🐛 Bug Reports**: GitHub issue tracker +- **📧 Direct Support**: Contact developers for critical issues + +--- + +**Ready to unlock the full potential of your Android device?** Start with our [installation guide](./installation) and join thousands of users who trust SukiSU-Ultra for their root needs. diff --git a/docs/en/guide/installation.md b/docs/en/guide/installation.md new file mode 100644 index 00000000..dea8b682 --- /dev/null +++ b/docs/en/guide/installation.md @@ -0,0 +1,121 @@ +# Installation Guide + +This guide provides comprehensive instructions for installing SukiSU-Ultra on your Android device. Please follow the steps carefully. + +## Prerequisites + +Before you begin, ensure you have the following: + +- [ ] A compatible device. Check the [Compatibility Guide](./compatibility.md) for details. +- [ ] Unlocked bootloader. +- [ ] Custom recovery installed, such as TWRP. +- [ ] Basic knowledge of flashing custom ROMs and kernels. +- [ ] Your device's kernel source or a compatible pre-built kernel. + +## Installation Methods + +There are several ways to install SukiSU-Ultra, depending on your device and preference. + +### Method 1: Using Pre-built GKI Packages + +This is the recommended method for devices with Generic Kernel Image (GKI) 2.0, such as many Xiaomi, Redmi, and Samsung models.[^1] + +[^1]: This method is not suitable for devices from manufacturers that heavily modify the kernel, like Meizu, OnePlus, Realme, and Oppo. + +#### Steps: + +1. **Download GKI Build**: Visit our [resources section](./links.md) to find the appropriate GKI build for your device's kernel version. Download the `.zip` file that includes `AnyKernel3` in its name. +2. **Flash via Recovery**: + - [ ] Boot your device into TWRP recovery. + - [ ] Select "Install". + - [ ] Navigate to the downloaded `AnyKernel3` zip file and select it. + - [ ] Swipe to confirm the flash. + - [ ] Once flashing is complete, reboot your system. +3. **Verify Installation**: + - [ ] Install the SukiSU-Ultra Manager app. + - [ ] Open the app and check if root access is granted and working correctly. + - [ ] You can also verify the new kernel version in your device's settings. + +::: details File Format Guide +The `.zip` archive without a suffix is uncompressed. The `.gz` suffix indicates compression used for specific models. +::: + +### Method 2: Custom Build for OnePlus Devices + +For OnePlus devices, you'll need to create a custom build. + +#### Steps: + +1. **Gather Device Information**: You will need: + - Your kernel version (e.g., `5.10`, `5.15`). + - Your processor's codename. + - The branch and configuration files from the OnePlus open-source kernel repository. +2. **Create Custom Build**: Use the link in our [resources section](./links.md) to generate a custom build with your device's information. +3. **Flash the Build**: + - [ ] Download the generated `AnyKernel3` zip file. + - [ ] Boot into recovery. + - [ ] Flash the zip file. + - [ ] Reboot and verify the installation. + +### Method 3: Manual Kernel Integration (Advanced) + +This method is for advanced users who are building a kernel from source. + +#### Integration Scripts: + +- **Main Branch (GKI)**: + ```sh [bash] + curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main + ``` +- **Non-GKI Branch**: + ```sh [bash] + curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki + ``` +- **SUSFS-Dev Branch (Recommended)**: + ```sh [bash] + curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main + ``` + +::: warning Required Kernel Configs +For KPM support, you must enable `CONFIG_KPM=y`. +For non-GKI devices, you also need to enable `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y`. +::: + +## Post-Installation + +### Maintaining Root After OTA Updates + +To keep root access after an Over-the-Air (OTA) update, follow these steps ==before rebooting==. + +1. **Flash to Inactive Slot**: + - [ ] After the OTA update is downloaded and installed, **do not reboot**. + - [ ] Open the SukiSU-Ultra Manager. + - [ ] Go to the flashing/patching interface. + - [ ] Select your `AnyKernel3` kernel zip file. + - [ ] Choose to install it to the inactive slot. + - [ ] Once flashed, you can safely reboot. +2. **Alternative: LKM Mode**: You can also use LKM mode to install to the unused slot after an OTA. + +::: tip +For non-GKI devices, the safest method to retain root after an OTA is to use TWRP to flash the kernel again. +::: + +## Verification Checklist + +After installation, please verify the following: + +- [ ] **Manager App**: The SukiSU-Ultra Manager app opens and shows a successful root status. +- [ ] **Root Access**: Root checker apps confirm that root access is working. +- [ ] **Kernel Version**: The kernel version in `Settings > About Phone` reflects the SukiSU-Ultra kernel. + +## Troubleshooting + +If you encounter any issues: + +1. Double-check the [Compatibility Guide](./compatibility.md). +2. Visit our [GitHub repository](https://github.com/sukisu-ultra/sukisu-ultra) for issues and solutions. +3. Join our [Telegram community](https://t.me/sukiksu) for live support. + +::: danger Safety Reminder +⚠️ **Always have a backup!** Keep a copy of your original `boot.img` and be prepared to restore your device if something goes wrong. +::: diff --git a/docs/en/guide/license.md b/docs/en/guide/license.md new file mode 100644 index 00000000..5a9873a9 --- /dev/null +++ b/docs/en/guide/license.md @@ -0,0 +1,77 @@ +# License + +## 📄 Software Licensing + +### Kernel Components + +::: info GPL-2.0 License +The files in the "kernel" directory are under GPL-2.0-only license +::: + +**License:** [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) + +### Application Core + +::: tip GPL-3.0 License +All other parts (except mentioned below) are under GPL-3.0 or later license +::: + +**License:** [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) + +## Artwork & Brand Assets + +### Launcher Icons & Character Art + +::: warning Copyright Notice +Special licensing requirements for anime character artwork +::: + +The images of the files `ic_launcher(?!.*alt.*).*` with anime character emoticons have specific copyright terms: + +**Copyright Holders:** + +- **Anime Character Art:** [五十根大虾仁](https://space.bilibili.com/370927) +- **Brand Intellectual Property:** [明风OuO](https://space.bilibili.com/274939213) +- **Vectorization:** @MiRinChan + +**License Requirements:** + +1. **Creative Commons License:** [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) +2. **Author Authorization:** Required from both copyright holders +3. **Attribution:** Must credit all contributors listed above + +::: details Usage Requirements +Before using these artistic assets, you must: + +- Comply with Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license +- Obtain authorization from both original authors for use of artistic content +- Provide proper attribution to all contributors + ::: + +## 📋 License Summary + +| Component | License | Notes | +| -------------------- | ------------------------------------------------------------------------- | ------------------------------------- | +| **Kernel Files** | [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | Files in `/kernel/` directory | +| **Application Code** | [GPL-3.0+](https://www.gnu.org/licenses/gpl-3.0.html) | Main application components | +| **Character Art** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | + Author authorization required | +| **Brand Assets** | Mixed Licensing | See specific attribution requirements | + +## 🔗 License Links + +- **GPL-2.0:** [Full License Text](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) +- **GPL-3.0:** [Full License Text](https://www.gnu.org/licenses/gpl-3.0.html) +- **CC BY-NC-SA 4.0:** [Full License Text](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) + +## 📞 Licensing Questions + +For questions about licensing or usage permissions: + +1. **Code Licensing:** Refer to respective GPL license terms +2. **Artwork Usage:** Contact original authors for authorization +3. **Commercial Use:** Review CC BY-NC-SA 4.0 restrictions +4. **Distribution:** Ensure compliance with all applicable licenses + +::: tip Compliance Note +When redistributing or modifying SukiSU-Ultra, ensure you comply with all applicable licenses and attribution requirements for each component. +::: diff --git a/docs/en/guide/links.md b/docs/en/guide/links.md new file mode 100644 index 00000000..19ea90b3 --- /dev/null +++ b/docs/en/guide/links.md @@ -0,0 +1,77 @@ +# More Links + +## 🌐 Translation & Localization + +::: info Contribute Translations +If you need to submit a translation for the manager, please visit our Crowdin project +::: + +**Translation Platform:** [Crowdin - SukiSU-Ultra](https://crowdin.com/project/SukiSU-Ultra) + +## 🔧 Projects & Builds + +Projects compiled based on Sukisu and susfs: + +### GKI Builds + +::: tip Universal GKI Support +Generic Kernel Image builds with KernelSU and SUSFS integration +::: + +**Repository:** [GKI_KernelSU_SUSFS](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) + +### OnePlus Builds + +::: tip Device-Specific Builds +Automated OnePlus kernel builds with MKSU and SUSFS +::: + +**Repository:** [Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) + +## 📱 Community & Support + +### Telegram Community + +::: info Join Our Community +Connect with other users, get support, and stay updated +::: + +**Main Group:** [Tg Group](https://t.me/sukiksu) + +### Test Builds + +::: warning Experimental Builds +Test builds are experimental and may be unstable +::: + +**Test Builds Channel:** [Latest Test Build](https://t.me/Sukiksu/7114) + +## Downloads & Releases + +### Official Releases + +::: tip Stable Releases +Download the latest stable versions from our GitHub releases +::: + +**GitHub Releases:** [SukiSU-Ultra Releases](https://github.com/sukisu-ultra/sukisu-ultra/releases) + +### Issue Reporting + +::: info Bug Reports & Feature Requests +Report bugs or request new features on our GitHub repository +::: + +**GitHub Issues:** [Report Issues](https://github.com/sukisu-ultra/sukisu-ultra/issues) + +## 🔗 Quick Links Summary + +| Resource | Link | Description | +| ------------------ | ---------------------------------------------------------------------------- | ---------------------- | +| **Translations** | [Crowdin](https://crowdin.com/project/SukiSU-Ultra) | Submit translations | +| **Telegram Group** | [t.me/sukiksu](https://t.me/sukiksu) | Community support | +| **Test Builds** | [Test Channel](https://t.me/Sukiksu/7114) | Experimental builds | +| **Releases** | [GitHub Releases](https://github.com/sukisu-ultra/sukisu-ultra/releases) | Stable downloads | +| **Issues** | [GitHub Issues](https://github.com/sukisu-ultra/sukisu-ultra/issues) | Bug reports | +| **GKI Builds** | [GKI Repository](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) | Universal builds | +| **OnePlus Builds** | [OnePlus Repository](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) | Device-specific builds | diff --git a/docs/en/guide/troubleshooting.md b/docs/en/guide/troubleshooting.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 00000000..92d40e1b --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,37 @@ +--- +layout: home + +hero: + name: 'SukiSU-Ultra' + text: 'Next-Generation Android Root Solution' + tagline: Advanced kernel-based root management for Android devices + image: + src: /logo.svg + alt: SukiSU-Ultra + actions: + - theme: brand + text: Get Started + link: /guide/ + - theme: alt + text: View on GitHub + link: https://github.com/sukisu-ultra/sukisu-ultra + +features: + - title: Kernel-based su and root access management + details: Secure root access management at the kernel level. + + - title: Not based on OverlayFS module system + details: Based on Magic Mount from 5ec1cff. + + - title: App Profile + details: Lock root privileges in a cage. + + - title: Bringing back non-GKI/GKI 1.0 support + details: Enhanced compatibility for older devices. + + - title: More customization + details: Extensive customization options available. + + - title: Support for KPM kernel modules + details: Full KernelPatch Module functionality. +--- diff --git a/docs/public/HarmonyOS_Sans_SC.ttf b/docs/public/HarmonyOS_Sans_SC.ttf new file mode 100644 index 00000000..91edb76b Binary files /dev/null and b/docs/public/HarmonyOS_Sans_SC.ttf differ diff --git a/docs/public/_headers b/docs/public/_headers new file mode 100644 index 00000000..0bc2308c --- /dev/null +++ b/docs/public/_headers @@ -0,0 +1,60 @@ +# Global headers for security and performance +/* + X-Frame-Options: DENY + X-Content-Type-Options: nosniff + Referrer-Policy: strict-origin-when-cross-origin + Strict-Transport-Security: "max-age=31536000; includeSubDomains; preload" + Permissions-Policy: "camera=(), microphone=(), geolocation=()" + Content-Security-Policy: "default-src 'self'; script-src 'self' https://static.cloudflareinsights.com; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" + +# Cache static assets for maximum performance +/assets/* + Cache-Control: public, max-age=31536000, immutable + +/*.js + Cache-Control: public, max-age=31536000, immutable + +/*.css + Cache-Control: public, max-age=31536000, immutable + +/*.woff2 + Cache-Control: public, max-age=31536000, immutable + +/*.woff + Cache-Control: public, max-age=31536000, immutable + +# Images - 30 days cache +/*.svg + Cache-Control: public, max-age=2592000 + +/*.png + Cache-Control: public, max-age=2592000 + +/*.jpg + Cache-Control: public, max-age=2592000 + +/*.jpeg + Cache-Control: public, max-age=2592000 + +/*.webp + Cache-Control: public, max-age=2592000 + +/*.avif + Cache-Control: public, max-age=2592000 + +/*.ico + Cache-Control: public, max-age=2592000 + +# Manifest and service worker +/site.webmanifest + Cache-Control: public, max-age=86400 + +/sw.js + Cache-Control: public, max-age=0, must-revalidate + +# Offline page and HTML caching +/*.html + Cache-Control: public, max-age=60, must-revalidate + +/offline.html + Cache-Control: public, max-age=3600 diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg new file mode 100644 index 00000000..5e862c39 --- /dev/null +++ b/docs/public/favicon.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/docs/public/logo.svg b/docs/public/logo.svg new file mode 100644 index 00000000..b3d8e0f2 --- /dev/null +++ b/docs/public/logo.svg @@ -0,0 +1,535 @@ + + + + diff --git a/docs/public/offline.html b/docs/public/offline.html new file mode 100644 index 00000000..4cfeefe4 --- /dev/null +++ b/docs/public/offline.html @@ -0,0 +1,80 @@ + + + + + + Offline | SukiSU-Ultra + + + + +
+
+

You're offline

+

We couldn't load this page because your device has no internet connection.

+

+ When you're back online, try again. Some pages you visited before may still work from + cache. +

+ +
+
+ + diff --git a/docs/public/robots.txt b/docs/public/robots.txt new file mode 100644 index 00000000..1ee0e359 --- /dev/null +++ b/docs/public/robots.txt @@ -0,0 +1,76 @@ +User-agent: * +Allow: / +Disallow: /admin/ +Disallow: /.git/ +Disallow: /node_modules/ +Disallow: /api/ +Disallow: /.vitepress/ + +# Sitemap +Sitemap: https://sukisu.org/sitemap.xml + +# Crawl-delay for high-traffic optimization +Crawl-delay: 0.5 + +# Major search engines (global optimization) +User-agent: Googlebot +Allow: / +Crawl-delay: 0.5 + +User-agent: Bingbot +Allow: / +Crawl-delay: 1 + +User-agent: Slurp +Allow: / +Crawl-delay: 1 + +User-agent: DuckDuckBot +Allow: / +Crawl-delay: 0.5 + +User-agent: Baiduspider +Allow: / +Crawl-delay: 2 + +# Asian search engines (for China, Japan, etc.) +User-agent: YandexBot +Allow: / +Crawl-delay: 1 + +User-agent: NaverBot +Allow: / +Crawl-delay: 1 + +User-agent: SogouSpider +Allow: / +Crawl-delay: 2 + +# Block resource-intensive bots for performance +User-agent: AhrefsBot +Disallow: / + +User-agent: MJ12bot +Disallow: / + +User-agent: SemrushBot +Disallow: / + +User-agent: DotBot +Disallow: / + +# Block AI training crawlers to save bandwidth +User-agent: GPTBot +Disallow: / + +User-agent: ChatGPT-User +Disallow: / + +User-agent: CCBot +Disallow: / + +User-agent: anthropic-ai +Disallow: / + +User-agent: Claude-Web +Disallow: / diff --git a/docs/public/safari-pinned-tab.svg b/docs/public/safari-pinned-tab.svg new file mode 100644 index 00000000..327a7b06 --- /dev/null +++ b/docs/public/safari-pinned-tab.svg @@ -0,0 +1,535 @@ + + + + diff --git a/docs/public/web-app-manifest-192x192.png b/docs/public/web-app-manifest-192x192.png new file mode 100644 index 00000000..5fe27db2 Binary files /dev/null and b/docs/public/web-app-manifest-192x192.png differ diff --git a/docs/public/web-app-manifest-512x512.png b/docs/public/web-app-manifest-512x512.png new file mode 100644 index 00000000..82ac4b9b Binary files /dev/null and b/docs/public/web-app-manifest-512x512.png differ diff --git a/docs/zh/config.ts b/docs/zh/config.ts new file mode 100644 index 00000000..de065d18 --- /dev/null +++ b/docs/zh/config.ts @@ -0,0 +1,101 @@ +import { defineConfig, type DefaultTheme } from 'vitepress' + +export default defineConfig({ + lang: 'zh-Hans', + description: '下一代 Android Root 解决方案 - Android 上的内核级的高级 root 方案', + + themeConfig: { + nav: nav(), + + sidebar: { + '/zh/': { base: '/zh/', items: sidebar() }, + }, + + search: { options: searchOptions() }, + editLink: { + pattern: 'https://github.com/sukisu-ultra/sukisu-ultra/edit/main/docs/:path', + text: '在 GitHub 上编辑此页面', + }, + + docFooter: { + prev: '上一页', + next: '下一页', + }, + + outline: { + label: '页面导航', + }, + + lastUpdated: { + text: '最后更新于', + }, + + notFound: { + title: '页面未找到', + quote: '抱歉,我们无法找到您要查找的页面。', + linkLabel: '前往首页', + linkText: '带我回首页', + }, + + langMenuLabel: '多语言', + returnToTopLabel: '回到顶部', + sidebarMenuLabel: '菜单', + darkModeSwitchLabel: '主题', + lightModeSwitchTitle: '切换到浅色模式', + darkModeSwitchTitle: '切换到深色模式', + skipToContentLabel: '跳转到内容', + }, +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { text: '首页', link: '/zh/' }, + { + text: '开始使用', + items: [ + { text: '介绍', link: '/zh/guide/' }, + { text: '安装', link: '/zh/guide/installation' }, + { text: '集成', link: '/zh/guide/how-to-integrate' }, + { text: '兼容性', link: '/zh/guide/compatibility' }, + { text: '链接', link: '/zh/guide/links' }, + { text: '许可', link: '/zh/guide/license' }, + ], + }, + ] +} + +function sidebar(): DefaultTheme.SidebarItem[] { + return [ + { + text: '开始使用', + items: [ + { text: '介绍', link: '/guide/' }, + { text: '安装', link: '/guide/installation' }, + { text: '集成', link: '/guide/how-to-integrate' }, + { text: '兼容性', link: '/guide/compatibility' }, + { text: '链接', link: '/guide/links' }, + { text: '许可', link: '/guide/license' }, + ], + }, + ] +} + +function searchOptions(): Partial { + return { + translations: { + button: { + buttonText: '搜索文档', + buttonAriaLabel: '搜索文档', + }, + modal: { + noResultsText: '无法找到相关结果', + resetButtonTitle: '清除查询条件', + footer: { + selectText: '选择', + navigateText: '切换', + closeText: '关闭', + }, + }, + }, + } +} diff --git a/docs/zh/guide/compatibility.md b/docs/zh/guide/compatibility.md new file mode 100644 index 00000000..e77f30cc --- /dev/null +++ b/docs/zh/guide/compatibility.md @@ -0,0 +1,23 @@ +# 兼容性状态 + +::: info KernelSU +KernelSU(v0.9.5 之前的版本)官方支持 Android GKI 2.0 设备(内核 5.10+) +::: + +::: warning 传统内核支持 +较旧的内核(4.4+)也兼容,但内核必须手动构建 +::: + +::: tip 扩展兼容性 +SukiSU-Ultra 可以通过额外的反向移植支持 3.x 内核(3.4-3.18) +::: + +## 架构支持 + +目前支持以下处理器架构: + +| 架构 | 支持级别 | 备注 | +| --------------- | :---------: | -----------: | +| **arm64-v8a** | ✅ 完全支持 | 主要目标架构 | +| **armeabi-v7a** | ✅ 基础支持 | 最低功能要求 | +| **X86_64** | 🟡 部分支持 | 支持部分设备 | diff --git a/docs/zh/guide/how-to-integrate.md b/docs/zh/guide/how-to-integrate.md new file mode 100644 index 00000000..3e52abe1 --- /dev/null +++ b/docs/zh/guide/how-to-integrate.md @@ -0,0 +1,94 @@ +# 集成指导 + +SukiSU 可以集成到 GKI 和 non-GKI 内核中,并且已反向移植到 4.14 版本。 + + + +有些 OEM 定制可能导致多达 50% 的内核代码超出内核树代码,而非来自上游 Linux 内核或 ACK。因此,non-GKI 内核的定制特性导致了严重的内核碎片化,而且我们缺乏构建它们的通用方法。因此,我们无法提供 non-GKI 内核的启动映像。 + +前提条件:开源的、可启动的内核。 + +## Hook 方法 + +1. **KPROBES hook:** + - GKI kernels 的默认 hook 方法。 + - 需要 `# CONFIG_KSU_MANUAL_HOOK is not set`(未设定) & `CONFIG_KPROBES=y` + - 用作可加载的内核模块 (LKM). + +2. **Manual hook:** + + + - 需要 `CONFIG_KSU_MANUAL_HOOK=y` + - 需要 [`guide/how-to-integrate.md`](how-to-integrate.md) + - 需要 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) + +3. **Tracepoint Hook:** + - 自 SukiSU commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124) 引入的 hook 方法 + - 需要 `CONFIG_KSU_TRACEPOINT_HOOK=y` + - 需要 [`guide/tracepoint-hook.md`](tracepoint-hook.md) + + + +如果您能够构建可启动内核,有两种方法可以将 KernelSU 集成到内核源代码中: + +1. 使用 `kprobe` 自动集成 +2. 手动集成 + +## 与 kprobe 集成 + +适用: + +- GKI 内核 + +不适用: + +- non-GKI 内核 + +KernelSU 使用 kprobe 机制来做内核的相关 hook,如果 _kprobe_ 可以在你编译的内核中正常运行,那么推荐用这个方法来集成。 + +请参阅此文档 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#integrate-with-kprobe)。虽然标题为“适用于 non-GKI”,但仅适用于 GKI。 + +替换 KernelSU 添加到内核源代码树的步骤的执行命令为: + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main +``` + +## 手动修改内核源代码 + +适用: + +- GKI 内核 +- non-GKI 内核 + +请参考此文档 [https://github.com/~ (non-GKI 内核集成)](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) 和 [https://github.com/~ (GKI 内核构建)](https://kernelsu.org/zh_CN/guide/how-to-build.html) 进行手动集成。虽然第一个链接的标题是“适用于 non-GKI”,但它也适用于 GKI。两者都可以正常工作。 + +还有另一种集成方法,但是仍在开发中。 + + + +将 KernelSU(SukiSU)添加到内核源代码树的步骤的运行命令将被替换为: + +### GKI 内核 + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main +``` + +### non-GKI 内核 + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki +``` + +### 带有 susfs 的 GKI / non-GKI 内核(实验) + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-{{branch}} +``` + +分支: + +- `main` (susfs-main) +- `test` (susfs-test) +- 版本号 (例如: susfs-1.5.7, 你需要在 [分支](https://github.com/SukiSU-Ultra/SukiSU-Ultra/branches) 里找到它) diff --git a/docs/zh/guide/index.md b/docs/zh/guide/index.md new file mode 100644 index 00000000..3e57c77a --- /dev/null +++ b/docs/zh/guide/index.md @@ -0,0 +1,35 @@ +# 什么是 SukiSU-Ultra? + +一个 Android 上基于内核的 root 方案,由 [`tiann/KernelSU`](https://github.com/tiann/KernelSU) 分叉而来,添加了一些有趣的变更。 + +## 特性 + +1. 基于内核的 su 和权限管理。 +2. 基于 Magic Mount 的模块系统。 +3. App Profile: 把 Root 权限关进笼子里。 +4. 支持 non-GKI 与 GKI 1.0。 +5. KPM 支持 +6. 可调整管理器外观,可自定义 susfs 配置。 + +## 如何安装 + +了解如何在您的设备上 **[安装](./installation)** SukiSU-Ultra + +## 如何集成 + +阅读 **[集成](./how-to-integrate.md)** 将 SukiSU 集成到你的内核中 + +## 了解兼容性 + +检查设备 **[兼容性](./compatibility)** 要求 + +## 资源获取 + +查找其他资源和 **[下载](./links)** + +## 获取支持 + +需要帮助?我们在这里为您提供帮助: + +- **错误报告**: [GitHub Issues](https://github.com/SukiSU-Ultra/SukiSU-Ultra/issues) +- **直接支持**: 联系开发者处理关键问题 diff --git a/docs/zh/guide/installation.md b/docs/zh/guide/installation.md new file mode 100644 index 00000000..81c95b7d --- /dev/null +++ b/docs/zh/guide/installation.md @@ -0,0 +1,149 @@ +# 安装参考 + +::: details 将会了解 SukiSU-Ultra 安装过程 +[[toc]] +::: + +::: danger 警告 +**Root 您的设备可能会使保修失效,如果操作不当可能会造成永久性损坏。** +请务必在继续之前创建完整备份,阅读文档确保与您的设备兼容,遵循文档参考,准备好恢复计划 +::: + +## 通用 GKI + +请**全部**参考 [KernelSU 安装指南](https://kernelsu.org/zh_CN/guide/installation.html) + +1. 适用于 GKI 2.0 设备,如小米、红米、三星等(不包括内核修改的制造商,如魅族、一加、真我和 OPPO) +2. 在[更多链接](./links)中查找 GKI 构建。找到设备内核版本,然后下载并使用 TWRP 或内核刷写工具刷入带有 `AnyKernel3` 后缀的 + zip 文件。 +3. 无后缀的 `.zip` 档案是未压缩的,`gz` 后缀是特定型号使用的压缩格式。 + +## 一加设备 + +使用[更多链接](./links)部分提到的链接,用您的设备信息创建自定义构建,然后刷入带有 AnyKernel3 后缀的 zip 文件。 + +::: details 展开 + +- 只需要填写内核版本的前两部分,如 `5.10`、`5.15`、`6.1` 或 `6.6`。 +- 请自行搜索处理器代号,通常是不含数字的英文字母。 +- 可以从一加开源内核仓库中找到分支和配置文件。 +- 第三方 Recovery(推荐 TWRP) + +::: + +## 开始安装 + +### 通用 GKI 安装 + +::: tip +适用于 GKI 2.0 设备,如小米、红米、三星等(不包括内核修改的制造商,如魅族、一加、真我和 OPPO) +::: + +#### 步骤: + +1. 下载 GKI 构建文件 + + 从我们的[资源部分](./links)查找 GKI 构建。查找您设备的内核版本并下载带有 `AnyKernel3` 后缀的 `zip` 文件。 + +2. 通过 Recovery 刷入 + + 启动到 `TWRP recovery`,选择 **Install**,导航到下载的 `AnyKernel3 zip` 文件,滑动刷入后重启系统 + +3. [验证安装](#验证) + +::: details 文件格式说明 +无后缀的 `.zip` 档案是未压缩的,`gz` 后缀是特定型号使用的压缩格式。 +::: + +### 一加设备安装 + +1. 获取设备信息 + +- 内核版本(前两部分,例如 `5.10`、`5.15`、`6.1`、`6.6`) +- 处理器代号(通常是不含数字的英文) +- 来自一加开源内核仓库的分支和配置文件 + +2. 创建自定义构建 + + 使用我们[资源部分](./links)中提到的链接,用您的设备信息创建自定义构建。 + +3. 刷入构建 + + 下载生成的带有 AnyKernel3 后缀的 zip 文件,启动到 `TWRP recovery`,选择 **Install**,导航到下载的 `AnyKernel3 zip` 文件,滑动刷入后重启系统 + +::: tip +您只需要填写内核版本的前两部分。自行搜索处理器代号 +::: + +### 手动内核集成 + +面向希望将 SukiSU Ultra 集成到自己内核构建中的高级用户 + +#### 主分支(GKI) + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main +``` + +#### 非 GKI 分支 + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki +``` + +#### SUSFS-Dev 分支(推荐) + +```sh [bash] +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-dev +``` + +```bash +curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main +``` + +::: warning 必需的内核配置 +为了支持 KPM,添加 `CONFIG_KPM=y` + +对于非 GKI 设备,还要添加 `CONFIG_KALLSYMS=y` 和 `CONFIG_KALLSYMS_ALL=y` +::: + +## 安装后设置 + +### 系统更新时保持 Root + +> [!IMPORTANT] +> 如何在 OTA 更新后保持 root 访问权限: + +#### 步骤: + +1. 系统更新后重启前 + - OTA 安装后不要立即重启,将 SukiSU Ultra 安装到第二插槽 + - 打开 SukiSU Ultra 管理器,在**刷入/修补内核**界面选择 **GKI/non_GKI install**,选择您的 `AnyKernel3` 内核 `zip` 文件,选择与当前运行插槽相对的插槽然后刷入重启。 + +2. 替代方案:LKM 模式 + + 使用 [LKM 模式](#通用-gki) 在 OTA 后安装到未使用的插槽。 + +::: warning 警告 +**非 GKI 设备注意事项:** 此方法不支持所有非 GKI 设备。对于非 GKI 设备,使用 TWRP 是最安全的方法。 +::: + +## 验证 + +安装后,验证一切是否正常工作, + +- 打开 SukiSU Ultra 管理器检查 root 工作状态 +- 使用 root 权限的应用程序来验证 root 访问是否工作正常 +- 在设置 -> 关于手机中检查内核版本 + +## 需要帮助? + +如果在安装过程中遇到问题: + +1. 查看我们的[兼容性指南](./compatibility)了解设备要求 +2. 访问我们的 [GitHub 仓库](https://github.com/sukisu-ultra/sukisu-ultra)获取支持 +3. 加入我们的 [Telegram 社区](https://t.me/sukiksu)获取帮助 + +::: danger 安全提醒 +**始终有备用计划!** 保留您的原始 `boot.img/init_boot.img` 并知道如何在出现问题时恢复设备。 +::: diff --git a/docs/zh/guide/license.md b/docs/zh/guide/license.md new file mode 100644 index 00000000..a99bce2b --- /dev/null +++ b/docs/zh/guide/license.md @@ -0,0 +1,77 @@ +# 许可证 + +## 软件许可 + +### 内核组件 + +::: info GPL-2.0 许可证 +"kernel" 目录中的文件采用 GPL-2.0-only 许可证 +::: + +**许可证:** [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) + +### 应用程序核心 + +::: tip GPL-3.0 许可证 +所有其他部分(除下述特别说明外)采用 GPL-3.0 或更高版本许可证 +::: + +**许可证:** [GPL-3.0 或更高版本](https://www.gnu.org/licenses/gpl-3.0.html) + +## 艺术作品与品牌资产 + +### 启动器图标与角色艺术 + +::: warning 版权声明 +动画角色艺术作品有特殊许可要求 +::: + +包含动画角色表情的文件 `ic_launcher(?!.*alt.*).*` 图像有特定的版权条款: + +**版权持有者:** + +- **动画角色艺术:** [怡子曰曰](https://space.bilibili.com/10545509) +- **品牌知识产权:** [明风OuO](https://space.bilibili.com/274939213) +- **矢量化制作:** @MiRinChan + +**许可要求:** + +1. **知识共享许可证:** [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) +2. **作者授权:** 需要获得两位版权持有者的授权 +3. **署名要求:** 必须署名上述所有贡献者 + +::: details 使用要求 +在使用这些艺术资产之前,您必须: + +- 遵守知识共享署名-非商业性使用-相同方式共享 4.0 国际许可证 +- 获得两位原作者对艺术内容使用的授权 +- 为所有贡献者提供适当的署名 + ::: + +## 摘要 + +| 组件 | 许可证 | 备注 | +| ---------------- | ------------------------------------------------------------------------- | ----------------------- | +| **内核文件** | [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | `/kernel/` 目录中的文件 | +| **应用程序代码** | [GPL-3.0+](https://www.gnu.org/licenses/gpl-3.0.html) | 主要应用程序组件 | +| **角色艺术** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | + 需要作者授权 | +| **品牌资产** | 混合许可 | 查看具体署名要求 | + +## 链接 + +- **GPL-2.0:** [完整许可证文本](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) +- **GPL-3.0:** [完整许可证文本](https://www.gnu.org/licenses/gpl-3.0.html) +- **CC BY-NC-SA 4.0:** [完整许可证文本](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) + +## 问题 + +关于许可证或使用权限的问题: + +1. **代码许可:** 参考相应的 GPL 许可证条款 +2. **艺术作品使用:** 联系原作者获取授权 +3. **商业使用:** 查看 CC BY-NC-SA 4.0 限制条款 +4. **分发:** 确保遵守所有适用的许可证 + +::: tip 合规提示 +在重新分发或修改 SukiSU-Ultra 时,请确保遵守各个组件的所有适用许可证和署名要求。 +::: diff --git a/docs/zh/guide/links.md b/docs/zh/guide/links.md new file mode 100644 index 00000000..ff280a5c --- /dev/null +++ b/docs/zh/guide/links.md @@ -0,0 +1,71 @@ +# 更多链接 + +## 参与翻译 + +::: info 贡献翻译 +如果您需要为管理器提交翻译,请访问我们的 Crowdin 项目 +::: + +**翻译平台:** [Crowdin - SukiSU-Ultra](https://crowdin.com/project/SukiSU-Ultra) + +## 项目与构建 + +基于 Sukisu 和 susfs 编译的项目: + +### GKI 构建 + +::: tip 通用 GKI 支持 +集成 KernelSU 和 SUSFS 的通用内核映像构建 +::: + +**仓库:** [GKI_KernelSU_SUSFS](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) + +### OnePlus 构建 + +::: tip 设备特定构建 +带有 MKSU 和 SUSFS 的自动化 OnePlus 内核构建 +::: + +**仓库:** [Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) + +## 社区与支持 + +### Telegram 社区 + +> 与其他用户联系,获取支持并保持更新 + +**主群组:** [Tg Group](https://t.me/sukiksu) + +### 测试构建 + +::: warning 实验性构建 +测试构建是实验性的,可能不稳定 +::: + +**测试构建频道:** [最新测试构建](https://t.me/Sukiksu/7114) + +## 下载与发布 + +### 官方发布 + +> 从我们的 GitHub 发布页面下载最新稳定版本 + +**GitHub 发布:** [SukiSU-Ultra 发布](https://github.com/sukisu-ultra/sukisu-ultra/releases) + +### 问题报告 + +> 在我们的 GitHub 仓库上报告错误或请求新功能 + +**GitHub 问题:** [报告问题](https://github.com/sukisu-ultra/sukisu-ultra/issues) + +## 快速链接汇总 + +| 资源 | 链接 | 描述 | +| ----------------- | :--------------------------------------------------------------------: | -----------: | +| **翻译** | [Crowdin](https://crowdin.com/project/SukiSU-Ultra) | 提交翻译 | +| **Telegram 群组** | [t.me/sukiksu](https://t.me/sukiksu) | 社区支持 | +| **测试构建** | [测试频道](https://t.me/Sukiksu/7114) | 实验性构建 | +| **发布** | [GitHub 发布](https://github.com/sukisu-ultra/sukisu-ultra/releases) | 稳定下载 | +| **问题** | [GitHub 问题](https://github.com/sukisu-ultra/sukisu-ultra/issues) | 错误报告 | +| **GKI 构建** | [GKI 仓库](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) | 通用构建 | +| **OnePlus 构建** | [OnePlus 仓库](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) | 设备特定构建 | diff --git a/docs/zh/guide/tracepoint-hook.md b/docs/zh/guide/tracepoint-hook.md new file mode 100644 index 00000000..84470610 --- /dev/null +++ b/docs/zh/guide/tracepoint-hook.md @@ -0,0 +1,266 @@ +# Tracepoint Hook 集成 + +## 介绍 + +自 commit [49b01aad](https://github.com/SukiSU-Ultra/SukiSU-Ultra/commit/49b01aad74bcca6dba5a8a2e053bb54b648eb124) 起,SukiSU 引入了 Tracepoint Hook + +**该 Hook 理论上相比于 Kprobes Hook,性能开销更小,但次于 Manual Hook / Syscall Hook** + +::: warning +目前 Tracepoint Hook 在 6.x 设备上并不稳定,请勿使用,否则可能出现无法开机或无法获取 `ROOT` 权限等问题。 +::: + +> [!NOTE] +> 本教程参考了 [backslashxx/KernelSU#5](https://github.com/backslashxx/KernelSU/issues/5) 的 syscall hook v1.4 版本钩子,以及原版 KernelSU 的 [Manual Hook](https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source) + +## 在内核中放置 TP 钩子 + +::: code-group + +```diff[exec.c] +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -78,6 +78,10 @@ + #include + #endif + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif ++ + EXPORT_TRACEPOINT_SYMBOL_GPL(task_rename); + + static int bprm_creds_from_file(struct linux_binprm *bprm); +@@ -2037,6 +2041,9 @@ static int do_execve(struct filename *filename, + { + struct user_arg_ptr argv = { .ptr.native = __argv }; + struct user_arg_ptr envp = { .ptr.native = __envp }; ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_execveat_hook((int *)AT_FDCWD, &filename, &argv, &envp, 0); ++#endif + return do_execveat_common(AT_FDCWD, filename, argv, envp, 0); + } + +@@ -2064,6 +2071,9 @@ static int compat_do_execve(struct filename *filename, + .is_compat = true, + .ptr.compat = __envp, + }; ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_execveat_sucompat_hook((int *)AT_FDCWD, &filename, NULL, NULL, NULL); /* 32-bit su */ ++#endif + return do_execveat_common(AT_FDCWD, filename, argv, envp, 0); + } +``` + +```diff[open.c] +--- a/fs/open.c ++++ b/fs/open.c +@@ -37,6 +37,10 @@ + #include "internal.h" + #include + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif ++ + int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry, + loff_t length, unsigned int time_attrs, struct file *filp) + { +@@ -468,6 +472,9 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla + + SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + { ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL); ++#endif + return do_faccessat(dfd, filename, mode, 0); + } +``` + +```diff[read_write.c] +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -25,6 +25,10 @@ + #include + #include + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif ++ + const struct file_operations generic_ro_fops = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, +@@ -630,6 +634,9 @@ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count) + + SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) + { ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_sys_read_hook(fd, &buf, &count); ++#endif + return ksys_read(fd, buf, count); + } +``` + +```diff[stat.c] +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -24,6 +24,10 @@ + #include "internal.h" + #include "mount.h" + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif ++ + /** + * generic_fillattr - Fill in the basic attributes from the inode struct + * @mnt_userns: user namespace of the mount the inode was found from +@@ -408,6 +412,10 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, + struct kstat stat; + int error; + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_stat_hook(&dfd, &filename, &flag); ++#endif ++ + error = vfs_fstatat(dfd, filename, &stat, flag); + if (error) + return error; +@@ -559,6 +567,10 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename, + struct kstat stat; + int error; + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_stat_hook(&dfd, &filename, &flag); /* 32-bit su support */ ++#endif ++ + error = vfs_fstatat(dfd, filename, &stat, flag); + if (error) + return error; +``` + +::: +通常是要改四个地方: + +1. compat_do_execve,通常位于 `fs/exec.c` +2. do_faccessat,通常位于 `/fs/open.c` +3. sys_read,通常位于 `fs/read_write.c` +4. newfstatat SYSCALL,通常位于 `fs/stat.c` + +如果没有 do_faccessat 方法,可以找 faccessat 的 SYSCALL 定义(对于早于 4.17 的内核) + +```diff +--- a/fs/open.c ++++ b/fs/open.c +@@ -31,6 +31,9 @@ + #include + #include + #include ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif + + #include "internal.h" + +@@ -369,6 +372,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + int res; + unsigned int lookup_flags = LOOKUP_FOLLOW; + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_faccessat_hook(&dfd, &filename, &mode, NULL); ++#endif + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; +``` + +如果没有 sys_read 方法,并且 4.14 及以下需要修改 read 的 SYSCALL 定义 + +```diff +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -25,6 +25,11 @@ + #include + #include + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../drivers/kernelsu/ksu_trace.h> ++#endif ++ ++ + const struct file_operations generic_ro_fops = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, +@@ -575,6 +580,9 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) + + if (f.file) { + loff_t pos = file_pos_read(f.file); ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_sys_read_hook(fd, &buf, &count); ++#endif + ret = vfs_read(f.file, buf, count, &pos); + if (ret >= 0) + file_pos_write(f.file, pos); +``` + +## 安全模式 + +要使用 KernelSU 内置的安全模式,你还需要修改 `drivers/input/input.c` 中的 input_handle_event 方法: + +```diff +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -26,6 +26,10 @@ + #include "input-compat.h" + #include "input-poller.h" + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../../drivers/kernelsu/ksu_trace.h> ++#endif ++ + MODULE_AUTHOR("Vojtech Pavlik "); + MODULE_DESCRIPTION("Input core"); + MODULE_LICENSE("GPL"); +@@ -451,6 +455,10 @@ void input_event(struct input_dev *dev, + { + unsigned long flags; + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_input_hook(&type, &code, &value); ++#endif ++ + if (is_event_supported(type, dev->evbit, EV_MAX)) { + + spin_lock_irqsave(&dev->event_lock, flags); +``` + +## pm 命令执行失败? + +你需要修改 `drivers/tty/pty.c` + +```diff +--- a/drivers/tty/pty.c ++++ b/drivers/tty/pty.c +@@ -31,6 +31,10 @@ + #include + #include "tty.h" + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++#include <../../drivers/kernelsu/ksu_trace.h> ++#endif ++ + #undef TTY_DEBUG_HANGUP + #ifdef TTY_DEBUG_HANGUP + # define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args) +@@ -707,6 +711,10 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, + { + struct tty_struct *tty; + ++#if defined(CONFIG_KSU) && defined(CONFIG_KSU_TRACEPOINT_HOOK) ++ trace_ksu_trace_devpts_hook((struct inode *)file->f_path.dentry->d_inode); ++#endif ++ + mutex_lock(&devpts_mutex); + tty = devpts_get_priv(file->f_path.dentry); + mutex_unlock(&devpts_mutex); +``` diff --git a/docs/zh/index.md b/docs/zh/index.md new file mode 100644 index 00000000..7f08bc35 --- /dev/null +++ b/docs/zh/index.md @@ -0,0 +1,37 @@ +--- +layout: home + +hero: + name: 'SukiSU-Ultra' + text: '下一代 Android Root 解决方案' + tagline: Android 上的内核级的高级 root 方案 + image: + src: /logo.svg + alt: SukiSU-Ultra + actions: + - theme: brand + text: 开始使用 + link: /zh/guide/ + - theme: alt + text: 在 GitHub 上查看 + link: https://github.com/sukisu-ultra/sukisu-ultra + +features: + - title: 内核级的 su 和 root 权限管理 + details: 在内核进行安全的 root 权限管理。 + + - title: 不基于 OverlayFS 的模块系统 + details: 模块系统基于来自 5ec1cff 的 Magic Mount。 + + - title: App Profile + details: 把 root 权限关进笼子里。 + + - title: 重新支持非 GKI 与 GKI 1.0 内核 + details: 增强对旧设备的兼容性。 + + - title: 更多自定义选项 + details: 提供广泛的自定义选项。 + + - title: 支持 KPM + details: 完整的基于 KernelPatch 的 KPM 功能。 +--- diff --git a/favicon/apple-touch-icon.png b/favicon/apple-touch-icon.png new file mode 100644 index 00000000..47e856c5 Binary files /dev/null and b/favicon/apple-touch-icon.png differ diff --git a/favicon/favicon-96x96.png b/favicon/favicon-96x96.png new file mode 100644 index 00000000..ea26f7a8 Binary files /dev/null and b/favicon/favicon-96x96.png differ diff --git a/favicon/favicon.ico b/favicon/favicon.ico new file mode 100644 index 00000000..fa6e1dcb Binary files /dev/null and b/favicon/favicon.ico differ diff --git a/favicon/favicon.svg b/favicon/favicon.svg new file mode 100644 index 00000000..5e862c39 --- /dev/null +++ b/favicon/favicon.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/favicon/site.webmanifest b/favicon/site.webmanifest new file mode 100644 index 00000000..47b1fee7 --- /dev/null +++ b/favicon/site.webmanifest @@ -0,0 +1,26 @@ +{ + "name": "SukiSU", + "short_name": "SukiSU", + "icons": [ + { + "src": "/favicon.svg", + "type": "image/svg+xml", + "purpose": "any" + }, + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "theme_color": "#000000", + "background_color": "#000000", + "display": "standalone" +} diff --git a/favicon/web-app-manifest-192x192.png b/favicon/web-app-manifest-192x192.png new file mode 100644 index 00000000..5fe27db2 Binary files /dev/null and b/favicon/web-app-manifest-192x192.png differ diff --git a/favicon/web-app-manifest-512x512.png b/favicon/web-app-manifest-512x512.png new file mode 100644 index 00000000..82ac4b9b Binary files /dev/null and b/favicon/web-app-manifest-512x512.png differ diff --git a/package.json b/package.json new file mode 100644 index 00000000..3d131e90 --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "sukisu-ultra-docs", + "version": "1.0.1", + "description": "SukiSU-Ultra Documentation - Next-Generation Android Root Solution", + "type": "module", + "scripts": { + "dev": "tsx scripts/rebuild-ico.ts && tsx scripts/sync-favicons.ts && vitepress dev docs --host", + "build": "tsx scripts/sync-favicons.ts && vitepress build docs && pnpm build:sw:dist", + "preview": "vitepress preview docs", + "build:sw": "tsc scripts/sw.ts --target ES2022 --lib ES2022,WebWorker --outDir docs/public --skipLibCheck", + "build:sw:dist": "tsc scripts/sw.ts --target ES2022 --lib ES2022,WebWorker --outDir docs/.vitepress/dist --skipLibCheck", + "build:scripts": "pnpm build:sw", + "type-check": "tsc --noEmit", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "keywords": [ + "android", + "root", + "kernelsu", + "sukisu", + "documentation", + "vitepress" + ], + "repository": { + "type": "git", + "url": "https://github.com/sukisu-ultra/sukisu-ultra.git" + }, + "homepage": "https://sukisu.org", + "bugs": { + "url": "https://github.com/sukisu-ultra/sukisu-ultra/issues" + }, + "devDependencies": { + "@types/node": "^24.3.0", + "@types/serviceworker": "^0.0.152", + "markdown-it-footnote": "^4.0.0", + "markdown-it-mark": "^4.0.0", + "markdown-it-mathjax3": "^4.3.2", + "markdown-it-sub": "^2.0.0", + "markdown-it-task-lists": "^2.1.1", + "prettier": "^3.6.2", + "terser": "^5.44.0", + "ts-node": "^10.9.2", + "tsx": "^4.20.5", + "typescript": "^5.9.2", + "vitepress": "2.0.0-alpha.12", + "vue": "^3.5.21" + }, + "engines": { + "node": ">=22" + }, + "packageManager": "pnpm@10.15.1", + "dependencies": { + "@nolebase/vitepress-plugin-git-changelog": "^2.18.2", + "vitepress-plugin-group-icons": "^1.6.3" + } +} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 00000000..b5554666 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +packages: + - docs + - . + +onlyBuiltDependencies: + - esbuild diff --git a/scripts/sw.ts b/scripts/sw.ts new file mode 100644 index 00000000..d8c0fd3a --- /dev/null +++ b/scripts/sw.ts @@ -0,0 +1,207 @@ +/// + +const CACHE_NAME: string = 'sukisu-ultra-v2.0' +const STATIC_CACHE: string = 'sukisu-static-v2.0' +const RUNTIME_CACHE: string = 'sukisu-runtime-v2.0' +const IMAGE_CACHE: string = 'sukisu-images-v2.0' + +const CRITICAL_ASSETS: string[] = [ + '/', + '/guide/', + '/guide/installation', + '/guide/compatibility', + '/zh/', + '/zh/guide/', + '/logo.svg', + '/favicon.ico', + '/offline.html', +] + +const CACHE_STRATEGIES: { + static: string[] + images: string[] + documents: string[] +} = { + static: ['.css', '.js', '.woff2', '.woff', '.ttf', '.otf'], + images: ['.png', '.jpg', '.jpeg', '.svg', '.webp', '.avif', '.gif', '.ico'], + documents: ['.html', '.json', '.xml'], +} + +self.addEventListener('install', (event: ExtendableEvent) => { + event.waitUntil( + (async (): Promise => { + const cache: Cache = await caches.open(STATIC_CACHE) + try { + await cache.addAll(CRITICAL_ASSETS) + } catch (error) { + console.warn('Failed to cache some assets:', error) + } + ;(self as any).skipWaiting() + })() + ) +}) + +self.addEventListener('activate', (event: ExtendableEvent) => { + event.waitUntil( + (async (): Promise => { + const cacheNames: string[] = await caches.keys() + const validCaches: string[] = [STATIC_CACHE, RUNTIME_CACHE, IMAGE_CACHE, CACHE_NAME] + + await Promise.all( + cacheNames + .filter((name: string) => !validCaches.includes(name)) + .map((name: string) => caches.delete(name)) + ) + ;(self as any).clients.claim() + })() + ) +}) + +self.addEventListener('fetch', (event: FetchEvent) => { + const { request } = event + const url: URL = new URL(request.url) + + if (request.method !== 'GET' || url.origin !== location.origin) return + if (url.pathname.startsWith('/api/')) return + + event.respondWith(handleRequest(request, url)) +}) + +async function handleRequest(request: Request, url: URL): Promise { + const isStatic: boolean = CACHE_STRATEGIES.static.some((ext: string) => + url.pathname.endsWith(ext) + ) + const isImage: boolean = CACHE_STRATEGIES.images.some((ext: string) => url.pathname.endsWith(ext)) + const isDocument: boolean = + CACHE_STRATEGIES.documents.some((ext: string) => url.pathname.endsWith(ext)) || + url.pathname.endsWith('/') + + try { + if (isStatic) { + return await handleStatic(request) + } else if (isImage) { + return await handleImage(request) + } else if (isDocument) { + return await handleDocument(request) + } else { + return await handleDefault(request) + } + } catch (error) { + return await handleOffline(request) + } +} + +async function handleStatic(request: Request): Promise { + const cache: Cache = await caches.open(STATIC_CACHE) + const cached: Response | undefined = await cache.match(request) + + if (cached) { + fetch(request) + .then((response: Response) => { + if (response.ok) cache.put(request, response.clone()) + }) + .catch(() => {}) + + return cached + } + + const response: Response = await fetch(request) + if (response.ok) { + cache.put(request, response.clone()) + } + return response +} + +async function handleImage(request: Request): Promise { + const cache: Cache = await caches.open(IMAGE_CACHE) + const cached: Response | undefined = await cache.match(request) + + if (cached) return cached + + const response: Response = await fetch(request) + if (response.ok) { + cache.put(request, response.clone()) + } + return response +} + +async function handleDocument(request: Request): Promise { + const cache: Cache = await caches.open(RUNTIME_CACHE) + + try { + const response: Response = await fetch(request) + if (response.ok) { + cache.put(request, response.clone()) + } + return response + } catch (error) { + const cached: Response | undefined = await cache.match(request) + if (cached) return cached + + if (request.mode === 'navigate') { + const offlinePage: Response | undefined = await caches.match('/offline.html') + if (offlinePage) return offlinePage + } + + throw error + } +} + +async function handleDefault(request: Request): Promise { + const cache: Cache = await caches.open(RUNTIME_CACHE) + + try { + const response: Response = await fetch(request) + if (response.ok) { + cache.put(request, response.clone()) + } + return response + } catch (error) { + const cached: Response | undefined = await cache.match(request) + if (cached) return cached + throw error + } +} + +async function handleOffline(request: Request): Promise { + const cache: Cache = await caches.open(STATIC_CACHE) + + if (request.mode === 'navigate') { + const offlinePage: Response | undefined = await caches.match('/offline.html') + if (offlinePage) return offlinePage + } + + return new Response('Offline', { + status: 503, + statusText: 'Service Unavailable', + headers: new Headers({ + 'Content-Type': 'text/plain', + }), + }) +} + +self.addEventListener('sync', (event: any) => { + if (event.tag === 'data-sync') { + event.waitUntil(syncData()) + } +}) + +async function syncData(): Promise { + try { + console.log('Syncing application data...') + } catch (error) { + console.error('Data sync failed:', error) + } +} + +interface PerformanceMessage { + type: string + name: string +} + +self.addEventListener('message', (event: MessageEvent) => { + const data = event.data as PerformanceMessage + if (data && data.type === 'PERFORMANCE_MARK') { + performance.mark(data.name) + } +}) diff --git a/scripts/sync-favicons.ts b/scripts/sync-favicons.ts new file mode 100644 index 00000000..edb8caf4 --- /dev/null +++ b/scripts/sync-favicons.ts @@ -0,0 +1,38 @@ +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +const srcDir = path.join(__dirname, '../favicon') +const dstDir = path.join(__dirname, '../docs/public') + +function ensureDir(dir: string) { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }) +} + +function copyAll(src: string, dst: string) { + ensureDir(dst) + const entries = fs.readdirSync(src, { withFileTypes: true }) + let count = 0 + for (const entry of entries) { + const s = path.join(src, entry.name) + const d = path.join(dst, entry.name) + if (entry.isDirectory()) { + copyAll(s, d) + } else if (entry.isFile()) { + fs.copyFileSync(s, d) + count++ + } + } + return count +} + +if (!fs.existsSync(srcDir)) { + console.warn('Favicons source folder not found:', srcDir) + process.exit(0) +} + +const copied = copyAll(srcDir, dstDir) +console.log(`✅ Synced ${copied} favicon file(s) from \'favicon\' to docs/public`) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..e8f544e5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "outDir": "./dist", + "rootDir": "./", + "types": ["node", "serviceworker"], + "lib": ["ES2022", "WebWorker"], + "ignoreDeprecations": "5.0" + }, + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + }, + "include": ["scripts/**/*"], + "exclude": ["node_modules", "dist", "docs/.vitepress/dist"] +} diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 00000000..e0e8fd5c --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,11 @@ +# Cloudflare Pages Configuration for SukiSU-Ultra +name = "sukisu-ultra-docs" +compatibility_date = "2025-08-04" +compatibility_flags = ["nodejs_compat"] +pages_build_output_dir = "docs/.vitepress/dist" + +[env.production] +name = "sukisu-ultra-docs" + +[env.preview] +name = "sukisu-ultra-docs-preview"