Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enhance markdown preview for backlinks #8956

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export const sectionContent = style({
display: 'flex',
flexDirection: 'column',
gap: 4,
marginTop: 4,
selectors: {
'&[hidden]': {
display: 'none',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
import {
BlockStdScope,
type EditorHost,
type ExtensionType,
ShadowlessElement,
} from '@blocksuite/affine/block-std';
import type {
AffineAIPanelState,
AffineAIPanelWidgetConfig,
Expand All @@ -10,8 +15,14 @@ import {
ParagraphBlockComponent,
} from '@blocksuite/affine/blocks';
import { WithDisposable } from '@blocksuite/affine/global/utils';
import { BlockViewType, type Doc, type Query } from '@blocksuite/affine/store';
import { css, html, LitElement, nothing, type PropertyValues } from 'lit';
import {
BlockViewType,
type Doc,
type JobMiddleware,
type Query,
type Schema,
} from '@blocksuite/affine/store';
import { css, html, nothing, type PropertyValues } from 'lit';
import { property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { keyed } from 'lit/directives/keyed.js';
Expand Down Expand Up @@ -70,9 +81,12 @@ const customHeadingStyles = css`
export type TextRendererOptions = {
maxHeight?: number;
customHeading?: boolean;
extensions?: ExtensionType[];
additionalMiddlewares?: JobMiddleware[];
};

export class TextRenderer extends WithDisposable(LitElement) {
// todo: refactor it for more general purpose usage instead of AI only?
export class TextRenderer extends WithDisposable(ShadowlessElement) {
static override styles = css`
.ai-answer-text-editor.affine-page-viewport {
background: transparent;
Expand Down Expand Up @@ -177,8 +191,9 @@ export class TextRenderer extends WithDisposable(LitElement) {
if (this._answers.length > 0) {
const latestAnswer = this._answers.pop();
this._answers = [];
if (latestAnswer) {
markDownToDoc(this.host, latestAnswer)
const schema = this.schema ?? this.host?.std.doc.collection.schema;
if (latestAnswer && schema) {
markDownToDoc(schema, latestAnswer, this.options.additionalMiddlewares)
.then(doc => {
this._doc = doc.blockCollection.getDoc({
query: this._query,
Expand Down Expand Up @@ -245,7 +260,7 @@ export class TextRenderer extends WithDisposable(LitElement) {
html`<div class="ai-answer-text-editor affine-page-viewport">
${new BlockStdScope({
doc: this._doc,
extensions: CustomPageEditorBlockSpecs,
extensions: this.options.extensions ?? CustomPageEditorBlockSpecs,
}).render()}
</div>`
)}
Expand Down Expand Up @@ -277,7 +292,10 @@ export class TextRenderer extends WithDisposable(LitElement) {
accessor answer!: string;

@property({ attribute: false })
accessor host!: EditorHost;
accessor host: EditorHost | null = null;

@property({ attribute: false })
accessor schema: Schema | null = null;

@property({ attribute: false })
accessor options!: TextRendererOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
PlainTextAdapter,
titleMiddleware,
} from '@blocksuite/affine/blocks';
import type { JobMiddleware, Schema } from '@blocksuite/affine/store';
import { DocCollection, Job } from '@blocksuite/affine/store';
import { assertExists } from '@blocksuite/global/utils';
import type {
Expand Down Expand Up @@ -184,16 +185,23 @@ export async function replaceFromMarkdown(
await job.snapshotToSlice(snapshot, host.doc, parent, index);
}

export async function markDownToDoc(host: EditorHost, answer: string) {
const schema = host.std.doc.collection.schema;
export async function markDownToDoc(
schema: Schema,
answer: string,
additionalMiddlewares?: JobMiddleware[]
) {
// Should not create a new doc in the original collection
const collection = new DocCollection({
schema,
});
collection.meta.initialize();
const middlewares = [defaultImageProxyMiddleware];
if (additionalMiddlewares) {
middlewares.push(...additionalMiddlewares);
}
const job = new Job({
collection,
middlewares: [defaultImageProxyMiddleware],
middlewares,
});
const mdAdapter = new MarkdownAdapter(job);
const doc = await mdAdapter.toDoc({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const copyTextAnswer = async (panel: AffineAIPanelWidget) => {
};

export const copyText = async (host: EditorHost, text: string) => {
const previewDoc = await markDownToDoc(host, text);
const previewDoc = await markDownToDoc(host.std.doc.schema, text);
const models = previewDoc
.getBlocksByFlavour('affine:note')
.map(b => b.model)
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/core/src/blocksuite/presets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './_common/components/text-renderer';
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import type { DocMode } from '@blocksuite/affine/blocks';
import type { DocCollection } from '@blocksuite/affine/store';
import { LiveData, useLiveData, useService } from '@toeverything/infra';
import {
DocsService,
LiveData,
useLiveData,
useService,
} from '@toeverything/infra';
import clsx from 'clsx';
import { nanoid } from 'nanoid';
import {
Expand Down Expand Up @@ -36,6 +41,7 @@ function AffinePageReferenceInner({
Icon: UserIcon,
}: AffinePageReferenceProps) {
const docDisplayMetaService = useService(DocDisplayMetaService);
const docsService = useService(DocsService);
const i18n = useI18n();

let linkWithMode: DocMode | null = null;
Expand All @@ -62,15 +68,19 @@ function AffinePageReferenceInner({
);
})
);
const title = useLiveData(
const notFound = !useLiveData(docsService.list.doc$(pageId));

let title = useLiveData(
docDisplayMetaService.title$(pageId, { reference: true })
);

title = notFound ? i18n.t('com.affine.notFoundPage.title') : title;

return (
<>
<span className={notFound ? styles.notFound : ''}>
<Icon className={styles.pageReferenceIcon} />
<span className="affine-reference-title">{i18n.t(title)}</span>
</>
</span>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { style } from '@vanilla-extract/css';
import { cssVarV2 } from '@toeverything/theme/v2';
import { globalStyle, style } from '@vanilla-extract/css';

export const pageReferenceIcon = style({
verticalAlign: 'middle',
fontSize: '1.1em',
transform: 'translate(2px, -1px)',
color: cssVarV2('icon/primary'),
});

export const pageReferenceLink = style({
Expand All @@ -12,3 +14,13 @@ export const pageReferenceLink = style({
wordBreak: 'break-word',
hyphens: 'auto',
});

export const notFound = style({
color: cssVarV2('text/secondary'),
textDecoration: 'line-through',
});

globalStyle('affine-reference .affine-reference', {
color: 'inherit !important',
textDecoration: 'none !important',
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
import { cssVarV2 } from '@toeverything/theme/v2';
import { globalStyle, style } from '@vanilla-extract/css';

export const container = style({
width: '100%',
Expand Down Expand Up @@ -49,7 +50,6 @@ export const title = style({
});

export const showButton = style({
width: '56px',
height: '28px',
borderRadius: '8px',
border: '1px solid ' + cssVar('--affine-border-color'),
Expand All @@ -74,9 +74,45 @@ export const linksTitles = style({

export const link = style({
width: '100%',
height: '32px',
height: '30px',
display: 'flex',
alignItems: 'center',
gap: '4px',
whiteSpace: 'nowrap',
});

globalStyle(`${link} .affine-reference-title`, {
borderBottom: 'none',
});

export const linkPreviewContainer = style({
display: 'flex',
flexDirection: 'column',
gap: '8px',
});

export const linkPreview = style({
border: `1px solid ${cssVarV2('layer/insideBorder/border')}`,
borderRadius: '8px',
padding: '8px',
color: cssVarV2('text/primary'),
':hover': {
backgroundColor: cssVarV2('layer/background/hoverOverlay'),
},
});

export const linkPreviewRenderer = style({
cursor: 'pointer',
});

export const collapsedIcon = style({
transition: 'all 0.2s ease-in-out',
color: cssVarV2('icon/primary'),
fontSize: 20,
selectors: {
'&[data-collapsed="true"]': {
transform: 'rotate(90deg)',
color: cssVarV2('icon/secondary'),
},
},
});
Loading
Loading