mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-09-20 07:57:29 +03:00
fix: the image lost after exporting (#3150)
Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
parent
3968deb6d4
commit
4f88774999
21
.github/workflows/workers.yml
vendored
Normal file
21
.github/workflows/workers.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Deploy Cloudflare Worker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- packages/workers/**
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
name: Deploy
|
||||
environment: production
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
workingDirectory: 'packages/workers'
|
@ -24,6 +24,7 @@ const buildPreset = {
|
||||
enableBroadcastChannelProvider: true,
|
||||
enableDebugPage: true,
|
||||
changelogUrl: 'https://affine.pro/blog/whats-new-affine-0630',
|
||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||
enablePreloading: true,
|
||||
enableNewSettingModal: true,
|
||||
enableNewSettingUnstableApi: false,
|
||||
@ -41,6 +42,7 @@ const buildPreset = {
|
||||
enableBroadcastChannelProvider: true,
|
||||
enableDebugPage: true,
|
||||
changelogUrl: 'https://affine.pro/blog/whats-new-affine-0630',
|
||||
imageProxyUrl: 'https://workers.toeverything.workers.dev/proxy/image',
|
||||
enablePreloading: true,
|
||||
enableNewSettingModal: true,
|
||||
enableNewSettingUnstableApi: false,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { PageBlockModel } from '@blocksuite/blocks';
|
||||
import { ContentParser } from '@blocksuite/blocks/content-parser';
|
||||
import {
|
||||
ArrowRightSmallIcon,
|
||||
ExportIcon,
|
||||
@ -11,16 +10,16 @@ import {
|
||||
ExportToPngIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { Menu, MenuItem } from '../../..';
|
||||
import { getContentParser } from './get-content-parser';
|
||||
import type { CommonMenuItemProps } from './types';
|
||||
|
||||
export const ExportToPdfMenuItem = ({
|
||||
onSelect,
|
||||
}: CommonMenuItemProps<{ type: 'pdf' }>) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const contentParserRef = useRef<ContentParser>();
|
||||
const { currentEditor } = globalThis;
|
||||
const setPushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
@ -53,9 +52,7 @@ export const ExportToPdfMenuItem = ({
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const contentParser =
|
||||
contentParserRef.current ??
|
||||
(contentParserRef.current = new ContentParser(currentEditor.page));
|
||||
const contentParser = getContentParser(currentEditor.page);
|
||||
|
||||
contentParser
|
||||
.exportPdf()
|
||||
@ -95,17 +92,14 @@ export const ExportToHtmlMenuItem = ({
|
||||
onSelect,
|
||||
}: CommonMenuItemProps<{ type: 'html' }>) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const contentParserRef = useRef<ContentParser>();
|
||||
const { currentEditor } = globalThis;
|
||||
const setPushNotification = useSetAtom(pushNotificationAtom);
|
||||
const onClickExportHtml = useCallback(() => {
|
||||
if (!currentEditor) {
|
||||
return;
|
||||
}
|
||||
if (!contentParserRef.current) {
|
||||
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||
}
|
||||
contentParserRef.current
|
||||
const contentParser = getContentParser(currentEditor.page);
|
||||
contentParser
|
||||
.exportHtml()
|
||||
.then(() => {
|
||||
onSelect?.({ type: 'html' });
|
||||
@ -138,7 +132,6 @@ export const ExportToPngMenuItem = ({
|
||||
onSelect,
|
||||
}: CommonMenuItemProps<{ type: 'png' }>) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const contentParserRef = useRef<ContentParser>();
|
||||
const { currentEditor } = globalThis;
|
||||
const setPushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
@ -146,9 +139,7 @@ export const ExportToPngMenuItem = ({
|
||||
if (!currentEditor) {
|
||||
return;
|
||||
}
|
||||
const contentParser =
|
||||
contentParserRef.current ??
|
||||
(contentParserRef.current = new ContentParser(currentEditor.page));
|
||||
const contentParser = getContentParser(currentEditor.page);
|
||||
|
||||
contentParser
|
||||
.exportPng()
|
||||
@ -189,17 +180,14 @@ export const ExportToMarkdownMenuItem = ({
|
||||
onSelect,
|
||||
}: CommonMenuItemProps<{ type: 'markdown' }>) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const contentParserRef = useRef<ContentParser>();
|
||||
const { currentEditor } = globalThis;
|
||||
const setPushNotification = useSetAtom(pushNotificationAtom);
|
||||
const onClickExportMarkdown = useCallback(() => {
|
||||
if (!currentEditor) {
|
||||
return;
|
||||
}
|
||||
if (!contentParserRef.current) {
|
||||
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||
}
|
||||
contentParserRef.current
|
||||
const contentParser = getContentParser(currentEditor.page);
|
||||
contentParser
|
||||
.exportMarkdown()
|
||||
.then(() => {
|
||||
onSelect?.({ type: 'markdown' });
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { ContentParser } from '@blocksuite/blocks/content-parser';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
|
||||
const contentParserWeakMap = new WeakMap<Page, ContentParser>();
|
||||
|
||||
export function getContentParser(page: Page) {
|
||||
if (!contentParserWeakMap.has(page)) {
|
||||
contentParserWeakMap.set(
|
||||
page,
|
||||
new ContentParser(page, {
|
||||
imageProxyEndpoint: !environment.isDesktop
|
||||
? runtimeConfig.imageProxyUrl
|
||||
: undefined,
|
||||
})
|
||||
);
|
||||
}
|
||||
return contentParserWeakMap.get(page) as ContentParser;
|
||||
}
|
2
packages/env/src/global.ts
vendored
2
packages/env/src/global.ts
vendored
@ -63,6 +63,8 @@ export const buildFlagsSchema = z.object({
|
||||
enableBroadcastChannelProvider: z.boolean(),
|
||||
enableDebugPage: z.boolean(),
|
||||
changelogUrl: z.string(),
|
||||
// see: packages/workers
|
||||
imageProxyUrl: z.string(),
|
||||
enablePreloading: z.boolean(),
|
||||
enableNewSettingModal: z.boolean(),
|
||||
enableNewSettingUnstableApi: z.boolean(),
|
||||
|
63
packages/workers/src/index.ts
Normal file
63
packages/workers/src/index.ts
Normal file
@ -0,0 +1,63 @@
|
||||
const ALLOW_ORIGIN = ['https://affine.pro', 'https://affine.fail'];
|
||||
|
||||
function isString(s: any): boolean {
|
||||
return typeof s === 'string' || s instanceof String;
|
||||
}
|
||||
|
||||
function isOriginAllowed(
|
||||
origin: string,
|
||||
allowedOrigin: string | RegExp | Array<string | RegExp>
|
||||
): boolean {
|
||||
if (Array.isArray(allowedOrigin)) {
|
||||
for (let i = 0; i < allowedOrigin.length; ++i) {
|
||||
if (isOriginAllowed(origin, allowedOrigin[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (isString(allowedOrigin)) {
|
||||
return origin === allowedOrigin;
|
||||
} else if (allowedOrigin instanceof RegExp) {
|
||||
return allowedOrigin.test(origin);
|
||||
} else {
|
||||
return !!allowedOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
async function proxyImage(request: Request): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
const imageURL = url.searchParams.get('url');
|
||||
|
||||
if (!imageURL) {
|
||||
return new Response('Missing "url" parameter', { status: 400 });
|
||||
}
|
||||
|
||||
const imageRequest = new Request(imageURL, {
|
||||
method: 'GET',
|
||||
headers: request.headers,
|
||||
});
|
||||
|
||||
const response = await fetch(imageRequest);
|
||||
const modifiedResponse = new Response(response.body);
|
||||
modifiedResponse.headers.set('Access-Control-Allow-Origin', '*');
|
||||
modifiedResponse.headers.set('Access-Control-Allow-Methods', 'GET');
|
||||
|
||||
return modifiedResponse;
|
||||
}
|
||||
|
||||
const handler = {
|
||||
async fetch(request: Request) {
|
||||
if (!isOriginAllowed(request.headers.get('Origin') || '', ALLOW_ORIGIN)) {
|
||||
return new Response('unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
const url = new URL(request.url);
|
||||
if (url.pathname.startsWith('/proxy/image')) {
|
||||
return await proxyImage(request);
|
||||
}
|
||||
|
||||
return new Response('not found', { status: 404 });
|
||||
},
|
||||
};
|
||||
|
||||
export default handler;
|
3
packages/workers/wrangler.toml
Normal file
3
packages/workers/wrangler.toml
Normal file
@ -0,0 +1,3 @@
|
||||
name = "workers"
|
||||
main = "./src/index.ts"
|
||||
compatibility_date = "2023-07-11"
|
Loading…
Reference in New Issue
Block a user