mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 03:33:06 +08:00
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
This commit is contained in:
@@ -50,4 +50,28 @@ describe('footnoteUrlPreprocessor', () => {
|
||||
'[^ref]: {"type":"url","url":"https%3A%2F%2Fexample.com%2Fpath%20with%20spaces%3Fparam%3Dvalue%26another%3Dparam"}';
|
||||
expect(footnoteUrlPreprocessor(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should encode unencoded favicon URLs', () => {
|
||||
const input =
|
||||
'[^ref]: {"type":"url","url":"https://example.com","favicon":"https://example.com/icon.png"}';
|
||||
const expected =
|
||||
'[^ref]: {"type":"url","url":"https%3A%2F%2Fexample.com","favicon":"https%3A%2F%2Fexample.com%2Ficon.png"}';
|
||||
expect(footnoteUrlPreprocessor(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should not encode already encoded favicon URLs', () => {
|
||||
const input =
|
||||
'[^ref]: {"type":"url","url":"https://example.com","favicon":"https%3A%2F%2Fexample.com%2Ficon.png"}';
|
||||
const expected =
|
||||
'[^ref]: {"type":"url","url":"https%3A%2F%2Fexample.com","favicon":"https%3A%2F%2Fexample.com%2Ficon.png"}';
|
||||
expect(footnoteUrlPreprocessor(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('should handle both URL and icon encoding in the same footnote', () => {
|
||||
const input =
|
||||
'[^ref]: {"type":"url","url":"https://example.com?param=value","favicon":"https://example.com/icon.png?size=large"}';
|
||||
const expected =
|
||||
'[^ref]: {"type":"url","url":"https%3A%2F%2Fexample.com%3Fparam%3Dvalue","favicon":"https%3A%2F%2Fexample.com%2Ficon.png%3Fsize%3Dlarge"}';
|
||||
expect(footnoteUrlPreprocessor(input)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,20 +35,41 @@ export function footnoteUrlPreprocessor(content: string): string {
|
||||
(match, reference, jsonContent) => {
|
||||
try {
|
||||
const footnoteData = JSON.parse(jsonContent.trim());
|
||||
// If footnoteData is not an object or doesn't have url, return original content
|
||||
// If the url is already encoded, return original content
|
||||
if (
|
||||
typeof footnoteData !== 'object' ||
|
||||
!footnoteData.url ||
|
||||
isEncoded(footnoteData.url)
|
||||
) {
|
||||
// Basic validation checks
|
||||
if (typeof footnoteData !== 'object') {
|
||||
return match;
|
||||
}
|
||||
|
||||
return formatFootnoteDefinition(reference, {
|
||||
if (!footnoteData.url) {
|
||||
return match;
|
||||
}
|
||||
|
||||
// Check if URLs are already encoded
|
||||
const isUrlEncoded = isEncoded(footnoteData.url);
|
||||
const hasIcon = !!footnoteData.favicon;
|
||||
const isIconEncoded = hasIcon && isEncoded(footnoteData.favicon);
|
||||
|
||||
// If both URL and icon (if present) are already encoded, return original
|
||||
if (isUrlEncoded && (!hasIcon || isIconEncoded)) {
|
||||
return match;
|
||||
}
|
||||
|
||||
// Create processed data with encoded URLs
|
||||
const processedData = {
|
||||
...footnoteData,
|
||||
url: encodeURIComponent(footnoteData.url),
|
||||
});
|
||||
url: isUrlEncoded
|
||||
? footnoteData.url
|
||||
: encodeURIComponent(footnoteData.url),
|
||||
};
|
||||
|
||||
// Add encoded favicon if present
|
||||
if (hasIcon) {
|
||||
processedData.favicon = isIconEncoded
|
||||
? footnoteData.favicon
|
||||
: encodeURIComponent(footnoteData.favicon);
|
||||
}
|
||||
|
||||
return formatFootnoteDefinition(reference, processedData);
|
||||
} catch {
|
||||
// Keep original content if JSON parsing fails
|
||||
return match;
|
||||
|
||||
Reference in New Issue
Block a user