diff --git a/.github/labeler.yml b/.github/labeler.yml
index de5759a57f..7fc60e08d8 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -48,3 +48,5 @@ app:web: 'apps/web/**/*'
app:electron: 'apps/electron/**/*'
app:server: 'apps/server/**/*'
+
+app:docs: 'apps/docs/**/*'
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 87ce7078bc..0ac223aa7e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -48,6 +48,19 @@ jobs:
yarn lint --max-warnings=0
yarn circular
+ build-docs:
+ name: Build Docs
+ runs-on: ubuntu-latest
+ environment: development
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup Node.js
+ uses: ./.github/actions/setup-node
+ - run: yarn nx build @affine/docs
+ env:
+ NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
+
build-storybook:
name: Build Storybook
runs-on: ubuntu-latest
diff --git a/.gitignore b/.gitignore
index 97c37bddf8..90550a7e9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ Thumbs.db
.history
.next
+.vercel
out/
storybook-static
i18n-generated.ts
diff --git a/apps/docs/entries.ts b/apps/docs/entries.ts
new file mode 100644
index 0000000000..6103ac4d58
--- /dev/null
+++ b/apps/docs/entries.ts
@@ -0,0 +1,21 @@
+import { defineEntries } from 'waku/server';
+
+export default defineEntries(
+ // getEntry
+ async id => {
+ switch (id) {
+ case 'App':
+ return import('./src/app.js') as any;
+ default:
+ return null;
+ }
+ },
+ // getBuildConfig
+ async () => {
+ return {
+ '/': {
+ elements: [['App', {}]],
+ },
+ };
+ }
+);
diff --git a/apps/docs/index.html b/apps/docs/index.html
new file mode 100644
index 0000000000..867f772e71
--- /dev/null
+++ b/apps/docs/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+ AFFiNE Developer Documentation
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/docs/package.json b/apps/docs/package.json
new file mode 100644
index 0000000000..569ebe07fb
--- /dev/null
+++ b/apps/docs/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@affine/docs",
+ "version": "0.1.0",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "waku dev",
+ "build": "waku build",
+ "build:vercel": "waku build && cp -Lr ./dist/.vercel/output ./.vercel/"
+ },
+ "dependencies": {
+ "@affine/component": "workspace:*",
+ "@blocksuite/block-std": "0.0.0-20230624163241-751f7170-nightly",
+ "@blocksuite/blocks": "0.0.0-20230624163241-751f7170-nightly",
+ "@blocksuite/editor": "0.0.0-20230624163241-751f7170-nightly",
+ "@blocksuite/global": "0.0.0-20230624163241-751f7170-nightly",
+ "@blocksuite/lit": "0.0.0-20230624163241-751f7170-nightly",
+ "@blocksuite/store": "0.0.0-20230624163241-751f7170-nightly",
+ "express": "^4.18.2",
+ "react": "18.3.0-canary-16d053d59-20230506",
+ "react-dom": "18.3.0-canary-16d053d59-20230506",
+ "react-server-dom-webpack": "18.3.0-canary-16d053d59-20230506",
+ "waku": "0.12.1"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.12",
+ "@types/react-dom": "^18.2.5",
+ "@vanilla-extract/css": "^1.11.1",
+ "@vanilla-extract/vite-plugin": "^3.8.2",
+ "autoprefixer": "^10.4.14",
+ "tailwindcss": "^3.3.2",
+ "typescript": "^5.1.3"
+ }
+}
diff --git a/apps/docs/postcss.config.mjs b/apps/docs/postcss.config.mjs
new file mode 100644
index 0000000000..2aa7205d4b
--- /dev/null
+++ b/apps/docs/postcss.config.mjs
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/apps/docs/src/app.tsx b/apps/docs/src/app.tsx
new file mode 100644
index 0000000000..a68408b58f
--- /dev/null
+++ b/apps/docs/src/app.tsx
@@ -0,0 +1,26 @@
+'use server';
+import fs from 'node:fs/promises';
+import path from 'node:path';
+
+import type { ReactElement } from 'react';
+import { lazy } from 'react';
+
+const Editor = lazy(() =>
+ import('./components/editor.js').then(({ Editor }) => ({ default: Editor }))
+);
+
+const markdown = await fs.readFile(path.join('./src/pages/index.md'), {
+ encoding: 'utf-8',
+});
+
+const App = (): ReactElement => {
+ return (
+
+ );
+};
+
+export default App;
diff --git a/apps/docs/src/components/editor.tsx b/apps/docs/src/components/editor.tsx
new file mode 100644
index 0000000000..60c026fcc4
--- /dev/null
+++ b/apps/docs/src/components/editor.tsx
@@ -0,0 +1,54 @@
+'use client';
+import '@blocksuite/editor/themes/affine.css';
+
+import { BlockSuiteEditor } from '@affine/component/block-suite-editor';
+import { ContentParser } from '@blocksuite/blocks/content-parser';
+import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
+import { assertExists, Workspace } from '@blocksuite/store';
+import type { ReactElement } from 'react';
+import { useCallback } from 'react';
+
+const workspace = new Workspace({
+ id: 'local-workspace',
+})
+ .register(AffineSchemas)
+ .register(__unstableSchemas);
+
+const page = workspace.createPage({
+ id: 'example-page',
+});
+
+export type EditorProps = {
+ text: string;
+};
+
+export const Editor = (props: EditorProps): ReactElement => {
+ return (
+ {
+ const text = props.text;
+ await page.waitForLoaded();
+ const metadata = text.split('---\n')[1];
+ assertExists(metadata);
+
+ // find title
+ const title = metadata.split('title: ')[1]?.split('\n')[0];
+ const pageBlockId = page.addBlock('affine:page', {
+ title: new page.Text(title),
+ });
+ page.addBlock('affine:surface', {}, pageBlockId);
+ const noteBlockId = page.addBlock('affine:note', {}, pageBlockId);
+ const contentParser = new ContentParser(page);
+ const content = text.split('---\n')[2];
+ assertExists(content);
+ console.log('metadata', title, content);
+ await contentParser.importMarkdown(content, noteBlockId);
+ },
+ [props.text]
+ )}
+ />
+ );
+};
diff --git a/apps/docs/src/index.css b/apps/docs/src/index.css
new file mode 100644
index 0000000000..b5c61c9567
--- /dev/null
+++ b/apps/docs/src/index.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/apps/docs/src/index.tsx b/apps/docs/src/index.tsx
new file mode 100644
index 0000000000..652a0a60dc
--- /dev/null
+++ b/apps/docs/src/index.tsx
@@ -0,0 +1,14 @@
+import './index.css';
+
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+import { serve } from 'waku/client';
+
+const App = serve('App');
+const rootElement = (
+
+
+
+);
+
+createRoot(document.getElementById('root') as HTMLElement).render(rootElement);
diff --git a/apps/docs/src/pages/index.md b/apps/docs/src/pages/index.md
new file mode 100644
index 0000000000..74666683b8
--- /dev/null
+++ b/apps/docs/src/pages/index.md
@@ -0,0 +1,9 @@
+---
+title: AFFiNE Developer Documentation
+---
+
+```shell
+corepack enable
+yarn install
+nx dev @affine/docs
+```
diff --git a/apps/docs/tailwind.config.mjs b/apps/docs/tailwind.config.mjs
new file mode 100644
index 0000000000..b620f7f422
--- /dev/null
+++ b/apps/docs/tailwind.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ['./index.html', './src/**/*.{ts,tsx}'],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json
new file mode 100644
index 0000000000..7dfad6d12a
--- /dev/null
+++ b/apps/docs/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "moduleResolution": "Node16",
+ "strict": true,
+ "target": "esnext",
+ "downlevelIteration": true,
+ "esModuleInterop": true,
+ "module": "NodeNext",
+ "skipLibCheck": true,
+ "noUncheckedIndexedAccess": true,
+ "exactOptionalPropertyTypes": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src", "entries.ts"],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ },
+ {
+ "path": "../../packages/component"
+ }
+ ]
+}
diff --git a/apps/docs/tsconfig.node.json b/apps/docs/tsconfig.node.json
new file mode 100644
index 0000000000..5a7ebf789a
--- /dev/null
+++ b/apps/docs/tsconfig.node.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "composite": true,
+ "target": "ESNext",
+ "module": "ESNext",
+ "resolveJsonModule": true,
+ "moduleResolution": "Node16",
+ "allowSyntheticDefaultImports": true,
+ "outDir": "dist/scripts",
+ "rootDir": "."
+ },
+ "include": ["vite.config.ts", "vite.prod.config.ts"]
+}
diff --git a/apps/docs/vite.config.ts b/apps/docs/vite.config.ts
new file mode 100644
index 0000000000..365ff28aac
--- /dev/null
+++ b/apps/docs/vite.config.ts
@@ -0,0 +1,13 @@
+import path from 'node:path';
+import url from 'node:url';
+
+import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
+import { defineConfig } from 'waku/config';
+
+export default defineConfig({
+ root: path.dirname(url.fileURLToPath(import.meta.url)),
+ plugins: [vanillaExtractPlugin()],
+ build: {
+ target: 'esnext',
+ },
+});
diff --git a/packages/component/src/components/block-suite-editor/index.tsx b/packages/component/src/components/block-suite-editor/index.tsx
index 2555e3c69c..99f09232ad 100644
--- a/packages/component/src/components/block-suite-editor/index.tsx
+++ b/packages/component/src/components/block-suite-editor/index.tsx
@@ -1,4 +1,3 @@
-import { config } from '@affine/env';
import { editorContainerModuleAtom } from '@affine/jotai';
import type { BlockHub } from '@blocksuite/blocks';
import type { EditorContainer } from '@blocksuite/editor';
@@ -195,7 +194,7 @@ export const BlockSuiteEditor = memo(function BlockSuiteEditor(
}>
- {config.enableImagePreviewModal && props.page && (
+ {props.page && (
{createPortal(
=8.0.9"
+ ts-node: ">=9.0.0"
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ checksum: b61f890499ed7dcda1e36c20a9582b17d745bad5e2b2c7bc96942465e406bc43ae03f270c08e60d1e29dab1ee50cb26970b5eb20c9aae30e066e20bd607ae4e4
+ languageName: node
+ linkType: hard
+
+"postcss-nested@npm:^6.0.1":
+ version: 6.0.1
+ resolution: "postcss-nested@npm:6.0.1"
+ dependencies:
+ postcss-selector-parser: ^6.0.11
+ peerDependencies:
+ postcss: ^8.2.14
+ checksum: 7ddb0364cd797de01e38f644879189e0caeb7ea3f78628c933d91cc24f327c56d31269384454fc02ecaf503b44bfa8e08870a7c4cc56b23bc15640e1894523fa
+ languageName: node
+ linkType: hard
+
+"postcss-selector-parser@npm:^6.0.11":
+ version: 6.0.13
+ resolution: "postcss-selector-parser@npm:6.0.13"
+ dependencies:
+ cssesc: ^3.0.0
+ util-deprecate: ^1.0.2
+ checksum: f89163338a1ce3b8ece8e9055cd5a3165e79a15e1c408e18de5ad8f87796b61ec2d48a2902d179ae0c4b5de10fccd3a325a4e660596549b040bc5ad1b465f096
+ languageName: node
+ linkType: hard
+
+"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.2.0":
+ version: 4.2.0
+ resolution: "postcss-value-parser@npm:4.2.0"
+ checksum: 819ffab0c9d51cf0acbabf8996dffbfafbafa57afc0e4c98db88b67f2094cb44488758f06e5da95d7036f19556a4a732525e84289a425f4f6fd8e412a9d7442f
+ languageName: node
+ linkType: hard
+
"postcss-values-parser@npm:^2.0.1":
version: 2.0.1
resolution: "postcss-values-parser@npm:2.0.1"
@@ -26504,6 +26822,21 @@ __metadata:
languageName: node
linkType: hard
+"react-server-dom-webpack@npm:18.3.0-canary-16d053d59-20230506":
+ version: 18.3.0-canary-16d053d59-20230506
+ resolution: "react-server-dom-webpack@npm:18.3.0-canary-16d053d59-20230506"
+ dependencies:
+ acorn-loose: ^8.3.0
+ loose-envify: ^1.1.0
+ neo-async: ^2.6.1
+ peerDependencies:
+ react: 18.3.0-canary-16d053d59-20230506
+ react-dom: 18.3.0-canary-16d053d59-20230506
+ webpack: ^5.59.0
+ checksum: 3d12d8e1f777adf77da23dc5ae6955226af60fe64ea94c068b1401314102ea72bb59fdaf6b41902190fba75b7070c3669f2fe4ab107ad855510723d126feb3cb
+ languageName: node
+ linkType: hard
+
"react-style-singleton@npm:^2.2.1":
version: 2.2.1
resolution: "react-style-singleton@npm:2.2.1"
@@ -26573,6 +26906,15 @@ __metadata:
languageName: node
linkType: hard
+"read-cache@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "read-cache@npm:1.0.0"
+ dependencies:
+ pify: ^2.3.0
+ checksum: cffc728b9ede1e0667399903f9ecaf3789888b041c46ca53382fa3a06303e5132774dc0a96d0c16aa702dbac1ea0833d5a868d414f5ab2af1e1438e19e6657c6
+ languageName: node
+ linkType: hard
+
"read-pkg-up@npm:^2.0.0":
version: 2.0.0
resolution: "read-pkg-up@npm:2.0.0"
@@ -27071,7 +27413,7 @@ __metadata:
languageName: node
linkType: hard
-"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.21.0, resolve@npm:^1.22.1, resolve@npm:~1.22.1":
+"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.21.0, resolve@npm:^1.22.1, resolve@npm:^1.22.2, resolve@npm:~1.22.1":
version: 1.22.3
resolution: "resolve@npm:1.22.3"
dependencies:
@@ -27107,7 +27449,7 @@ __metadata:
languageName: node
linkType: hard
-"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.21.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@~1.22.1#~builtin":
+"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.21.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.22.2#~builtin, resolve@patch:resolve@~1.22.1#~builtin":
version: 1.22.3
resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=c3c19d"
dependencies:
@@ -28542,6 +28884,24 @@ __metadata:
languageName: node
linkType: hard
+"sucrase@npm:^3.32.0":
+ version: 3.32.0
+ resolution: "sucrase@npm:3.32.0"
+ dependencies:
+ "@jridgewell/gen-mapping": ^0.3.2
+ commander: ^4.0.0
+ glob: 7.1.6
+ lines-and-columns: ^1.1.6
+ mz: ^2.7.0
+ pirates: ^4.0.1
+ ts-interface-checker: ^0.1.9
+ bin:
+ sucrase: bin/sucrase
+ sucrase-node: bin/sucrase-node
+ checksum: 79f760aef513adcf22b882d43100296a8afa7f307acef3e8803304b763484cf138a3e2cebc498a6791110ab20c7b8deba097f6ce82f812ca8f1723e3440e5c95
+ languageName: node
+ linkType: hard
+
"sudo-prompt@npm:^9.1.1":
version: 9.2.1
resolution: "sudo-prompt@npm:9.2.1"
@@ -28708,6 +29068,40 @@ __metadata:
languageName: node
linkType: hard
+"tailwindcss@npm:^3.3.2":
+ version: 3.3.2
+ resolution: "tailwindcss@npm:3.3.2"
+ dependencies:
+ "@alloc/quick-lru": ^5.2.0
+ arg: ^5.0.2
+ chokidar: ^3.5.3
+ didyoumean: ^1.2.2
+ dlv: ^1.1.3
+ fast-glob: ^3.2.12
+ glob-parent: ^6.0.2
+ is-glob: ^4.0.3
+ jiti: ^1.18.2
+ lilconfig: ^2.1.0
+ micromatch: ^4.0.5
+ normalize-path: ^3.0.0
+ object-hash: ^3.0.0
+ picocolors: ^1.0.0
+ postcss: ^8.4.23
+ postcss-import: ^15.1.0
+ postcss-js: ^4.0.1
+ postcss-load-config: ^4.0.1
+ postcss-nested: ^6.0.1
+ postcss-selector-parser: ^6.0.11
+ postcss-value-parser: ^4.2.0
+ resolve: ^1.22.2
+ sucrase: ^3.32.0
+ bin:
+ tailwind: lib/cli.js
+ tailwindcss: lib/cli.js
+ checksum: 4897c70e671c885e151f57434d87ccb806f468a11900f028245b351ffbca5245ff0c10ca5dbb6eb4c7c4df3de8a15a05fe08c2aea4b152cb07bee9bb1d8a14a8
+ languageName: node
+ linkType: hard
+
"tapable@npm:^2.1.1, tapable@npm:^2.2.0":
version: 2.2.1
resolution: "tapable@npm:2.2.1"
@@ -28896,6 +29290,24 @@ __metadata:
languageName: node
linkType: hard
+"thenify-all@npm:^1.0.0":
+ version: 1.6.0
+ resolution: "thenify-all@npm:1.6.0"
+ dependencies:
+ thenify: ">= 3.1.0 < 4"
+ checksum: dba7cc8a23a154cdcb6acb7f51d61511c37a6b077ec5ab5da6e8b874272015937788402fd271fdfc5f187f8cb0948e38d0a42dcc89d554d731652ab458f5343e
+ languageName: node
+ linkType: hard
+
+"thenify@npm:>= 3.1.0 < 4":
+ version: 3.3.1
+ resolution: "thenify@npm:3.3.1"
+ dependencies:
+ any-promise: ^1.0.0
+ checksum: 84e1b804bfec49f3531215f17b4a6e50fd4397b5f7c1bccc427b9c656e1ecfb13ea79d899930184f78bc2f57285c54d9a50a590c8868f4f0cef5c1d9f898b05e
+ languageName: node
+ linkType: hard
+
"through2@npm:^2.0.3":
version: 2.0.5
resolution: "through2@npm:2.0.5"
@@ -29145,6 +29557,13 @@ __metadata:
languageName: node
linkType: hard
+"ts-interface-checker@npm:^0.1.9":
+ version: 0.1.13
+ resolution: "ts-interface-checker@npm:0.1.13"
+ checksum: 20c29189c2dd6067a8775e07823ddf8d59a33e2ffc47a1bd59a5cb28bb0121a2969a816d5e77eda2ed85b18171aa5d1c4005a6b88ae8499ec7cc49f78571cb5e
+ languageName: node
+ linkType: hard
+
"ts-log@npm:^2.2.3":
version: 2.2.5
resolution: "ts-log@npm:2.2.5"
@@ -30301,6 +30720,27 @@ __metadata:
languageName: node
linkType: hard
+"waku@npm:0.12.1":
+ version: 0.12.1
+ resolution: "waku@npm:0.12.1"
+ dependencies:
+ "@swc/core": 1.3.64
+ "@vitejs/plugin-react": ^4.0.0
+ busboy: ^1.6.0
+ vite: ^4.3.9
+ peerDependencies:
+ express: ^4.18.2
+ react: 18.3.0-canary-613e6f5fc-20230616
+ react-server-dom-webpack: 18.3.0-canary-613e6f5fc-20230616
+ peerDependenciesMeta:
+ express:
+ optional: true
+ bin:
+ waku: dist/cli.js
+ checksum: c0df6ac35e79eb3216be287db3d5a4507982a50334d7a474cabd70171754adba742f60fef8ae32f512cc82cd207b591158079d798d208db407308c6cd835d77d
+ languageName: node
+ linkType: hard
+
"walkdir@npm:^0.4.1":
version: 0.4.1
resolution: "walkdir@npm:0.4.1"
@@ -30876,7 +31316,7 @@ __metadata:
languageName: node
linkType: hard
-"yaml@npm:^2.2.1, yaml@npm:^2.2.2":
+"yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2":
version: 2.3.1
resolution: "yaml@npm:2.3.1"
checksum: 2c7bc9a7cd4c9f40d3b0b0a98e370781b68b8b7c4515720869aced2b00d92f5da1762b4ffa947f9e795d6cd6b19f410bd4d15fdd38aca7bd96df59bd9486fb54