refactor: remove bookmark plugin (#4544)

This commit is contained in:
Alex Yang 2023-09-30 00:48:33 -05:00 committed by GitHub
parent b440c3a820
commit c911806062
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 32 additions and 361 deletions

View File

@ -125,7 +125,6 @@ If you have questions, you are welcome to contact us. One of the best places to
| Official Plugin | Description | Status |
| ----------------------------------------------------- | ----------------------------------------- | ------ |
| [@affine/bookmark-plugin](plugins/bookmark) | A block for bookmarking a website | ✅ |
| [@affine/copilot-plugin](plugins/copilot) | AI Copilot that help you document writing | 🚧 |
| [@affine/image-preview-plugin](plugins/image-preview) | Component for previewing an image | ✅ |
| [@affine/outline](plugins/outline) | Outline for your document | ✅ |

View File

@ -4,14 +4,8 @@ import type { SerializedBlock } from '@blocksuite/blocks';
import type { BaseBlockModel } from '@blocksuite/store';
import type { Page } from '@blocksuite/store';
import type { VEditor } from '@blocksuite/virgo';
import type { ReactElement } from 'react';
import { StrictMode } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
export type BookMarkProps = {
page: Page;
};
type ShortcutMap = {
[key: string]: (e: KeyboardEvent, page: Page) => void;
};
@ -121,7 +115,11 @@ const shouldShowBookmarkMenu = (pastedBlocks: Record<string, unknown>[]) => {
return !!firstBlock.text[0].attributes?.link;
};
const BookMarkUI = ({ page }: BookMarkProps) => {
export type BookmarkProps = {
page: Page;
};
export const Bookmark = ({ page }: BookmarkProps) => {
const [anchor, setAnchor] = useState<Range | null>(null);
const [selectedOption, setSelectedOption] = useState<string>(
menuOptions[0].id
@ -244,15 +242,3 @@ const BookMarkUI = ({ page }: BookMarkProps) => {
</MuiClickAwayListener>
) : null;
};
type AppProps = {
page: Page;
};
export const App = (props: AppProps): ReactElement => {
return (
<StrictMode>
<BookMarkUI page={props.page} />
</StrictMode>
);
};

View File

@ -31,6 +31,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import { pageSettingFamily } from '../atoms';
import { fontStyleOptions, useAppSetting } from '../atoms/settings';
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
import { Bookmark } from './bookmark';
import * as styles from './page-detail-editor.css';
import { editorContainer, pluginContainer } from './page-detail-editor.css';
import { TrashButtonGroup } from './pure/trash-button-group';
@ -139,6 +140,7 @@ const EditorWrapper = memo(function EditorWrapper({
)}
/>
{meta.trash && <TrashButtonGroup />}
<Bookmark page={page} />
</>
);
});

View File

@ -26,7 +26,6 @@
"main": "./dist/main.js",
"devDependencies": {
"@affine-test/kit": "workspace:*",
"@affine/bookmark-plugin": "workspace:*",
"@affine/copilot-plugin": "workspace:*",
"@affine/env": "workspace:*",
"@affine/hello-world-plugin": "workspace:*",

View File

@ -32,7 +32,6 @@ export const config = () => {
resolve(electronDir, './src/main/index.ts'),
resolve(electronDir, './src/preload/index.ts'),
resolve(electronDir, './src/helper/index.ts'),
resolve(electronDir, './src/worker/plugin.ts'),
],
entryNames: '[dir]',
outdir: resolve(electronDir, './dist'),

View File

@ -64,7 +64,6 @@ export const registerHandlers = () => {
ipcMain.handle(chan, async (e, ...args) => {
const start = performance.now();
try {
// @ts-expect-error - TODO: fix this
const result = await handler(e, ...args);
logger.info(
'[ipc-api]',

View File

@ -9,7 +9,6 @@ import { registerHandlers } from './handlers';
import { ensureHelperProcess } from './helper-process';
import { logger } from './logger';
import { restoreOrCreateWindow } from './main-window';
import { registerPlugin } from './plugin';
import { registerProtocol } from './protocol';
import { registerUpdater } from './updater';
@ -59,7 +58,6 @@ setupDeepLink(app);
app
.whenReady()
.then(registerProtocol)
.then(registerPlugin)
.then(registerHandlers)
.then(registerEvents)
.then(ensureHelperProcess)

View File

@ -1,57 +0,0 @@
import { join, resolve } from 'node:path';
import { Worker } from 'node:worker_threads';
import { logger, pluginLogger } from '@affine/electron/main/logger';
import { AsyncCall } from 'async-call-rpc';
import { ipcMain } from 'electron';
import { readFile } from 'fs/promises';
import { MessageEventChannel } from '../shared/utils';
const builtInPlugins = ['bookmark'];
declare global {
// fixme(himself65):
// remove this when bookmark block plugin is migrated to plugin-infra
// eslint-disable-next-line no-var
var asyncCall: Record<string, (...args: any) => PromiseLike<any>>;
}
export async function registerPlugin() {
logger.info('import plugin manager');
const asyncCall = AsyncCall<
Record<string, (...args: any) => PromiseLike<any>>
>(
{
log: (...args: any[]) => {
pluginLogger.log(...args);
},
},
{
channel: new MessageEventChannel(
new Worker(resolve(__dirname, './worker.js'), {})
),
}
);
globalThis.asyncCall = asyncCall;
await Promise.all(
builtInPlugins.map(async plugin => {
const pluginPackageJsonPath = join(
process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'),
`./${plugin}/package.json`
);
logger.info(`${plugin} plugin path:`, pluginPackageJsonPath);
const packageJson = JSON.parse(
await readFile(pluginPackageJsonPath, 'utf-8')
);
console.log('packageJson', packageJson);
const serverCommand: string[] = packageJson.affinePlugin.serverCommand;
serverCommand.forEach(command => {
ipcMain.handle(command, async (_, ...args) => {
logger.info(`plugin ${plugin} called`);
return asyncCall[command](...args);
});
});
})
);
}

View File

@ -1,4 +1,5 @@
import { app, BrowserWindow, nativeTheme } from 'electron';
import { getLinkPreview } from 'link-preview-js';
import { isMacOS } from '../../shared/utils';
import type { NamespaceHandlers } from '../type';
@ -43,12 +44,30 @@ export const uiHandlers = {
getGoogleOauthCode: async () => {
return getGoogleOauthCode();
},
/**
* @deprecated Remove this when bookmark block plugin is migrated to plugin-infra
*/
getBookmarkDataByLink: async (_, link: string) => {
return globalThis.asyncCall[
'com.blocksuite.bookmark-block.get-bookmark-data-by-link'
](link);
const previewData = (await getLinkPreview(link, {
timeout: 6000,
headers: {
'user-agent': 'googlebot',
},
followRedirects: 'follow',
}).catch(() => {
return {
title: '',
siteName: '',
description: '',
images: [],
videos: [],
contentType: `text/html`,
favicons: [],
};
})) as any;
return {
title: previewData.title,
description: previewData.description,
icon: previewData.favicons[0],
image: previewData.images[0],
};
},
} satisfies NamespaceHandlers;

View File

@ -1,52 +0,0 @@
import { join, resolve } from 'node:path';
import { parentPort } from 'node:worker_threads';
import type { ServerContext } from '@affine/sdk/server';
import { AsyncCall } from 'async-call-rpc';
import { MessageEventChannel } from '../shared/utils';
if (!parentPort) {
throw new Error('parentPort is null');
}
const commandProxy: Record<string, (...args: any[]) => Promise<any>> = {};
parentPort.start();
const mainThread = AsyncCall<{
log: (...args: any[]) => Promise<void>;
}>(commandProxy, {
channel: new MessageEventChannel(parentPort),
});
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.log = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.error = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.info = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.debug = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
globalThis.console.warn = mainThread.log;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const bookmarkPluginModule = require(
join(
process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'),
'./bookmark/index.cjs'
)
);
const serverContext: ServerContext = {
registerCommand: (command, fn) => {
console.log('register command', command);
commandProxy[command] = fn;
},
unregisterCommand: command => {
console.log('unregister command', command);
delete commandProxy[command];
},
};
bookmarkPluginModule.entry(serverContext);

View File

@ -42,7 +42,6 @@ export const pluginPackageJson = atom<
>([]);
export const enabledPluginAtom = atomWithStorage('affine-enabled-plugin', [
'@affine/bookmark-plugin',
'@affine/image-preview-plugin',
'@affine/outline-plugin',
]);

View File

@ -15,9 +15,7 @@ export const packageJsonInputSchema = z.object({
release: z.union([z.boolean(), z.enum(['development'])]),
entry: z.object({
core: z.string(),
server: z.string().optional(),
}),
serverCommand: z.array(z.string()).optional(),
}),
});
@ -31,7 +29,6 @@ export const packageJsonOutputSchema = z.object({
core: z.string(),
}),
assets: z.array(z.string()),
serverCommand: z.array(z.string()).optional(),
}),
});

View File

@ -64,9 +64,6 @@ const external = [
// css
/^@vanilla-extract/,
// remove this when bookmark plugin is ready
'link-preview-js',
];
const allPluginDir = path.resolve(projectRoot, 'plugins');
@ -103,15 +100,6 @@ const outDir = path.resolve(projectRoot, 'apps', 'core', 'public', 'plugins');
const coreOutDir = path.resolve(outDir, plugin);
const serverOutDir = path.resolve(
projectRoot,
'apps',
'electron',
'dist',
'plugins',
plugin
);
const coreEntry = path.resolve(pluginDir, json.affinePlugin.entry.core);
const generatePackageJson: PluginOption = {
@ -127,7 +115,6 @@ const generatePackageJson: PluginOption = {
core: 'index.js',
},
assets: [...metadata.assets],
serverCommand: json.affinePlugin.serverCommand,
},
} satisfies z.infer<typeof packageJsonOutputSchema>;
packageJsonOutputSchema.parse(packageJson);
@ -191,25 +178,3 @@ await build({
generatePackageJson,
],
});
// step 2: generate server bundle
if (json.affinePlugin.entry.server) {
const serverEntry = path.resolve(pluginDir, json.affinePlugin.entry.server);
await build({
build: {
watch: isWatch ? {} : undefined,
minify: false,
outDir: serverOutDir,
emptyOutDir: true,
lib: {
entry: serverEntry,
fileName: 'index',
formats: ['cjs'],
},
rollupOptions: {
external,
},
},
plugins: [generatePackageJson],
});
}

View File

@ -1,5 +0,0 @@
# AFFiNE Bookmark
> Bookmark plugin
![preview](assets/preview.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,30 +0,0 @@
{
"name": "@affine/bookmark-plugin",
"type": "module",
"version": "0.9.0-canary.13",
"description": "Bookmark Plugin",
"affinePlugin": {
"release": true,
"entry": {
"core": "./src/index.ts",
"server": "./src/server.ts"
},
"serverCommand": [
"com.blocksuite.bookmark-block.get-bookmark-data-by-link"
]
},
"scripts": {
"dev": "af dev",
"build": "af build"
},
"dependencies": {
"@affine/component": "workspace:*",
"@affine/sdk": "workspace:*",
"@blocksuite/icons": "^2.1.33",
"foxact": "^0.2.20",
"link-preview-js": "^3.0.5"
},
"devDependencies": {
"@affine/plugin-cli": "workspace:*"
}
}

View File

@ -1,26 +0,0 @@
{
"name": "@affine/bookmark-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"namedInputs": {
"default": [
"{projectRoot}/**/*",
"{workspaceRoot}/packages/plugin-cli/**/*",
"sharedGlobals"
]
},
"targets": {
"build": {
"executor": "nx:run-script",
"options": {
"script": "build"
},
"dependsOn": ["^build"],
"inputs": ["default"],
"outputs": [
"{workspaceRoot}/apps/core/public/plugins/bookmark",
"{workspaceRoot}/apps/electron/dist/plugins/bookmark"
]
}
},
"tags": ["plugin"]
}

View File

@ -1,21 +0,0 @@
import type { PluginContext } from '@affine/sdk/entry';
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './app';
export const entry = (context: PluginContext) => {
console.log('register');
context.register('editor', (div, editor) => {
const root = createRoot(div);
root.render(createElement(App, { page: editor.page }));
return () => {
root.unmount();
};
});
return () => {
console.log('unregister');
};
};

View File

@ -1,65 +0,0 @@
import type { ServerContext } from '@affine/sdk/server';
import { getLinkPreview } from 'link-preview-js';
type MetaData = {
title?: string;
description?: string;
icon?: string;
image?: string;
[x: string]: string | string[] | undefined;
};
export interface PreviewType {
url: string;
title: string;
siteName: string | undefined;
description: string | undefined;
mediaType: string;
contentType: string | undefined;
images: string[];
videos: {
url: string | undefined;
secureUrl: string | null | undefined;
type: string | null | undefined;
width: string | undefined;
height: string | undefined;
}[];
favicons: string[];
}
export const entry = (context: ServerContext) => {
context.registerCommand(
'com.blocksuite.bookmark-block.get-bookmark-data-by-link',
async (url: string): Promise<MetaData> => {
const previewData = (await getLinkPreview(url, {
timeout: 6000,
headers: {
'user-agent': 'googlebot',
},
followRedirects: 'follow',
}).catch(() => {
return {
title: '',
siteName: '',
description: '',
images: [],
videos: [],
contentType: `text/html`,
favicons: [],
};
})) as PreviewType;
return {
title: previewData.title,
description: previewData.description,
icon: previewData.favicons[0],
image: previewData.images[0],
};
}
);
return () => {
context.unregisterCommand(
'com.blocksuite.bookmark-block.get-bookmark-data-by-link'
);
};
};

View File

@ -1,17 +0,0 @@
{
"extends": "../../tsconfig.json",
"include": ["./src"],
"compilerOptions": {
"noEmit": false,
"outDir": "lib",
"jsx": "preserve"
},
"references": [
{
"path": "../../packages/sdk"
},
{
"path": "../../packages/component"
}
]
}

View File

@ -22,7 +22,6 @@ test('plugin should exist', async ({ page }) => {
);
});
const plugins = [
'@affine/bookmark-plugin',
'@affine/copilot-plugin',
'@affine/hello-world-plugin',
'@affine/image-preview-plugin',

View File

@ -119,9 +119,6 @@
{
"path": "./packages/sdk"
},
{
"path": "./plugins/bookmark"
},
{
"path": "./plugins/copilot"
},

View File

@ -146,19 +146,6 @@ __metadata:
languageName: unknown
linkType: soft
"@affine/bookmark-plugin@workspace:*, @affine/bookmark-plugin@workspace:plugins/bookmark":
version: 0.0.0-use.local
resolution: "@affine/bookmark-plugin@workspace:plugins/bookmark"
dependencies:
"@affine/component": "workspace:*"
"@affine/plugin-cli": "workspace:*"
"@affine/sdk": "workspace:*"
"@blocksuite/icons": ^2.1.33
foxact: ^0.2.20
link-preview-js: ^3.0.5
languageName: unknown
linkType: soft
"@affine/cli@workspace:*, @affine/cli@workspace:packages/cli":
version: 0.0.0-use.local
resolution: "@affine/cli@workspace:packages/cli"
@ -368,7 +355,6 @@ __metadata:
resolution: "@affine/electron@workspace:apps/electron"
dependencies:
"@affine-test/kit": "workspace:*"
"@affine/bookmark-plugin": "workspace:*"
"@affine/copilot-plugin": "workspace:*"
"@affine/env": "workspace:*"
"@affine/hello-world-plugin": "workspace:*"