chore: init website (#5)

* chore: init website

* chore: rework website ci

* fix: working-directory

* chore: trigger website ci

* chore: optimize docs

* chore: remove unused md
This commit is contained in:
大果 2022-02-22 18:35:06 +08:00 committed by ClarkXia
parent b2600c8f43
commit 42a0a374ef
52 changed files with 1647 additions and 0 deletions

45
.github/workflows/website.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: Build Website
on:
push:
paths:
- 'website/**'
# 任务
jobs:
build-and-deploy:
# 服务器环境:最新版 Ubuntu
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./website
steps:
# 拉取代码
- uses: actions/checkout@v2
- name: Use Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- run: yarn
- run: yarn build
# 部署到 GitHub Pages
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.0
if: github.ref == 'refs/heads/master'
with:
BRANCH: gh-pages
FOLDER: build

4
.gitignore vendored
View File

@ -40,3 +40,7 @@ examples/*/.ice
build build
dist dist
.history .history
# website
.docusaurus
.cache-loader

21
website/README.md Normal file
View File

@ -0,0 +1,21 @@
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
## Installation
```console
yarn install
```
## Local Development
```console
yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
## Deployment
Just push.

3
website/babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};

74
website/config/footer.js Normal file
View File

@ -0,0 +1,74 @@
module.exports = {
style: 'dark',
links: [
{
title: '参考',
items: [
{
to: 'https://iceteam.gitee.io',
label: '国内镜像站点',
},
],
},
{
title: '社区',
items: [
{
label: '社区钉钉群',
href: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group.png',
},
{
label: '阿里内部钉钉群',
href: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group-inside.JPG',
},
{
label: 'GitHub Issue',
href: 'https://github.com/alibaba/ice/issues'
}
],
},
{
title: '生态',
items: [
{
label: '微前端 icestark',
href: 'http://micro-frontends.ice.work',
},
{
label: 'ahooks',
href: 'https://ahooks.js.org/',
},
{
label: 'Formily',
href: 'https://v2.formilyjs.org/',
},
],
},
{
title: '更多',
items: [
{
label: '淘系前端',
href: 'https://fed.taobao.org/',
},
{
label: 'Rax',
href: 'https://rax.js.org',
},
{
label: 'AppWorks',
href: 'https://appworks.site',
},
{
label: 'Kraken',
href: 'https://openkraken.com/',
},
{
label: 'Midway',
href: 'https://midwayjs.org/',
}
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} 飞冰ICE. Built with Docusaurus.`,
}

81
website/config/navbar.js Normal file
View File

@ -0,0 +1,81 @@
module.exports = {
title: '飞冰',
logo: {
alt: '飞冰ICE',
src: 'img/logo.png',
},
items: [
{
type: 'search',
position: 'right',
},
{
to: '/docs/guide/about',
position: 'right',
label: '指南',
},
{
position: 'right',
label: '插件',
to: '/docs/plugin/develop/start'
},
{
position: 'right',
label: '示例',
to: '/docs/examples/antd'
},
{
label: '生态',
position: 'right',
items: [
{
label: '微前端 icestark',
to: 'http://micro-frontends.ice.work/',
},
{
label: '可视化工具 AppWorks',
to: 'https://appworks.site/',
},
{
label: '自定义物料开发',
to: 'https://appworks.site/materials/about.html',
},
{
label: '前端环境 AppToolkit',
to: 'https://github.com/appworks-lab/toolkit#readme',
},
],
},
{
label: '资源',
position: 'right',
items: [
{
to: 'https://fusion.design/pc/doc/component/102',
label: 'fusion 组件',
},
{
to: 'https://ant.design',
label: 'antd 组件',
},
{
to: 'https://iceteam.gitee.io',
label: '国内镜像站点',
},
{
label: '社区钉钉群',
to: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group.png',
},
{
label: '阿里内部钉钉群',
to: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group-inside.JPG',
},
],
},
{
href: 'https://github.com/alibaba/ice',
label: 'GitHub',
position: 'right',
},
],
};

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const getDocsFromDir = require('../scripts/getDocsFromDir');
module.exports = {
docs: [
'guide/about',
// 'guide/start',
// 'guide/upgrade',
{
type: 'category',
label: '基础指南',
collapsed: false,
items: getDocsFromDir('guide/basic')
},
{
type: 'category',
label: '进阶指南',
collapsed: false,
items: getDocsFromDir('guide/advanced')
},
],
plugin: [
{
type: 'category',
label: '插件开发',
collapsed: false,
items: getDocsFromDir('plugin/develop')
},
{
type: 'category',
label: '官方插件',
collapsed: false,
items: getDocsFromDir('plugin/list')
},
],
examples: getDocsFromDir('examples'),
};

View File

@ -0,0 +1,4 @@
---
title: 使用 antd 组件
order: 1
---

View File

@ -0,0 +1,4 @@
---
title: 使用 fusion 组件
order: 2
---

View File

@ -0,0 +1,5 @@
---
title: 使用 Tailwind CSS
order: 3
---

View File

@ -0,0 +1,6 @@
---
title: 关于飞冰
order: 1
---
About

View File

@ -0,0 +1,6 @@
---
title: 开发指南
order: 1
---
start

View File

@ -0,0 +1,65 @@
/** @type {import('@docusaurus/types').DocusaurusConfig} */
const navbar = require('./config/navbar');
const footer = require('./config/footer');
const config = {
title: '飞冰',
tagline: '基于 React 的应用研发框架',
url: 'https://beta.ice.work',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'throw',
favicon: 'img/favicon.ico',
organizationName: 'alibaba',
projectName: 'ice',
themeConfig: {
// announcementBar: {
// id: 'announcementBar-2',
// content: 'icejs 2.0 版本已发布,支持 Webpack 5 和 Vite 两种构建模式,点击 <a href="/docs/guide/upgrade">快速升级</a>',
// isCloseable: true,
// },
navbar,
footer,
// algolia: {
// apiKey: '01f284e7e1c13eac3dc14beb6d8b153d',
// indexName: 'ice',
// },
},
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./config/sidebars.js'),
// TODO
editUrl:
'https://github.com/ice-lab/ice-next/edit/master/website/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
// TODO
// gtag: {
// trackingID: 'G-QZ0FEKY38G',
// },
},
],
],
plugins: [
require.resolve("./plugins/redirect.js"),
]
};
if (process.env.USE_LOCAL_SEARCH) {
// 内部站点无法使用 algolia
delete config.themeConfig.algolia;
config.plugins.push([
require.resolve("@easyops-cn/docusaurus-search-local"),
{
hashed: true,
language: ["en", "zh"],
},
]);
}
module.exports = config;

48
website/package.json Normal file
View File

@ -0,0 +1,48 @@
{
"name": "ice-website",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "^2.0.0-beta.15",
"@docusaurus/preset-classic": "^2.0.0-beta.15",
"@docusaurus/theme-search-algolia": "^2.0.0-beta.15",
"@easyops-cn/docusaurus-search-local": "^0.19.1",
"@mdx-js/react": "^1.6.21",
"@svgr/webpack": "^5.5.0",
"clsx": "^1.1.1",
"file-loader": "^6.2.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"url-loader": "^4.1.1"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"axios": "^0.21.1",
"fs-extra": "^10.0.0",
"glob": "^7.1.7",
"gray-matter": "^4.0.3",
"nodejieba": "^2.5.2"
}
}

View File

@ -0,0 +1,93 @@
module.exports = function (context, options) {
return {
name: 'docusaurus-redirect-plugin',
async contentLoaded({content, actions}) {
const {createData, addRoute} = actions;
const routes = [
{
from: '/docs/guide/advance/fusion',
to: '/docs/plugin/list/fusion',
},
{
from: '/docs/guide/advance/antd',
to: '/docs/plugin/list/antd',
},
{
from: '/docs/guide/develop/plugin-dev',
to: '/docs/plugin/develop/start',
},
{
from: '/docs/guide/develop/plugin-build',
to: '/docs/plugin/develop/build',
},
{
from: '/docs/guide/develop/plugin-runtime',
to: '/docs/plugin/develop/runtime',
},
{
from: '/docs/guide/develop/plugin-list',
to: '/docs/plugin/list/moment-locales',
},
{
from: '/docs/guide/basic/api',
to: '/docs/config/about',
},
];
const redirectConfigPath = await createData(
'redirectConfig.json',
JSON.stringify(routes),
);
routes.forEach((item) => {
addRoute({
path: item.from,
component: '@site/src/components/Redirect',
modules: {
// propName -> JSON file path
redirectConfig: redirectConfigPath,
},
exact: true,
});
});
addRoute({
path: '/component',
component: '@site/src/components/Redirect',
modules: {
// propName -> JSON file path
redirectConfig: redirectConfigPath,
},
});
addRoute({
path: '/docs/guide/advance',
component: '@site/src/components/Redirect',
modules: {
// propName -> JSON file path
redirectConfig: redirectConfigPath,
},
});
addRoute({
path: '/docs/materials',
component: '@site/src/components/Redirect',
modules: {
// propName -> JSON file path
redirectConfig: redirectConfigPath,
},
});
addRoute({
path: '/docs/icestark',
component: '@site/src/components/Redirect',
modules: {
// propName -> JSON file path
redirectConfig: redirectConfigPath,
},
});
},
};
}

View File

@ -0,0 +1,37 @@
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const matter = require('gray-matter');
module.exports = function getDocsFromDir(dir) {
// docs/
const baseDir = path.join(__dirname, '../docs/');
const docsDir = path.join(baseDir, dir);
function getMarkdownOrder(filepath) {
return (matter(fs.readFileSync(filepath, 'utf-8')).data || {}).order || 100;
}
const docs = glob.sync('*.md', {
cwd: docsDir,
// ignore: 'README.md',
});
const result = docs
.map((doc) => {
return path.join(docsDir, doc);
})
.sort((a, b) => {
const orderA = getMarkdownOrder(a);
const orderB = getMarkdownOrder(b);
return orderA - orderB;
})
.map((filepath) => {
// /Users/xxx/site/docs/guide/basic/router.md => guide/basic/router
const id = path.relative(baseDir, filepath).replace(/\.md/, '');
return id;
});
return result;
}

View File

@ -0,0 +1,47 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
min-height: calc(100vh - var(--ifm-navbar-height));
margin: 0 auto;
max-width: 1200px;
padding: 54px 24px;
color: var(--ifm-color-content-secondary);
}
.block {
background-color: var(--ifm-color-area);
}
.titleContent {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.titleContent h2 {
font-size: 30px;
font-weight: 600;
text-align: center;
margin-bottom: 31;
color: var(--ifm-color-title);
}
.titleContent p {
font-size: 15px;
margin: 0;
line-height: 34px;
color: #878787;
text-align: center;
}

View File

@ -0,0 +1,19 @@
import React from 'react';
import clsx from 'clsx';
import styles from './area.module.css';
function AreaWrapper({ title, decs, contentStyle, containerStyle, children, isBlock, style }) {
return (
<div className={isBlock && styles.block}>
<div className={clsx(styles.container, containerStyle)} style={style || {}}>
<div className={styles.titleContent}>
<h2>{title}</h2>
<p>{decs}</p>
</div>
<div className={contentStyle}>{children}</div>
</div>
</div>
);
}
export default AreaWrapper;

View File

@ -0,0 +1,16 @@
.badge {
display: inline-block;
font-size: 12px;
font-weight: 600;
padding: 2px 5px;
text-shadow: 0 -1px 0 rgb(0 0 0 / 10%);
box-shadow: 0 0 0 1px #fff;
border-radius: 1px;
vertical-align: top;
color: #FFF;
border-radius: 4px;
}
.error {
background-color: #ff4d4f;
}

View File

@ -0,0 +1,12 @@
import React from 'react';
import styles from './badge.module.css'
function Badge({ type = 'error', text }) {
return (
<div className={`${styles.badge} ${styles[type]}`}>
{text}
</div>
);
}
export default Badge;

View File

@ -0,0 +1,40 @@
.button {
border-radius: 28.8px;
border: 0.9px solid #E2E2E2;
padding: 13px 25px;
font-size: 16px;
color: #000;
font-weight: 600;
outline: none;
min-width: 155px;
max-height: 52px;
cursor: pointer;
text-align: center;
color: var(--ifm-color-title);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: all .3s ease;
}
.primary {
color: #fff;
border-width: 0;
background: linear-gradient(90deg, #1395FE 4.83%, #1E72FF 94.74%);
box-shadow: 0px 5px 6px rgba(0, 87, 255, 0.26);
border-radius: 28.8px;
transition: all .3s ease;
}
.button:hover {
color: #000;
background-color: #fff;
text-decoration: none;
opacity: .9;
}
.primary:hover {
color: #fff;
text-decoration: none;
opacity: .8;
}

View File

@ -0,0 +1,13 @@
import React from 'react';
import clsx from 'clsx';
import styles from './button.module.css'
function Button({ primary = true, url, children }) {
return (
<a href={url} className={clsx(styles.button, primary && styles.primary)}>
{children}
</a>
);
}
export default Button;

View File

@ -0,0 +1,89 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.container {
margin-top: 60px;
display: grid;
grid-template-columns: repeat(2, calc((100% - 24px) / 2));
gap: 24px;
min-width: 100%;
margin-bottom: 40px;
}
.card {
background: transparent;
border-radius: 7px;
border: 1px solid var(--ifm-color-border-color);
height: 300px;
display: flex;
justify-content: flex-start;
align-items: center;
color: var(--ifm-color-title);
overflow: hidden;
transition: all .25s ease;
}
.card:hover {
cursor: pointer;
text-decoration: none;
opacity: 0.76;
color: inherit;
}
.content {
position: relative;
display: flex;
flex-direction: column;
margin-right: 15px;
overflow: hidden;
}
.content div {
height: 80px;
}
.card h3 {
font-size: 22px;
margin-bottom: 24px;
}
.card span {
font-size: 14px;
opacity: 0.45;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.card img {
width: 40%;
height: auto;
}
@media (max-width: 1366px) {
.container {
grid-template-columns: repeat(1, 100%);
}
.card img {
width: 30%;
height: auto;
}
}
@media (max-width: 1050px) {
.wrapper {
padding: 0;
}
}
@media (max-width: 620px) {
.card {
height: 240px;
}
}

View File

@ -0,0 +1,50 @@
import React from 'react';
import styles from './ecology.module.css';
import AreaWrapper from '../AreaWrapper';
const data = [
{
title: 'AppWorks',
decs: '基于 VS Code 插件,通过可视化操作、物料等能力降低前端研发门槛',
image: '/img/solution_03.png',
link: 'http://appworks.site/',
},
{
title: '微前端 icestark',
decs: '面向大型 Web 应用的解决方案,将巨石单体应用进行拆解,保证大型应用的可持续扩展、技术栈按需升级以及更好的跨团队协作',
image: '/img/solution_01.png',
link: 'http://micro-frontends.ice.work/',
},
{
title: 'ahooks',
decs: 'React Hooks 最佳实践,结合业务沉淀大量的 Hooks API减少业务中重复的样板代码',
image: '/img/solution_02.png',
link: 'https://ahooks.js.org/',
},
{
title: 'Formily',
decs: '面向复杂表单的解决方案,支持数据驱动、复杂场景的高性能、复杂联动等能力',
image: '/img/solution_04.png',
link: 'https://v2.formilyjs.org/',
},
];
function Ecology() {
return (
<AreaWrapper title={'领域解决方案'} decs={'面向不同业务领域沉淀了多种解决方案'} contentStyle={styles.container}>
{data.map((item, index) => (
<a key={index} className={styles.card} href={item.link} target="_blank">
<img src={item.image}></img>
<div className={styles.content}>
<h3>{item.title}</h3>
<div>
<span>{item.decs}</span>
</div>
</div>
</a>
))}
</AreaWrapper>
);
}
export default Ecology;

View File

@ -0,0 +1,105 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.container {
margin-top: 60px;
display: grid;
grid-template-columns: repeat(3, calc((100% - 28px - 28px) / 3));
gap: 28px;
min-width: 100%;
margin-bottom: 40px;
}
.card {
position: relative;
background: var(--ifm-color-background);
border-radius: 7px;
box-shadow: 0px 9px 33px rgba(0, 0, 0, 0.05);
height: 220px;
display: flex;
z-index: 1;
color: var(--ifm-color-title);
}
.card:hover {
color: #fff;
transition: all .3s ease;
box-shadow: 0px 5px 6px rgba(0, 87, 255, 0.260635);
text-decoration: none;
}
.card:after {
z-index: 2;
opacity: 0;
position: absolute;
content: '';
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 7px;
background: linear-gradient(121.13deg, #1395FE 50.91%, #1E72FF 119.06%);
transition: all .3s ease;
}
.card:hover:after {
opacity: 1;
color: #fff;
text-decoration: none;
}
.content {
position: relative;
display: flex;
flex-direction: column;
z-index: 3;
margin: 40px 30px;
flex: 1;
overflow: hidden;
}
.card h3 {
font-size: 21px;
margin-bottom: 14px;
}
.card span {
font-size: 14px;
opacity: .85;
}
.card p {
font-size: 16px;
background: linear-gradient(90deg, #1395FE 4.83%, #1E72FF 94.74%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
.card:hover p {
font-size: 16px;
background: #fff;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0
}
@media (max-width: 1366px) {
.container {
grid-template-columns: repeat(2, calc((100% - 28px) / 2));
}
}
@media (max-width: 560px) {
.container {
grid-template-columns: repeat(1, 100%);
}
.card {
height: 200px;
}
}

View File

@ -0,0 +1,60 @@
import React from 'react';
import styles from './feature.module.css';
import AreaWrapper from '../AreaWrapper';
const data = [
{
title: '规范',
decs: '从目录组织规范到代码风格,集成了结合阿里大量项目实践的研发规范',
url: '/docs/guide/basic/structure',
},
{
title: 'Vite',
decs: '同时支持 Vite/Webpack 模式,提供极速的调试构建体验',
url: '/docs/guide/about',
},
{
title: '开箱即用',
decs: '支持 TypeScript/CSS Modules/PostCSS/... 等工程能力,框架 API 具备良好的类型提示能力',
url: '/docs/guide/basic/build',
},
{
title: '最佳实践',
decs: '内置数据请求、状态管理、SSR、前端配置、日志输出等最佳实践',
url: '/docs/guide/basic/request',
},
{
title: '应用模式',
decs: '支持 SPA、MPA、微前端、Serverless 一体化等不同研发模式',
url: '/docs/guide/advanced/mpa',
},
{
title: '插件化',
decs: '通过插件将框架能力进行解耦,同时开发者也可以基于插件扩展框架能力',
url: '/docs/plugin/develop/start',
},
];
function Feature() {
return (
<AreaWrapper
title={'基于 React 的应用研发框架 icejs'}
decs={'开箱即用的研发框架,内置工程配置、状态管理、数据请求、权限管理等最佳实践,让开发者可以更加专注于业务逻辑'}
contentStyle={styles.container}
isBlock
>
{data.map((item, index) => (
<a key={index} className={styles.card} href={item.url}>
<div className={styles.content}>
<h3>{item.title}</h3>
<span>{item.decs}</span>
<div style={{ flex: 1 }}></div>
<p>{'Documentation >'}</p>
</div>
</a>
))}
</AreaWrapper>
);
}
export default Feature;

View File

@ -0,0 +1,34 @@
import React, { useEffect } from 'react';
export default function Redirect(props) {
const { location, history, redirectConfig = [] } = props;
const { pathname } = location;
useEffect(() => {
const item = redirectConfig.find((item) => item.from === pathname.replace(/\/$/, ''));
if (item) {
history.push(item.to);
} else {
if (/^\/component/.test(pathname)) {
// fusion /component/xxx -> /docs/fusion/about
history.push('/docs/fusion/about');
} else if (/^\/docs\/guide\/advance\//.test(pathname)) {
// advance -> advanced: /docs/guide/advance/xxx -> /docs/guide/advanced/xxx
history.push(pathname.replace('/advance/', '/advanced/'));
} else if (/^\/docs\/materials\//.test(pathname)) {
// /docs/materials/xxx -> https://appworks.site/materials/xxx.html
const targetUrl = `https://appworks.site/materials/${pathname.replace('/docs/materials/', '')}.html`;
window.location.replace(targetUrl);
} else if (/^\/docs\/icestark\//.test(pathname)) {
// icestark /docs/icestark/xxx -> https://micro-frontends.ice.work/
const targetUrl = 'https://micro-frontends.ice.work';
window.location.replace(targetUrl);
} else {
console.log('未知路由', pathname);
}
}
}, []);
return null;
}

View File

@ -0,0 +1,37 @@
import React from 'react';
import Button from '../Button';
import styles from './splash.module.css';
import splash from '../../../static/img/splash.png';
function Splash() {
return (
<header>
<div className={styles.splash}>
<div className={styles['title-container']}>
<h1 className={styles.title}>飞冰ICE 3.0</h1>
<p className={styles.subtitle}>
基于 React 的应用研发框架
</p>
<div className={styles.githubStars}>
<iframe
src="https://ghbtns.com/github-btn.html?user=alibaba&repo=ice&type=star&count=true&size=large"
frameBorder="0"
scrolling="0"
width="170"
height="30"
title="GitHub"
></iframe>
</div>
<div className={styles.buttons}>
<Button url={'/docs/guide/start'}>快速开始</Button>
</div>
</div>
<div className={styles['img-container']}>
<img className={styles['splash-img']} src={splash} />
</div>
</div>
</header>
);
}
export default Splash;

View File

@ -0,0 +1,122 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.splash {
display: grid;
overflow: hidden;
align-items: center;
min-height: calc(100vh - var(--ifm-navbar-height));
grid-template-areas: 'b a';
grid-template-columns: 1fr 1fr;
margin: 0 auto;
padding: 24px;
max-width: 1200px;
background-color: var(--ifm-background-color);
color: var(--ifm-color-content-secondary);
}
.title-container {
display: flex;
flex: 1;
flex-direction: column;
align-content: flex-start;
}
.title {
color: var(--ifm-color-title);
font-size: 40px;
font-weight: 600;
text-align: left;
}
.subtitle {
font-size: 16px;
line-height: 34px;
color: #878787;
}
.buttons {
display: flex;
align-items: center;
justify-content: flex-start;
}
.githubStars {
display: flex;
margin-bottom: 40px;
}
.img-container {
display: flex;
flex: 1;
margin: 45px;
}
.img {
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
@media (max-width: 900px) {
.splash {
grid-template-areas: 'a' 'b';
grid-template-columns: 1fr;
}
.title {
text-align: center;
}
.title-container {
margin-top: 100px;
}
.subtitle {
text-align: center;
}
.buttons {
justify-content: center;
}
.githubStars {
justify-content: center;
}
.img-container {
justify-content: center;
align-items: center;
margin: 70px;
}
.img {
max-width: 100px;
}
}
@media (max-width: 510px) {
.buttons {
flex-direction: column;
margin-bottom: 40px;
}
.buttons a {
width: calc(100% - 32px);
}
.title {
font-size: 36px;
}
.img-container {
margin-top: 50px;
margin: 20px;
}
}

View File

@ -0,0 +1,22 @@
import React from 'react';
import styles from './support.module.css';
function Support({ list }) {
const availablePlatforms = ['webpack', 'vite'];
return (
<span className={styles.container}>
{availablePlatforms.map((supportPlatform) => {
return (
<img
title={supportPlatform}
className={styles[supportPlatform]}
key={supportPlatform}
src={`/img/svg/${list.includes(supportPlatform) ? supportPlatform : `${supportPlatform}-gray`}.svg`}
/>
);
})}
</span>
);
}
export default Support;

View File

@ -0,0 +1,18 @@
.container {
position: relative;
top: 2px;
}
.container img {
margin-right: 5px;
}
.webpack {
height: 18px;
}
.vite {
height: 16px;
position: relative;
top: -2px;
}

View File

@ -0,0 +1,81 @@
import React from 'react';
import styles from './users.module.css';
import AreaWrapper from '../AreaWrapper';
const data = [
{
name: '淘宝',
image: 'https://img.alicdn.com/tfs/TB1zdJliDtYBeNjy1XdXXXXyVXa-184-76.png',
},
{
name: '菜鸟',
image: 'https://img.alicdn.com/tfs/TB1LgSMibuWBuNjSszgXXb8jVXa-206-72.png',
},
{
name: '新华智云',
image: 'https://img.alicdn.com/tfs/TB1jFDwiamWBuNjy1XaXXXCbXXa-284-56.png',
fill: true
},
{
name: '口碑',
image: 'https://img.alicdn.com/tfs/TB147fnikSWBuNjSszdXXbeSpXa-180-68.png',
fill: true
},
{
name: '钉钉',
image: 'https://img.alicdn.com/tfs/TB1fdJliDtYBeNjy1XdXXXXyVXa-208-78.png',
},
{
name: '阿里健康',
image: 'https://img.alicdn.com/tfs/TB19a2XikyWBuNjy0FpXXassXXa-244-68.png',
},
{
name: 'AliExpress',
image: 'https://img.alicdn.com/tfs/TB1m7veieuSBuNjSsziXXbq8pXa-262-62.png',
},
{
name: '阿里妈妈',
image: 'https://img.alicdn.com/tfs/TB10Mjkib1YBuNjSszhXXcUsFXa-208-76.png',
},
{
name: '闲鱼',
image: 'https://img.alicdn.com/tfs/TB1DPSIibGYBuNjy0FoXXciBFXa-128-60.png',
fill: true
},
{
name: '阿里云',
image: 'https://img.alicdn.com/tfs/TB1y9TNioR1BeNjy0FmXXb0wVXa-254-74.png',
fill: true
},
{
name: '优酷',
image: 'https://img.alicdn.com/tfs/TB1SpDwiamWBuNjy1XaXXXCbXXa-242-46.png',
},
{
name: '阿里通信',
image: 'https://img.alicdn.com/tfs/TB1EkveieuSBuNjSsziXXbq8pXa-240-78.png',
fill: true
},
];
function Users() {
return (
<AreaWrapper
title={'谁在使用'}
decs={'飞冰广泛服务于阿里巴巴众多面向运营、商家以及消费者端的业务'}
contentStyle={styles.content}
style={{
minHeight: 'auto',
}}
isBlock
>
{data.map((item, index) => (
<div key={index} className={styles.logo}>
<img alt={item.name} src={item.image} className={item.fill && styles.fill}></img>
</div>
))}
</AreaWrapper>
);
}
export default Users;

View File

@ -0,0 +1,49 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.content {
margin-top: 60px;
margin-bottom: 40px;
display: flex;
justify-content: center;
flex-flow: row wrap;
}
.logo {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
margin: 40px 26px 0 26px;
overflow: hidden;
height: 40px;
}
.logo span {
font-size: 14px;
opacity: 0.45;
color: var(--ifm-color-title);
}
.logo img {
height: 40px;
overflow: hidden;
}
.fill {
filter: var(--ice-users-fill-filter);
transform: var(--ice-users-fill-transform);
}
@media (max-width: 510px) {
.buttons {
flex-direction: column;
}
.logo {
margin: 0 20px 52px 20px;
}
}

View File

@ -0,0 +1,78 @@
/* stylelint-disable docusaurus/copyright-header */
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #5485f7;
--ifm-color-title: #111;
--ifm-color-background: #fff;
--ifm-color-border-color: rgba(208, 208, 208, 0.44);
--ifm-color-area: #fafafa;
/* --ifm-color-primary-dark: rgb(33, 175, 144);
--ifm-color-primary-darker: rgb(31, 165, 136);
--ifm-color-primary-darkest: rgb(26, 136, 112);
--ifm-color-primary-light: rgb(70, 203, 174);
--ifm-color-primary-lighter: rgb(102, 212, 189);
--ifm-color-primary-lightest: rgb(146, 224, 208); */
--ifm-code-font-size: 95%;
--ifm-container-width-xl: 1600px;
--ifm-footer-title-color: #fff;
/* --ifm-container-width: 1140 */
--site-primary-hue-saturation: 167, 68%;
--site-primary-hue-saturation-light: 167, 56%; /* do we really need this extra one? */
}
:root[data-theme='dark'] {
--ifm-color-title: #fff;
--ifm-color-background: #2a2d31;
--ifm-color-border-color: rgba(149, 149, 149, 0.27);
--ifm-color-area: #242527;
--ifm-footer-title-color: #fff;
--ice-users-fill-filter: drop-shadow(0 40px rgba(255, 255, 255, .72));
--ice-users-fill-transform: translateY(-40px);
}
.docusaurus-highlight-code-line {
background-color: rgb(72, 77, 91);
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
}
.navbar__title {
font-size: 22px;
margin-left: 4px;
}
.navbar__logo {
height: 50px;
}
.navbar__search-input:focus {
outline: none;
}
div[class^='announcementBar_'] {
--site-announcement-bar-stripe-color1: hsl(
var(--site-primary-hue-saturation),
85%
);
--site-announcement-bar-stripe-color2: hsl(
var(--site-primary-hue-saturation),
95%
);
background: repeating-linear-gradient(
35deg,
var(--site-announcement-bar-stripe-color1),
var(--site-announcement-bar-stripe-color1) 20px,
var(--site-announcement-bar-stripe-color2) 10px,
var(--site-announcement-bar-stripe-color2) 40px
);
font-weight: bold;
}

View File

@ -0,0 +1,24 @@
/**
* 首页
*/
import React from 'react';
import Layout from '@theme/Layout';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Splash from '../components/Splash';
import Feature from '../components/Feature';
// import Ecology from '../components/Ecology';
import Users from '../components/Users';
export default function Home() {
const { siteConfig } = useDocusaurusContext();
return (
<Layout title={`${siteConfig.title}-${siteConfig.tagline}`} description="基于 React 的应用研发框架">
<Splash />
<main>
<Feature />
{/* <Ecology /> */}
<Users />
</main>
</Layout>
);
}

68
website/src/theme/Root.js Normal file
View File

@ -0,0 +1,68 @@
import React, { useEffect, useState } from 'react';
import clsx from 'clsx';
import storage from '../utils/storage';
import styles from './Root.module.css';
const NO_REDIRECT_KEY = 'no-redirect-internal';
const STORAGE_VALID_TIME = 7 * (24 * 60 * 60 * 1000);
// Default implementation, that you can customize
function Root({ children }) {
const [noticeVisible, setNoticeVisible] = useState(false);
// TODO
// useEffect(() => {
// const noNeedRedirect = /alibaba-inc\.com/.test(window.location.href) || storage.get(NO_REDIRECT_KEY) === 'TRUE';
// if (noNeedRedirect) {
// return;
// }
// const privateURL =
// 'https://private-alipayobjects.alipay.com/alipay-rmsdeploy-image/rmsportal/VmvVUItLdPNqKlNGuRHi.png?r=' +
// Date.now();
// const img = new Image();
// img.onload = () => {
// setNoticeVisible(true);
// };
// img.src = privateURL;
// setTimeout(() => {
// img.src = null;
// }, 1000);
// }, []);
return (
<>
{children}
{noticeVisible && (
<div className={styles.wrapper}>
<div className={styles.container}>
<p className={styles.content}>检测到您是内网用户建议前往内部官网 ice.alibaba-inc.com 以获取更多信息</p>
<div className={styles.action}>
<div
className={clsx(styles.btn, styles.primaryBtn)}
onClick={() => {
location.href = 'https://ice.alibaba-inc.com';
}}
>
去内部官网推荐
</div>
<div
className={clsx(styles.btn)}
onClick={() => {
setNoticeVisible(false);
storage.set(NO_REDIRECT_KEY, 'TRUE', STORAGE_VALID_TIME);
}}
>
七天内不再提示
</div>
</div>
</div>
</div>
)}
</>
);
}
export default Root;

View File

@ -0,0 +1,43 @@
.wrapper {
position: fixed;
z-index: 1000;
bottom: 0;
left: 0;
width: 100%;
min-height: 300px;
background-color: #303846;
color: #fff;
}
.container {
margin: 0px auto;
max-width: 1200px;
padding: 54px 24px;
}
.content {
font-size: 18px;
}
.action {
display: flex;
margin-top: 20px;
/* justify-content: flex-end; */
}
.btn {
display: inline-block;
cursor: pointer;
background-color: #222;
color: #ccc;
padding: 8px 12px;
margin-right: 20px;
}
.btn:hover {
opacity: 0.8;
}
.primaryBtn {
background-color: #fff;
color: #000;
}

View File

@ -0,0 +1,42 @@
export default {
get: (key) => {
const result = window.localStorage.getItem(key);
if (result === null) {
return null;
}
try {
const { value, validTime, writeTime } = JSON.parse(result);
if (Date.now() - writeTime > validTime) {
// 已过期
window.localStorage.removeItem(key);
return null;
}
return value;
} catch (err) {
console.error('storage.get error', err);
// 清除掉不合法数据,防止持续报错
window.localStorage.removeItem(key);
return null;
}
},
/**
* 写入
* @param {String} key
* @param {String} value
* @param {String} validTime 有效时间单位 ms
*/
set: (key, value, validTime) => {
window.localStorage.setItem(
key,
JSON.stringify({
value,
validTime,
writeTime: Date.now(),
}),
);
},
};

0
website/static/.nojekyll Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
website/static/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@ -0,0 +1,15 @@
<svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg" >
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
<stop stop-color="#999"/>
<stop offset="1" stop-color="#ccc"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
<stop stop-color="#999"/>
<stop offset="0.0833333" stop-color="#666"/>
<stop offset="1" stop-color="#999"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,15 @@
<svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
<stop stop-color="#41D1FF"/>
<stop offset="1" stop-color="#BD34FE"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFEA83"/>
<stop offset="0.0833333" stop-color="#FFDD35"/>
<stop offset="1" stop-color="#FFA800"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,5 @@
<svg viewBox="0 0 774 875.7" xmlns="http://www.w3.org/2000/svg">
<path d="m387 0 387 218.9v437.9l-387 218.9-387-218.9v-437.9z" fill="#fff"/>
<path d="m704.9 641.7-305.1 172.6v-134.4l190.1-104.6zm20.9-18.9v-360.9l-111.6 64.5v232zm-657.9 18.9 305.1 172.6v-134.4l-190.2-104.6zm-20.9-18.9v-360.9l111.6 64.5v232zm13.1-384.3 312.9-177v129.9l-200.5 110.3-1.6.9zm652.6 0-312.9-177v129.9l200.5 110.2 1.6.9z" fill="#ccc"/>
<path d="m373 649.3-187.6-103.2v-204.3l187.6 108.3zm26.8 0 187.6-103.1v-204.4l-187.6 108.3zm-201.7-331.1 188.3-103.5 188.3 103.5-188.3 108.7z" fill="#aaa"/>
</svg>

After

Width:  |  Height:  |  Size: 576 B

View File

@ -0,0 +1,5 @@
<svg viewBox="0 0 774 875.7" xmlns="http://www.w3.org/2000/svg">
<path d="m387 0 387 218.9v437.9l-387 218.9-387-218.9v-437.9z" fill="#fff"/>
<path d="m704.9 641.7-305.1 172.6v-134.4l190.1-104.6zm20.9-18.9v-360.9l-111.6 64.5v232zm-657.9 18.9 305.1 172.6v-134.4l-190.2-104.6zm-20.9-18.9v-360.9l111.6 64.5v232zm13.1-384.3 312.9-177v129.9l-200.5 110.3-1.6.9zm652.6 0-312.9-177v129.9l200.5 110.2 1.6.9z" fill="#8ed6fb"/>
<path d="m373 649.3-187.6-103.2v-204.3l187.6 108.3zm26.8 0 187.6-103.1v-204.4l-187.6 108.3zm-201.7-331.1 188.3-103.5 188.3 103.5-188.3 108.7z" fill="#1c78c0"/>
</svg>

After

Width:  |  Height:  |  Size: 582 B