Commit Graph
100 Commits
Author SHA1 Message Date
donteatfriedrice 1bdccdbd57 feat(editor): track citation events (#12664)
Closes: [BS-3551](https://linear.app/affine-design/issue/BS-3551/citation埋点)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enhanced citation tracking across attachments, bookmarks, embedded documents, paragraphs, footnotes, rename modals, and toolbars for actions like editing, deleting, expanding, and hovering on citations.
  - Introduced a centralized citation service to unify citation detection and telemetry event management.
- **Chores**
  - Updated service exports and telemetry modules to include the new citation service and citation-related event types.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-06-05 03:09:24 +00:00
donteatfriedrice 053efb61f0 fix(editor): should set event dispatcher active as false when document is hidden (#12559)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - The application now automatically becomes inactive when the document is hidden, improving resource management and responsiveness to visibility changes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-06-05 02:28:32 +00:00
donteatfriedrice bc67766bb9 fix(editor): cleanup transformer middleware slot subscriptions (#12630)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved resource management by introducing explicit cleanup for various middleware components, ensuring that resources are properly released when no longer needed.

- **Refactor**
  - Updated middleware logic to support cleanup functions, enhancing the stability and performance of the application by preventing potential memory leaks.

- **Chores**
  - Enhanced lifecycle management in core systems to automatically dispose of resources when appropriate.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-29 08:33:30 +00:00
donteatfriedrice af3c002022 chore: remove link preview cache feature flag (#12568) 2025-05-27 10:07:33 +00:00
donteatfriedrice 69c7767003 chore: remove citation feature flag (#12567)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Footnote definitions and "Sources" headings are now always included in notes, without requiring a feature flag.
  - Enhanced footnote-related content with additional citation-style blocks such as bookmarks, embedded documents, and attachments.

- **Chores**
  - Removed the citation feature flag and its related configuration, logic, and translations from the application.

- **Documentation**
  - Updated localization files to remove entries related to the citation experimental feature.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-27 10:07:32 +00:00
donteatfriedrice a828c74f87 feat(editor): add experimental feature adapter panel to AFFiNE canary (#12489)
Closes: [BS-2539](https://linear.app/affine-design/issue/BS-2539/为-affine-添加-ef,并且支持在-affine-预览对应的功能)

> [!warning]
> This feature is only available in the canary build and is intended for debugging purposes.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced an "Adapter Panel" feature with a new sidebar tab for previewing document content in multiple formats (Markdown, PlainText, HTML, Snapshot), controllable via a feature flag.
  - Added a fully integrated adapter panel component with reactive UI elements for selecting adapters, toggling HTML preview modes, and updating content.
  - Provided a customizable adapter panel for both main app and playground environments, supporting content transformation pipelines and export previews.
  - Enabled seamless toggling and live updating of adapter panel content through intuitive menus and controls.

- **Localization**
  - Added English translations and descriptive settings for the Adapter Panel feature.

- **Chores**
  - Added new package and workspace dependencies along with TypeScript project references to support the Adapter Panel modules and components.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-23 14:08:12 +00:00
donteatfriedrice f99b143bf9 fix(editor): handle footnote reference immediately follow URLs when importing markdown (#12449)
Closes: [BS-3525](https://linear.app/affine-design/issue/BS-3525/markdown-adapter-紧跟着链接的-footnote-reference-会被识别成链接的一部分)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved handling of footnote references that immediately follow URLs in markdown, ensuring correct spacing and parsing.
- **Bug Fixes**
  - Footnote references after URLs are now parsed correctly, preventing formatting issues.
- **Tests**
  - Added comprehensive test suites to verify footnote reference preprocessing and markdown conversion.
- **Chores**
  - Introduced Vitest as a development dependency and added a dedicated test configuration for the footnote module.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-23 03:24:23 +00:00
donteatfriedrice a3b8aaff61 fix(editor): toggle switch style (#12436)
Closes: [BS-2852](https://linear.app/affine-design/issue/BS-2852/ui-bug:-toggle-的组件样式不一样了)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Style**
  - Updated toggle switch appearance with refined colors and spacing for a more polished look.

- **Bug Fixes**
  - Improved toggle switch functionality in settings menus to ensure correct state display and interaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-22 06:13:25 +00:00
donteatfriedrice 20e93543e2 fix(editor): subscribe docLinkClicked event for text renderer (#12406)
Closes: [BS-3520](https://linear.app/affine-design/issue/BS-3520/chat-panel-doc-citation-点击没有响应)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enhanced citation cards to support double-click actions for improved interaction.
  - Added the ability to open a preview view when clicking document links within rendered text content.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-21 07:34:28 +00:00
donteatfriedrice bfbbc2342e fix(editor): wrap inline elements in a p tag to avoid treated as paragraph block when importing html (#12389) 2025-05-21 02:45:17 +00:00
donteatfriedrice 1a070367f3 fix(editor): handle html content copied from google docs (#12383)
Closes: [BS-3508](https://linear.app/affine-design/issue/BS-3508/google-docs复制内容到affine时自动加粗问题)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Improved detection of bold, italic, underline, and strike-through formatting in imported HTML, supporting both tags and inline CSS styles.
  - Enhanced handling of inline elements containing block-level children to ensure correct formatting and structure during HTML import.
  - Introduced a plugin that converts inline elements with block-level children into block elements, preserving original tag information.
- **Bug Fixes**
  - Resolved issues where block-level elements nested inside inline tags could cause incorrect formatting or structure.
- **Tests**
  - Added comprehensive test coverage for HTML formatting conversions and plugin behavior to ensure accuracy and reliability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-21 02:45:17 +00:00
donteatfriedrice 76a8bf2834 fix(editor): flaky import notion html image unit test (#12354)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Chores**
  - Added a new development dependency to improve testing capabilities.

- **Tests**
  - Refactored image handling tests to use enhanced HTTP request mocking, improving test reliability and maintainability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-19 04:53:56 +00:00
donteatfriedrice b1594fcf6f feat(editor): provide callout markdown export options middleware (#12283)
Closes: [BS-3491](https://linear.app/affine-design/issue/BS-3491/支持-callout-导出成-vitepress-文档站支持的-markdown-格式)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added support for exporting callout blocks in both GFM and Admonition markdown styles, including configurable admonition types and custom titles.
  - Introduced middleware to customize callout export options for markdown serialization.

- **Tests**
  - Enhanced test coverage for callout markdown export, including scenarios with and without export middleware for different styles and content structures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-15 01:03:38 +00:00
donteatfriedrice d56d46d8d6 fix(editor): should preserve format in <p> when importing html (#12275)
Closes: [BS-3485](https://linear.app/affine-design/issue/BS-3485/粘贴-html-格式的内容时,紧邻着-bold-text-的普通文本会丢失空格)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Bug Fixes**
  - Improved handling of spaces and whitespace in paragraphs when converting HTML with inline formatting, ensuring spaces are preserved as in the original content.

- **Tests**
  - Added a new test to verify that spaces are correctly preserved in paragraphs containing bold and italic formatting during HTML conversion.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-15 00:50:10 +00:00
donteatfriedrice 26ece014f1 fix(editor): support relative image reference path when importing zip with images (#12264)
Closes: [BS-3385](https://linear.app/affine-design/issue/BS-3385/markdown类型的导入,支持media文件和md文件不在同目录的情况)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added utility functions to resolve and normalize image file paths in markdown and HTML imports.
  - Introduced middleware to provide full file path context during file import and transformation.
  - Added new types for improved asset and file management in zip imports.

- **Refactor**
  - Centralized and simplified image processing logic across HTML, Markdown, and Notion HTML adapters for improved maintainability.
  - Enhanced type safety and clarity in file and asset handling during zip imports.

- **Tests**
  - Added comprehensive tests for image file path resolution utility.

- **Documentation**
  - Improved inline code comments explaining file path resolution logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-14 02:30:30 +00:00
donteatfriedrice 5dbe6ff68b fix(editor): notion text adapter should handle text without styles correctly (#12248)
Closes: [BS-3486](https://linear.app/affine-design/issue/BS-3486/粘贴从-notion-复制的内容出错)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved handling of Notion text segments with empty or invalid style arrays, ensuring plain text and styled text are both processed correctly and preventing errors from malformed input.
- **Tests**
  - Added a test case to verify correct conversion of Notion text with empty styles arrays.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-13 08:05:30 +00:00
donteatfriedrice 0d518adc5b refactor(editor): add cache extension for link preview service (#12196)
Closes: [BS-2578](https://linear.app/affine-design/issue/BS-2578/优化-footnote-预览的逻辑:支持缓存结果,避免重复-loading)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a link preview caching mechanism, enabling faster and more efficient reuse of link preview data across the app.
  - Added a feature flag for enabling or disabling link preview cache, configurable through workspace experimental settings.
  - Enhanced localization with new entries describing the link preview cache feature.

- **Improvements**
  - Updated link preview service architecture for better extensibility and maintainability.
  - Improved integration of feature flags throughout chat and rendering components.

- **Bug Fixes**
  - Fixed tooltip formatting for footnote URLs.

- **Chores**
  - Updated dependencies and localization completeness tracking.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-13 05:11:34 +00:00
donteatfriedrice 4c56b685a1 fix(editor): footnote and citation icon url should be built with image proxy (#12169)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved how bookmark and footnote icons are displayed by routing image URLs through an image proxy service for enhanced reliability and consistency.

- **Refactor**
  - Adjusted the timing of service configuration for link previews and image proxies to occur after document initialization, ensuring more robust setup during content rendering.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-07 08:17:43 +00:00
donteatfriedrice 0a9f5a1da9 fix(editor): add credentialless attribute to iframe for COEP compliance (#12161)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Added enhanced privacy controls by including the `credentialless` attribute to embedded content iframes for PDF, Figma, Loom, YouTube, and generic iframe blocks. This helps improve security and privacy when displaying embedded content.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-07 04:01:57 +00:00
donteatfriedrice 83e55fad1e fix(editor): markdown url preprocessor should fully encode partial encoded url (#12091)
Closes: [BS-3369](https://linear.app/affine-design/issue/BS-3369/昨天发现-footnote-中的引用,和实际渲染出来的对不上)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
	- Improved handling of URLs in footnote definitions to ensure all URLs are fully percent-encoded, including those that were only partially encoded before.

- **Tests**
	- Added a new test case to verify that partially encoded URLs in footnotes are now fully encoded as expected.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-30 12:08:45 +00:00
donteatfriedrice 8ac3257f73 feat(editor): add local link preview data for bookmark block (#12085)
Closes: [BS-3343](https://linear.app/affine-design/issue/BS-3343/处理文档-readonly-时-bookmark-citation-preview-data-的获取和显示)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Improved bookmark blocks to display link previews even in readonly mode by dynamically fetching preview data when needed.

- **Refactor**
  - Enhanced event handling for bookmark cards, providing more consistent behavior when selecting or opening bookmarks.
  - Refined how preview data is sourced and rendered for bookmarks, ensuring more accurate and up-to-date information is shown.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-30 11:54:29 +00:00
donteatfriedrice 9a721c65b5 feat(editor): add callout block markdown adapter (#12070)
Closes: [BS-3358](https://linear.app/affine-design/issue/BS-3358/remark-callout-plugin)
Closes: [BS-3247](https://linear.app/affine-design/issue/BS-3247/callout-markdown-adapter-适配)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added support for callout blocks in Markdown, enabling recognition and conversion of callout syntax (e.g., `[!emoji]`) to and from block structures.
- **Bug Fixes**
  - Improved handling to distinguish callout blocks from regular blockquotes and paragraphs during Markdown processing.
- **Tests**
  - Introduced comprehensive tests for callout block serialization, deserialization, and plugin behavior to ensure correct Markdown handling.
- **Chores**
  - Added a new dependency for Markdown AST traversal.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-30 05:40:08 +00:00
donteatfriedrice 83670ab335 feat(editor): add experimental feature citation (#11984)
Closes: [BS-3122](https://linear.app/affine-design/issue/BS-3122/footnote-definition-adapter-适配)
Closes: [BS-3123](https://linear.app/affine-design/issue/BS-3123/几个-block-card-view-适配-footnote-态)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a new citation card component and web element for displaying citations.
  - Added support for citation-style rendering in attachment, bookmark, and linked document blocks.
  - Enabled citation parsing from footnote definitions in markdown for attachments, bookmarks, and linked docs.
  - Added a feature flag to enable or disable citation features.
  - Provided new toolbar logic to disable downloads for citation-style attachments.

- **Improvements**
  - Updated block models and properties to support citation identifiers.
  - Added localization and settings for the citation experimental feature.
  - Enhanced markdown adapters to recognize and process citation footnotes.
  - Included new constants and styles for citation card display.

- **Bug Fixes**
  - Ensured readonly state is respected in block interactions and rendering for citation blocks.

- **Documentation**
  - Added exports and effects for new citation components and features.

- **Tests**
  - Updated snapshots to include citation-related properties in block data.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-29 06:59:27 +00:00
donteatfriedrice 4887e1d612 refactor(editor): improve footnote URL preprocessor (#11975)
Closes: [BS-3302](https://linear.app/affine-design/issue/BS-3302/處理-affine-中的-redos-風險)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Bug Fixes**
	- Improved handling of footnote definitions with varied spacing, special characters, and malformed or incomplete entries, ensuring more reliable processing and display.
- **New Features**
	- Introduced advanced parsing for footnote URLs to improve accuracy and validation of footnote content.
- **Tests**
	- Expanded test coverage for footnote processing to include additional edge cases and mixed content scenarios, enhancing overall robustness.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-25 09:17:46 +00:00
donteatfriedrice cce31e822f feat(editor): update footnote popup style (#11932)
Closes: [BS-3113](https://linear.app/affine-design/issue/BS-3113/footnote-popup-ui-更新)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added a description display below the chip in the footnote popup when available.

- **Style**
  - Improved the appearance of footnote popups with enhanced border radius, padding, and layout.
  - Updated font styling for labels and descriptions.
  - Simplified chip styling by reducing height and removing unnecessary CSS properties.

- **Bug Fixes**
  - Tooltip content for URL references now displays both the link preview title and URL when available.

- **Refactor**
  - Simplified click handling by attaching it to the container instead of individual elements.
  - Removed unused click event properties from the footnote popup chip.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-24 15:48:30 +00:00
donteatfriedrice db5eadb72a feat(editor): add favicon, title, description support for footnote url reference (#11924)
Closes: [BS-3272](https://linear.app/affine-design/issue/BS-3272/footnote-适配-exa-api-返回结果)

## What's Changed

Add link preview data support (favicon, title, description) for URL references in footnotes:
- Store and display URL preview data in footnotes
- Add encoding/decoding support for favicon URLs
- Optimize link preview by using existing preview data when available
2025-04-23 11:57:25 +00:00
donteatfriedrice bbdea71686 fix(editor): add footnote url markdown preprocessor to avoid link node parsing (#11888)
Closes: [BS-3282](https://linear.app/affine-design/issue/BS-3282/预处理-footnote-definition-中的-url-避免-markdown-link-node-parsing)
2025-04-22 14:19:10 +00:00
donteatfriedrice a555df0200 fix(editor): footnote popup style and position issues (#11771)
Close [BS-3049](https://linear.app/affine-design/issue/BS-3049/chat引用的样式坏了) [BS-3024](https://linear.app/affine-design/issue/BS-3024/footnote-在容器边缘时,hover-抽搐)
2025-04-18 02:44:21 +00:00
donteatfriedrice d6287fd7b0 fix(editor): clicking footnote node should not open doc when readonly (#11749) 2025-04-17 08:52:17 +00:00
donteatfriedrice 022e5f2c93 fix(editor): update embed iframe block event tracker (#11736)
Close [BS-3151](https://linear.app/affine-design/issue/BS-3151/埋一下-reload-link-成功失败)
2025-04-16 09:53:38 +00:00
donteatfriedrice 212c13f843 fix(editor): add code block clipboard extension (#11731)
Close [BS-3109](https://linear.app/affine-design/issue/BS-3109/code-block-不支援-markdown-語法)
2025-04-16 08:32:00 +00:00
donteatfriedrice bfec5dd594 fix(editor): markdown html and image import (#11712)
Close
[BS-3145](https://linear.app/affine-design/issue/BS-3145/markdown-adapter-html-标签导入成-code-block)
[BS-3154](https://linear.app/affine-design/issue/BS-3154/[bug]-使用-markdown-with-files-导入到-affine-图片丢失)
2025-04-16 04:27:39 +00:00
donteatfriedrice 96e58316f7 feat(editor): add footnote node click handler (#11699)
Close [BS-3114](https://linear.app/affine-design/issue/BS-3114/点击-footnote-node-行为更新)
2025-04-15 12:22:43 +00:00
donteatfriedrice e02b159bf4 feat(core): remove preview footnote hover effect config (#11695)
Close [BS-3115](https://linear.app/affine-design/issue/BS-3115/侧边栏-footnote-ui-和用户行为与编辑器内统一)
2025-04-15 07:02:51 +00:00
donteatfriedrice 7aa87de5f7 fix(editor): markdown code preprocessor should handle link correctly (#11671)
Close [BS-3117](https://linear.app/affine-design/issue/BS-3117/代码粘贴后出现多余的-和-符号)
2025-04-14 08:28:43 +00:00
donteatfriedrice 4da00eba0d fix(editor): cut and paste surface-ref to same doc should remain surface-ref (#11639)
Close [BS-3107](https://linear.app/affine-design/issue/BS-3107/剪切-surface-ref-block-会变成指向当前文档的link-card)
2025-04-12 01:56:24 +00:00
donteatfriedrice 74ebec007d fix(editor): surface-ref refFlavour should be affine:frame when reference to a frame (#11632) 2025-04-11 06:51:31 +00:00
donteatfriedrice d5aebc1421 fix(editor): enhance markdown latex preprocessing (#11597)
Close [BS-2440](https://linear.app/affine-design/issue/BS-2440/inline-latex-markdown-adapter-需要更精确的处理)
2025-04-10 12:15:24 +00:00
donteatfriedrice dbb8451adb test(core): add e2e test for share page copy function (#11555)
related pr https://github.com/toeverything/AFFiNE/pull/11538
To close [BS-1915](https://linear.app/affine-design/issue/BS-1915/public-page-页面应该允许选中和复制内容)
2025-04-10 06:34:15 +00:00
donteatfriedrice 0302bd43cb fix(editor): should preserve indentation when pasting code with spaces into code block (#11587)
Close [BS-3087](https://linear.app/affine-design/issue/BS-3087/粘贴内容到-code-block-缩进会丢)
2025-04-10 04:48:08 +00:00
donteatfriedrice e4e3d8ef59 fix(editor): paste to code block should delete selected text (#11546)
Close [BS-3064](https://linear.app/affine-design/issue/BS-3064/fix-bug-pasting-in-code-block-does-not-replace-text)
2025-04-08 12:37:36 +00:00
donteatfriedrice b8e7ca3214 test(editor): fix flaky embed iframe e2e test (#11530) 2025-04-08 08:37:12 +00:00
donteatfriedrice 43809838ef test(editor): add embed iframe block e2e tests (#11502)
Close [BS-2669](https://linear.app/affine-design/issue/BS-2669/iframe-embed-block-添加测试)
2025-04-07 09:43:36 +00:00
donteatfriedrice 568a390b75 feat(editor): support markdown adapter preprocessed with latex delimiters (#11431)
To close [BS-2870](https://linear.app/affine-design/issue/BS-2870/支持识别-和-[-包裹内容为公式)

## Add Markdown Preprocessor Extension and Enhanced LaTeX Support

### Markdown Preprocessor Extension
This PR introduces a new preprocessor extension for Markdown adapters that allows preprocessing of content before conversion:

Adds a new PreprocessorManager for handling text transformations
Introduces extensible preprocessor interface that supports different processing levels (block/slice/doc)

Integrates preprocessor extension into the existing Markdown adapter workflow

### LaTeX Support Enhancement
Extends LaTeX support to handle both traditional and alternative syntax:
Adds support for backslash LaTeX syntax:

Block math: ```\[...\] ``` alongside existing ```$$...$$```
Inline math: ```\(...\) ``` alongside existing ```$...$```

Implements LaTeX preprocessor to standardize syntax before conversion

Updates tests to cover both syntax variants
2025-04-07 02:18:04 +00:00
donteatfriedrice 9206145a48 feat(editor): remove embed iframe feature flag (#11432)
Close [BS-3019](https://linear.app/affine-design/issue/BS-3019/remove-embed-iframe-feature-flag)
2025-04-03 04:59:52 +00:00
donteatfriedrice b8fd6370f8 fix(editor): remove embed iframe toolbar edit item (#11396) 2025-04-02 08:40:56 +00:00
donteatfriedrice 1dbd34177e feat(editor): embed iframe block event tracking (#11313)
Close [BS-2958](https://linear.app/affine-design/issue/BS-2958/埋点相关)
2025-04-01 02:50:23 +00:00
donteatfriedrice b2aa3084ec feat(editor): support to drag embed iframe from note to surface (#11267)
Close [BS-2807](https://linear.app/affine-design/issue/BS-2807/note-中与-surface-中-embed-iframe-block-互相拖动时的优化)
2025-03-31 06:23:11 +00:00
donteatfriedrice 7193393a06 fix(editor): embed iframe block idle status selected style (#11239)
Close [BS-2936](https://linear.app/affine-design/issue/BS-2936/占位去掉描边-grabber选中时颜色加深即可)
2025-03-28 02:25:00 +00:00
donteatfriedrice a459a00b21 feat(editor): support convert edgeless bookmark to embed iframe block (#11237)
Close [BS-2941](https://linear.app/affine-design/issue/BS-2941/白板-surface-中-card-view-无法转为-embed-view)
2025-03-28 02:25:00 +00:00
donteatfriedrice 676a8d653f fix(editor): reorder slash menu content & media group (#11233)
Close [BS-2935](https://linear.app/affine-design/issue/BS-2935/embed-在-slash-menu-中位置调整)
2025-03-27 08:36:40 +00:00
donteatfriedrice 0c73fde44a feat(editor): update embed iframe toolbar config (#11221)
part of [BS-2843](https://linear.app/affine-design/issue/BS-2843/iframe-embed-block-占位态)
2025-03-27 04:17:30 +00:00
donteatfriedrice e763061bd6 fix(editor): dragging area gets stuck when hovering some embed blocks (#11223)
Close [BS-2778](https://linear.app/affine-design/issue/BS-2778/[bug]-选区框选-html-block-卡顿)
2025-03-27 03:59:26 +00:00
donteatfriedrice c5624bfd13 refactor(editor): embed iframe block surface toolbar extension (#11193) 2025-03-26 08:38:07 +00:00
donteatfriedrice b5945c7e7d feat(editor): limit embed edgeless iframe block width and height (#11192)
[BS-2841](https://linear.app/affine-design/issue/BS-2841/iframe-embed-block-edgeless-block-component-限制-resize-时的最大最小宽高)
2025-03-26 08:38:06 +00:00
donteatfriedrice 39fa8e87cf feat(editor): add idle status for embed iframe block (#11142)
To close:
[BS-2843](https://linear.app/affine-design/issue/BS-2843/iframe-embed-block-占位态)
[BS-2844](https://linear.app/affine-design/issue/BS-2844/iframe-embed-block-create-modal-ui-调整)
[BS-2880](https://linear.app/affine-design/issue/BS-2880/spotify-选中时圆角有问题)
[BS-2881](https://linear.app/affine-design/issue/BS-2881/miro-圆角有问题-点击-see-the-board-加载之后就好了)
2025-03-26 08:38:06 +00:00
donteatfriedrice 5ea65b1709 feat(editor): support converting inline link to embed iframe block (#11030)
To close [BS-2846](https://linear.app/affine-design/issue/BS-2846/支持-inline-link-转成-embed-iframe-block)
2025-03-20 08:56:25 +00:00
donteatfriedrice f4202a7976 refactor(editor): move embed iframe config and service extension to shared (#11029) 2025-03-20 08:56:25 +00:00
donteatfriedrice e83f7eba00 feat(editor): add embed iframe provider google docs (#10998)
Related [BS-2835](https://linear.app/affine-design/issue/BS-2835/支持更多-embed-iframe-providers)
2025-03-20 04:42:26 +00:00
donteatfriedrice 46ed76ecb0 feat(editor): add embed iframe provider excalidraw (#10997) 2025-03-20 03:14:42 +00:00
donteatfriedrice f6e32d8894 feat(editor): add embed iframe provider miro (#10996) 2025-03-19 13:57:30 +00:00
donteatfriedrice 3a2d386275 feat(editor): support add embed iframe block in mobile (#10955)
To close [BS-2664](https://linear.app/affine-design/issue/BS-2664/iframe-embed-block-移动端支持)
2025-03-19 02:58:51 +00:00
donteatfriedrice 6eb34d70c1 feat(editor): support bookmark block convert to embed iframe block (#10907) 2025-03-17 05:00:55 +00:00
donteatfriedrice d7d512084e feat(editor): embed iframe error status card in surface (#10869)
To close [BS-2806](https://linear.app/affine-design/issue/BS-2806/iframe-embed-block-edgeless-loading-and-error-status)
2025-03-16 09:05:04 +00:00
donteatfriedrice 7ecb1f510d feat(editor): embed iframe loading status card in surface (#10868) 2025-03-16 09:05:04 +00:00
donteatfriedrice 1d4ee1e383 feat(editor): support embed iframe block in edgeless (#10830)
To close:
[BS-2665](https://linear.app/affine-design/issue/BS-2665/iframe-embed-block-edgeless-mode-支持)
[BS-2666](https://linear.app/affine-design/issue/BS-2666/iframe-embed-block-edgeless-toolbar)
[BS-2667](https://linear.app/affine-design/issue/BS-2667/iframe-embed-block-edgeless-mode-拖拽调整支持)
[BS-2789](https://linear.app/affine-design/issue/BS-2789/iframe-embed-block-edgeless-block-component)
2025-03-15 09:23:02 +00:00
donteatfriedrice d2c62602a4 feat(editor): support embed iframe block (#10740)
To close:
[BS-2660](https://linear.app/affine-design/issue/BS-2660/slash-menu-支持-iframe-embed)
[BS-2661](https://linear.app/affine-design/issue/BS-2661/iframe-embed-block-model-and-block-component)
[BS-2662](https://linear.app/affine-design/issue/BS-2662/iframe-embed-block-toolbar)
[BS-2768](https://linear.app/affine-design/issue/BS-2768/iframe-embed-block-loading-和-error-态)
[BS-2670](https://linear.app/affine-design/issue/BS-2670/iframe-embed-block-导出)

# PR Description

# Add Embed Iframe Block Support

## Overview

This PR introduces a new `EmbedIframeBlock` to enhance content embedding capabilities within our editor. This block allows users to seamlessly embed external content from various providers (Google Drive, Spotify, etc.) directly into their docs.

## New Blocks

### EmbedIframeBlock

The core block that renders embedded iframe content. This block:

* Displays external content within a secure iframe
* Handles loading states with visual feedback
* Provides error handling with edit and retry options
* Supports customization of width, height, and other iframe attributes

### Supporting Components

* **EmbedIframeCreateModal**: Modal interface for creating new iframe embeds
* **EmbedIframeLinkEditPopup**: UI for editing existing embed links
* **EmbedIframeLoadingCard**: Visual feedback during content loading
* **EmbedIframeErrorCard**: Error handling with retry functionality

## New Store Extensions

### EmbedIframeConfigExtension

This extension provides configuration for different embed providers:

```typescript
/**
 * The options for the iframe
 * @example
 * {
 *   defaultWidth: '100%',
 *   defaultHeight: '152px',
 *   style: 'border-radius: 8px;',
 *   allow: 'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture',
 * }
 * =>
 * <iframe
 *   width="100%"
 *   height="152px"
 *   style="border-radius: 8px;"
 *   allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
 * ></iframe>
 */
export type IframeOptions = {
  defaultWidth?: string;
  defaultHeight?: string;
  style?: string;
  referrerpolicy?: string;
  scrolling?: boolean;
  allow?: string;
  allowFullscreen?: boolean;
};

/**
 * Define the config of an embed iframe block provider
 */
export type EmbedIframeConfig = {
  /**
   * The name of the embed iframe block provider
   */
  name: string;
  /**
   * The function to match the url
   */
  match: (url: string) => boolean;
  /**
   * The function to build the oEmbed URL for fetching embed data
   */
  buildOEmbedUrl: (url: string) => string | undefined;
  /**
   * Use oEmbed URL directly as iframe src without fetching oEmbed data
   */
  useOEmbedUrlDirectly: boolean;
  /**
   * The options for the iframe
   */
  options?: IframeOptions;
};

export const EmbedIframeConfigIdentifier =
  createIdentifier<EmbedIframeConfig>('EmbedIframeConfig');

export function EmbedIframeConfigExtension(
  config: EmbedIframeConfig
): ExtensionType & {
  identifier: ServiceIdentifier<EmbedIframeConfig>;
} {
  const identifier = EmbedIframeConfigIdentifier(config.name);
  return {
    setup: di => {
      di.addImpl(identifier, () => config);
    },
    identifier,
  };
}
```

**example:**

```typescript
//  blocksuite/affine/blocks/block-embed/src/embed-iframe-block/configs/providers/spotify.ts

const SPOTIFY_DEFAULT_WIDTH = '100%';
const SPOTIFY_DEFAULT_HEIGHT = '152px';

// https://developer.spotify.com/documentation/embeds/reference/oembed
const spotifyEndpoint = 'https://open.spotify.com/oembed';

const spotifyUrlValidationOptions: EmbedIframeUrlValidationOptions = {
  protocols: ['https:'],
  hostnames: ['open.spotify.com', 'spotify.link'],
};

const spotifyConfig = {
  name: 'spotify',
  match: (url: string) =>
    validateEmbedIframeUrl(url, spotifyUrlValidationOptions),
  buildOEmbedUrl: (url: string) => {
    const match = validateEmbedIframeUrl(url, spotifyUrlValidationOptions);
    if (!match) {
      return undefined;
    }
    const encodedUrl = encodeURIComponent(url);
    const oEmbedUrl = `${spotifyEndpoint}?url=${encodedUrl}`;
    return oEmbedUrl;
  },
  useOEmbedUrlDirectly: false,
  options: {
    defaultWidth: SPOTIFY_DEFAULT_WIDTH,
    defaultHeight: SPOTIFY_DEFAULT_HEIGHT,
    allow:
      'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture',
    style: 'border-radius: 12px;',
    allowFullscreen: true,
  },
};

// add the config extension to store
export const SpotifyEmbedConfig = EmbedIframeConfigExtension(spotifyConfig);
```

**Key features:**

* Provider registration and discovery
* URL pattern matching
* Provider-specific embed options (width, height, features)

### EmbedIframeService

This service provides abilities to handle URL validation, data fetching, and block creation

**Type:**

```typescript
/**
 * Service for handling embeddable URLs
 */
export interface EmbedIframeProvider {
  /**
   * Check if a URL can be embedded
   * @param url URL to check
   * @returns true if the URL can be embedded, false otherwise
   */
  canEmbed: (url: string) => boolean;

  /**
   * Build a API URL for fetching embed data
   * @param url URL to build API URL
   * @returns API URL if the URL can be embedded, undefined otherwise
   */
  buildOEmbedUrl: (url: string) => string | undefined;

  /**
   * Get the embed iframe config
   * @param url URL to get embed iframe config
   * @returns Embed iframe config if the URL can be embedded, undefined otherwise
   */
  getConfig: (url: string) => EmbedIframeConfig | undefined;

  /**
   * Get embed iframe data
   * @param url URL to get embed iframe data
   * @returns Embed iframe data if the URL can be embedded, undefined otherwise
   */
  getEmbedIframeData: (url: string) => Promise<EmbedIframeData | null>;

  /**
   * Parse an embeddable URL and add an EmbedIframeBlock to doc
   * @param url Original url to embed
   * @param parentId Parent block ID
   * @param index Optional index to insert at
   * @returns Created block id if successful, undefined if the URL cannot be embedded
   */
  addEmbedIframeBlock: (
    props: Partial<EmbedIframeBlockProps>,
    parentId: string,
    index?: number
  ) => string | undefined;
}
```

**Implemetation:**

```typescript
export class EmbedIframeService
  extends StoreExtension
  implements EmbedIframeProvider
{
  static override key = 'embed-iframe-service';

  private readonly _configs: EmbedIframeConfig[];

  constructor(store: Store) {
    super(store);
    this._configs = Array.from(
      store.provider.getAll(EmbedIframeConfigIdentifier).values()
    );
  }

  canEmbed = (url: string): boolean => {
    return this._configs.some(config => config.match(url));
  };

  buildOEmbedUrl = (url: string): string | undefined => {
    return this._configs.find(config => config.match(url))?.buildOEmbedUrl(url);
  };

  getConfig = (url: string): EmbedIframeConfig | undefined => {
    return this._configs.find(config => config.match(url));
  };

  getEmbedIframeData = async (
    url: string,
    signal?: AbortSignal
  ): Promise<EmbedIframeData | null> => {
    try {
      const config = this._configs.find(config => config.match(url));
      if (!config) {
        return null;
      }

      const oEmbedUrl = config.buildOEmbedUrl(url);
      if (!oEmbedUrl) {
        return null;
      }

      // if the config useOEmbedUrlDirectly is true, return the url directly as iframe_url
      if (config.useOEmbedUrlDirectly) {
        return {
          iframe_url: oEmbedUrl,
        };
      }

      // otherwise, fetch the oEmbed data
      const response = await fetch(oEmbedUrl, { signal });
      if (!response.ok) {
        console.warn(
          `Failed to fetch oEmbed data: ${response.status} ${response.statusText}`
        );
        return null;
      }

      const data = await response.json();
      return data as EmbedIframeData;
    } catch (error) {
      if (error instanceof Error && error.name !== 'AbortError') {
        console.error('Error fetching embed iframe data:', error);
      }
      return null;
    }
  };

  addEmbedIframeBlock = (
    props: Partial<EmbedIframeBlockProps>,
    parentId: string,
    index?: number
  ): string | undefined => {
    const blockId = this.store.addBlock(
      'affine:embed-iframe',
      props,
      parentId,
      index
    );
    return blockId;
  };
}
```

**Usage:**

```typescript
// Usage example
const embedIframeService = this.std.get(EmbedIframeService);

// Check if a URL can be embedded
const canEmbed = embedIframeService.canEmbed(url);

// Get embed data for a URL
const embedData = await embedIframeService.getEmbedIframeData(url);

// Add an embed iframe block to the document
const block = embedIframeService.addEmbedIframeBlock({
  url,
  iframeUrl: embedData.iframe_url,
  title: embedData.title,
  description: embedData.description
}, parentId, index);
```

**Key features:**

* URL validation and transformation
* Provider-specific data fetching
* Block creation and management

## Adaptations

### Toolbar Integration

Added toolbar actions for embedded content:

* Copy link
* Edit embed title and description
* Toggle between inline/card views
* Add caption
* And more

### Slash Menu Integration

Added a new slash menu option for embedding content:

* Embed item for inserting embed iframe block
* Conditional rendering based on feature flags

### Adapters

Implemented adapters for various formats:

* **HTML Adapter**: Exports embed original urls as html links
* **Markdown Adapter**: Exports embed original urls as markdown links
* **Plain Text Adapter**: Exports embed original urls as link text

## To Be Continued:
- [ ] **UI Optimization**
- [ ] **Edgeless Mode Support**
- [ ] **Mobile Support**
2025-03-13 04:11:46 +00:00
donteatfriedrice 40351295c9 fix(editor): should not select or open latex editor when readonly (#10601) 2025-03-04 07:27:58 +00:00
donteatfriedrice 170066050e feat(core): support latex in ai text renderer (#10576) 2025-03-03 09:19:31 +00:00
donteatfriedrice 272d41e32d chore: remove unused component imports and styles from text-renderer (#10478) 2025-02-27 08:54:15 +00:00
donteatfriedrice 7c8ba13aad fix(core): extract a scrollable text renderer fot ai panel (#10469) 2025-02-27 07:00:16 +00:00
donteatfriedrice d63f16da5e fix(editor): affine preview root style (#10420)
Fix [BS-2677](https://linear.app/affine-design/issue/BS-2677/linked-doc-embed-view样式错误)

1. Only show the border of embed synced doc block (in note) when hover.
2. Fix affine preview root padding style, set padding only when affine preview root in embed synced doc block (in surface).
3. Only add the footnote config extension to the chat panel and chat block center peek. For footnotes in other page preview scenarios, such as footnote nodes within embed synced doc blocks or embed linked doc blocks, the hover effect should be maintained.
2025-02-26 04:25:24 +00:00
donteatfriedrice 378bb3795d refactor(editor): use doc title and id as snapshot file name (#10397)
[BS-2549](https://linear.app/affine-design/issue/BS-2549/snap-shot-导出建议使用文档名称作为文件名,而不是一个-id)
2025-02-24 09:32:32 +00:00
donteatfriedrice 1b2a4377fd feat(editor): update footnote node style and config (#10392)
[BS-2581](https://linear.app/affine-design/issue/BS-2581/优化-footnote-node-正文样式)
2025-02-24 08:15:04 +00:00
donteatfriedrice 2d41c2ff8d chore: bump theme (#10358) 2025-02-24 10:08:47 +08:00
donteatfriedrice 734ca154ae refactor(core): use image preview component in chat (#10357)
[BS-2421](https://linear.app/affine-design/issue/BS-2421/chat-block-and-chat-panel-input-render-images-时存在内存泄露风险)
2025-02-21 15:36:55 +00:00
donteatfriedrice 2b11941c0e chore: bump theme (#10290) 2025-02-19 11:37:19 +00:00
donteatfriedrice 54b7515167 fix(editor): log when export blob failed (#10287) 2025-02-19 10:06:50 +00:00
donteatfriedrice 319d909ac8 fix(editor): paste surface-ref block to another doc as embed-linked-doc block (#10274)
[BS-2155](https://linear.app/affine-design/issue/BS-2155/复制-insert-frame-group-粘贴后,应当变为-block-ref-link)
2025-02-19 07:02:27 +00:00
donteatfriedrice 15e9acefc2 fix(editor): paste when select multiple block texts (#10227)
[BS-2512](https://linear.app/affine-design/issue/BS-2512/选中多段粘贴,多段只有第一段会被replace,这个bug还在)
2025-02-18 12:13:55 +00:00
donteatfriedrice e67fd67a3c fix(core): copy more button group style (#10240) 2025-02-18 04:07:59 +00:00
donteatfriedrice 594224e3b4 feat(editor): support to copy in preview root block (#10214)
[BS-2590](https://linear.app/affine-design/issue/BS-2590/ai-chat-panel-的-copy-code-不-work-了) [BS-2550](https://linear.app/affine-design/issue/BS-2550/chat-panel-内的内容复制粘贴到-affine-编辑器时-时没办法保留格式)
2025-02-17 04:07:10 +00:00
donteatfriedrice 5a42edf076 fix(core): copy more button style (#10196)
[AF-2228](https://linear.app/affine-design/issue/AF-2228/ui-bug-retry-和-copy-的按钮颜色不一致)
2025-02-14 13:22:27 +00:00
donteatfriedrice e6b570e613 feat(core): support network search in chat block center peek (#10186)
[BS-2582](https://linear.app/affine-design/issue/BS-2582/chat-block-center-peek-支持-network-search)
2025-02-14 12:43:31 +00:00
donteatfriedrice 40c6e42ab8 fix(core): edgeless text ai action should generate image correctly (#10158)
[BS-2570](https://linear.app/affine-design/issue/BS-2570/edgeless-text-没有被正确的作为上下文放入-app)
2025-02-13 09:38:13 +00:00
donteatfriedrice bd041cbfcf fix(editor): shadowless element should remove style element correctly (#10128)
[BS-2565](https://linear.app/affine-design/issue/BS-2565/关闭-chat-block-center-peek-后新生成的-chat-block-最后一个-message-样式不正确)
2025-02-12 10:38:07 +00:00
donteatfriedrice 30612de1ad fix(core): wrap code in ai chat (#10108)
[BS-2540](https://linear.app/affine-design/issue/BS-2540/ai-chat-中-code-block-需要默认换行)
2025-02-12 09:43:52 +00:00
donteatfriedrice e350ba4a9c test: enable chat block e2e test (#10111) 2025-02-12 09:26:52 +00:00
donteatfriedrice 19f0eb1931 fix(core): use patched preview spec builder in ai chat (#10090)
[BS-2526](https://linear.app/affine-design/issue/BS-2526/chat-panel-里的-footnote-popup-需要支持交互)
2025-02-11 15:11:54 +00:00
donteatfriedrice 0df94b8e35 fix(core): typo (#10022)
[BS-2532](https://linear.app/affine-design/issue/BS-2532/typo-tidy-a-article-with-ai-mindmap-action-tidy-an-article-with-xxxxx)
2025-02-07 11:09:00 +00:00
donteatfriedrice b38389c670 feat(core): add tooltip for import dialog snapshot item (#10013)
[PD-2132](https://linear.app/affine-design/issue/PD-2132/import-导入优化:snapshot-需要一个问号,解释文档)
2025-02-07 10:23:59 +00:00
donteatfriedrice 9cae1c3a28 fix(core): copilot client should throw right ai error (#9958)
[BS-2488](https://linear.app/affine-design/issue/BS-2488/copilot-client-需要正确返回错误类型)
2025-02-05 12:46:13 +00:00
donteatfriedrice 4b553d153a feat(core): update chat error style (#9885)
[BS-2487](https://linear.app/affine-design/issue/BS-2487/报错样式更新)
2025-01-24 12:39:10 +00:00
donteatfriedrice c0eb735890 fix(core): extract text blocks markdown from doc (#9879)
[AF-2162](https://linear.app/affine-design/issue/AF-2162/ai-提取-markdown-内容不完整)
2025-01-24 04:18:53 +00:00
donteatfriedrice bdc8dd8d5f feat(editor): add link preview to footnote popup (#9869)
[BS-2399](https://linear.app/affine-design/issue/BS-2399/ai-link-的预览支持:获取-fav-icon-标题)
2025-01-23 09:31:21 +00:00
donteatfriedrice bf797c7a0c feat(editor): support footnote adapter (#9844)
[BS-2373](https://linear.app/affine-design/issue/BS-2373/适配-footnote-adapter)
2025-01-22 06:42:35 +00:00
donteatfriedrice f995f216bd fix(editor): inline latex editor should not be shown when doc is readonly (#9794)
[BS-2442](https://linear.app/affine-design/issue/BS-2442/只读时-inline-latex-node-点击不应该弹出-modal)
2025-01-20 15:44:07 +00:00
donteatfriedrice 4bd43a698c refactor(editor): refactor linkPreviewer as an extension and remove bookmark service (#9754)
[BS-2427](https://linear.app/affine-design/issue/BS-2427/移除-bookmark-block-service) [BS-2418](https://linear.app/affine-design/issue/BS-2418/linkpreviewer-重构成插件)
2025-01-20 04:18:00 +00:00
donteatfriedrice df910d7013 feat(editor): add affine inline footnote (#9745)
[BS-2369](https://linear.app/affine-design/issue/BS-2369/新增-affinetextattribute-footnote)  [BS-2370](https://linear.app/affine-design/issue/BS-2370/支持-footnote-自定义渲染行内内容) [BS-2372](https://linear.app/affine-design/issue/BS-2372/提供-footnoteconfigextension) [BS-2375](https://linear.app/affine-design/issue/BS-2375/footnote-自定义渲染-popup)

### Add new AffineTextAttribute: footnote

```
/**
 * FootNote is used to reference a doc, attachment or url.
 */
export interface AffineTextAttributes {
  ...
  footnote?: {
    label: string; // label of the footnote
    reference: {
      type: 'doc' | 'attachment' | 'url'; // type of reference
      docId?: string; // the id of the reference doc
      url?: string; //  the url of the reference network resource
      blobId?: string; // the id of the reference attachment
      fileName?: string; // the name of the reference attachment
      fileType?: string; // the type of the reference attachment
    }
  } | null
}
```

### FootNoteNodeConfigProvider Extension

#### FootNoteNodeConfig Type Definition

```
type FootNoteNodeRenderer = (
  footnote: FootNote,
  std: BlockStdScope
) => TemplateResult<1>;

type FootNotePopupRenderer = (
  footnote: FootNote,
  std: BlockStdScope,
  abortController: AbortController
) => TemplateResult<1>;

export interface FootNoteNodeConfig {
  customNodeRenderer?: FootNoteNodeRenderer;
  customPopupRenderer?: FootNotePopupRenderer;
  interactive?: boolean;
  hidePopup?: boolean;
}
```

#### FootNoteNodeConfigProvider Class

```
export class FootNoteNodeConfigProvider {
  private _customNodeRenderer?: FootNoteNodeRenderer;
  private _customPopupRenderer?: FootNotePopupRenderer;
  private _hidePopup: boolean;
  private _interactive: boolean;

  get customNodeRenderer() {
    return this._customNodeRenderer;
  }

  get customPopupRenderer() {
    return this._customPopupRenderer;
  }

  get doc() {
    return this.std.store;
  }

  get hidePopup() {
    return this._hidePopup;
  }

  get interactive() {
    return this._interactive;
  }

  constructor(
    config: FootNoteNodeConfig,
    readonly std: BlockStdScope
  ) {
    this._customNodeRenderer = config.customNodeRenderer;
    this._customPopupRenderer = config.customPopupRenderer;
    this._hidePopup = config.hidePopup ?? false;
    this._interactive = config.interactive ?? true;
  }

  setCustomNodeRenderer(renderer: FootNoteNodeRenderer) {
    this._customNodeRenderer = renderer;
  }

  setCustomPopupRenderer(renderer: FootNotePopupRenderer) {
    this._customPopupRenderer = renderer;
  }

  setHidePopup(hidePopup: boolean) {
    this._hidePopup = hidePopup;
  }

  setInteractive(interactive: boolean) {
    this._interactive = interactive;
  }
}
```

#### FootNoteNodeConfigProvider Extension

```
export const FootNoteNodeConfigIdentifier =
  createIdentifier<FootNoteNodeConfigProvider>('AffineFootNoteNodeConfig');

export function FootNoteNodeConfigExtension(
  config: FootNoteNodeConfig
): ExtensionType {
  return {
    setup: di => {
      di.addImpl(
        FootNoteNodeConfigIdentifier,
        provider =>
          new FootNoteNodeConfigProvider(config, provider.get(StdIdentifier))
      );
    },
  };
}
```

The footnote node can be extended by this extension.

### FootnoteInlineSpec

```
export const FootNoteInlineSpecExtension = InlineSpecExtension(
  'footnote',
  provider => {
    const std = provider.get(StdIdentifier);
    const config =
      provider.getOptional(FootNoteNodeConfigIdentifier) ?? undefined;
    return {
      name: 'footnote',
      schema: FootNoteSchema.optional().nullable().catch(undefined),
      match: delta => {
        return !!delta.attributes?.footnote;
      },
      renderer: ({ delta }) => {
        return html`<affine-footnote-node
          .delta=${delta}
          .std=${std}
          .config=${config}
        ></affine-footnote-node>`;
      },
      embed: true,
    };
  }
);
```
2025-01-17 09:38:43 +00:00
donteatfriedrice 4f421efb22 fix(editor): init default theme observer value according to data-theme (#9698) 2025-01-15 04:04:06 +00:00