Skip to content

Commit

Permalink
feat: enhance markdown preview for backlinks (#8956)
Browse files Browse the repository at this point in the history
fix AF-1770
fix AF-1771

---

fix: doc link middlewares
feat: markdown renderer
feat: allow multiple backlink for a single doc
feat: showing correct doc ref link
feat: trim long para & ident lists
feat: list indentition fix
feat: database/latext handling
feat: other block types handling
fix: lint
  • Loading branch information
pengx17 committed Dec 2, 2024
1 parent b8467a9 commit 31bab25
Show file tree
Hide file tree
Showing 19 changed files with 940 additions and 184 deletions.
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

0 comments on commit 31bab25

Please sign in to comment.