fix(export): apply block quote syntax to every line in annotation export, closes #3534 (#3536)

Add formatBlockQuote utility and blockquote nunjucks filter so both
default and custom template exports prefix every line with `>`.
Document all available formatters in the custom template help panel.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-03-14 22:23:17 +08:00
committed by GitHub
parent db3dee025b
commit f7b2a2432c
32 changed files with 493 additions and 32 deletions
@@ -1,5 +1,10 @@
import { describe, it, expect } from 'vitest';
import { renderNoteTemplate, validateNoteTemplate, NoteTemplateData } from '../../utils/note';
import {
renderNoteTemplate,
validateNoteTemplate,
formatBlockQuote,
NoteTemplateData,
} from '../../utils/note';
describe('renderNoteTemplate', () => {
const sampleData: NoteTemplateData = {
@@ -325,6 +330,23 @@ describe('renderNoteTemplate', () => {
});
});
describe('Blockquote filter', () => {
it('should prefix every line with > in templates', () => {
const data: NoteTemplateData = {
...sampleData,
chapters: [
{
title: 'Ch1',
annotations: [{ text: 'Line 1\nLine 2\nLine 3' }],
},
],
};
const template = '{{ chapters[0].annotations[0].text | blockquote }}';
const result = renderNoteTemplate(template, data);
expect(result).toBe('> Line 1\n> Line 2\n> Line 3');
});
});
describe('Newline to BR filter', () => {
it('should convert newlines to br tags', () => {
const dataWithNewlines: NoteTemplateData = {
@@ -570,3 +592,24 @@ describe('validateNoteTemplate', () => {
expect(result.isValid).toBe(true);
});
});
describe('formatBlockQuote', () => {
it('should prefix every line with > for multi-line text', () => {
const text = 'Nothing must happen to you\nNo, what am I saying\nEverything must happen to you';
expect(formatBlockQuote(text)).toBe(
'> Nothing must happen to you\n> No, what am I saying\n> Everything must happen to you',
);
});
it('should handle single-line text', () => {
expect(formatBlockQuote('Hello')).toBe('> Hello');
});
it('should handle empty string', () => {
expect(formatBlockQuote('')).toBe('> ');
});
it('should preserve empty lines within the quote', () => {
expect(formatBlockQuote('First\n\nThird')).toBe('> First\n> \n> Third');
});
});