feat: expand ISAC content modeling
This commit is contained in:
@@ -91,6 +91,172 @@ describe('article documents', () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('accepts and canonicalizes metadata emitted by the Tiptap editor', () => {
|
||||
const parsed = parseArticleDocument({
|
||||
version: 1,
|
||||
document: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'Read more',
|
||||
marks: [
|
||||
{
|
||||
type: 'link',
|
||||
attrs: {
|
||||
href: 'https://shd.build/news',
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer nofollow',
|
||||
class: null,
|
||||
title: 'News archive',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'orderedList',
|
||||
attrs: { start: 1, type: null },
|
||||
content: [
|
||||
{
|
||||
type: 'listItem',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'First item' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed?.document.document.content).toEqual([
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'Read more',
|
||||
marks: [
|
||||
{
|
||||
type: 'link',
|
||||
attrs: {
|
||||
href: 'https://shd.build/news',
|
||||
title: 'News archive',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'orderedList',
|
||||
content: [
|
||||
{
|
||||
type: 'listItem',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: 'First item' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
expect(parsed?.plainText).toContain('News archive');
|
||||
});
|
||||
|
||||
it('preserves supported ordered-list numbering', () => {
|
||||
const parsed = parseArticleDocument({
|
||||
version: 1,
|
||||
document: {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'orderedList',
|
||||
attrs: { start: 2, type: 'A' },
|
||||
content: [
|
||||
{
|
||||
type: 'listItem',
|
||||
content: [{ type: 'paragraph' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed?.document.document.content?.[0]).toMatchObject({
|
||||
type: 'orderedList',
|
||||
attrs: { start: 2, type: 'A' },
|
||||
});
|
||||
expect(parseArticleDocument(parsed?.document)?.document).toEqual(
|
||||
parsed?.document,
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects unknown link metadata and non-default ordered lists', () => {
|
||||
const documentWith = (content: unknown[]) => ({
|
||||
version: 1,
|
||||
document: { type: 'doc', content },
|
||||
});
|
||||
|
||||
expect(
|
||||
parseArticleDocument(
|
||||
documentWith([
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: 'unsafe metadata',
|
||||
marks: [
|
||||
{
|
||||
type: 'link',
|
||||
attrs: {
|
||||
href: 'https://shd.build',
|
||||
onclick: 'alert(1)',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
),
|
||||
).toBeNull();
|
||||
expect(
|
||||
parseArticleDocument(
|
||||
documentWith([
|
||||
{
|
||||
type: 'orderedList',
|
||||
attrs: { start: 0, type: 'decimal' },
|
||||
content: [],
|
||||
},
|
||||
]),
|
||||
),
|
||||
).toBeNull();
|
||||
expect(
|
||||
parseArticleDocument(
|
||||
documentWith([
|
||||
{
|
||||
type: 'orderedList',
|
||||
attrs: { start: 1, type: 1 },
|
||||
content: [],
|
||||
},
|
||||
]),
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('rejects duplicate embed keys and unknown envelope fields', () => {
|
||||
const embed = {
|
||||
type: 'buildEmbed',
|
||||
|
||||
Reference in New Issue
Block a user