2022-10-11 01:57:18 +05:30
import Audio from '~/content_editor/extensions/audio' ;
2022-07-16 23:28:13 +05:30
import Bold from '~/content_editor/extensions/bold' ;
import Blockquote from '~/content_editor/extensions/blockquote' ;
import BulletList from '~/content_editor/extensions/bullet_list' ;
import Code from '~/content_editor/extensions/code' ;
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight' ;
2022-10-11 01:57:18 +05:30
import Diagram from '~/content_editor/extensions/diagram' ;
2022-07-23 23:45:48 +05:30
import FootnoteDefinition from '~/content_editor/extensions/footnote_definition' ;
import FootnoteReference from '~/content_editor/extensions/footnote_reference' ;
2022-08-27 11:52:29 +05:30
import Frontmatter from '~/content_editor/extensions/frontmatter' ;
2022-07-16 23:28:13 +05:30
import HardBreak from '~/content_editor/extensions/hard_break' ;
2022-08-13 15:12:31 +05:30
import HTMLNodes from '~/content_editor/extensions/html_nodes' ;
2022-07-16 23:28:13 +05:30
import Heading from '~/content_editor/extensions/heading' ;
import HorizontalRule from '~/content_editor/extensions/horizontal_rule' ;
import Image from '~/content_editor/extensions/image' ;
import Italic from '~/content_editor/extensions/italic' ;
import Link from '~/content_editor/extensions/link' ;
import ListItem from '~/content_editor/extensions/list_item' ;
import OrderedList from '~/content_editor/extensions/ordered_list' ;
2022-07-23 23:45:48 +05:30
import Paragraph from '~/content_editor/extensions/paragraph' ;
2022-08-27 11:52:29 +05:30
import ReferenceDefinition from '~/content_editor/extensions/reference_definition' ;
2022-07-16 23:28:13 +05:30
import Sourcemap from '~/content_editor/extensions/sourcemap' ;
2022-07-23 23:45:48 +05:30
import Strike from '~/content_editor/extensions/strike' ;
import Table from '~/content_editor/extensions/table' ;
import TableHeader from '~/content_editor/extensions/table_header' ;
2022-10-11 01:57:18 +05:30
import TableOfContents from '~/content_editor/extensions/table_of_contents' ;
2022-07-23 23:45:48 +05:30
import TableRow from '~/content_editor/extensions/table_row' ;
import TableCell from '~/content_editor/extensions/table_cell' ;
import TaskList from '~/content_editor/extensions/task_list' ;
import TaskItem from '~/content_editor/extensions/task_item' ;
2022-10-11 01:57:18 +05:30
import Video from '~/content_editor/extensions/video' ;
2022-07-16 23:28:13 +05:30
import remarkMarkdownDeserializer from '~/content_editor/services/remark_markdown_deserializer' ;
import markdownSerializer from '~/content_editor/services/markdown_serializer' ;
2022-10-11 01:57:18 +05:30
import { SAFE _VIDEO _EXT , SAFE _AUDIO _EXT , DIAGRAM _LANGUAGES } from '~/content_editor/constants' ;
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
import { createTestEditor , createDocBuilder } from './test_utils' ;
2022-07-16 23:28:13 +05:30
const tiptapEditor = createTestEditor ( {
extensions : [
2022-10-11 01:57:18 +05:30
Audio ,
2022-07-16 23:28:13 +05:30
Blockquote ,
Bold ,
BulletList ,
Code ,
CodeBlockHighlight ,
2022-10-11 01:57:18 +05:30
Diagram ,
2022-07-23 23:45:48 +05:30
FootnoteDefinition ,
FootnoteReference ,
2022-08-27 11:52:29 +05:30
Frontmatter ,
2022-07-16 23:28:13 +05:30
HardBreak ,
Heading ,
HorizontalRule ,
Image ,
Italic ,
Link ,
ListItem ,
OrderedList ,
2022-08-27 11:52:29 +05:30
ReferenceDefinition ,
2022-07-16 23:28:13 +05:30
Sourcemap ,
2022-07-23 23:45:48 +05:30
Strike ,
Table ,
TableRow ,
TableHeader ,
TableCell ,
2022-10-11 01:57:18 +05:30
TableOfContents ,
2022-07-23 23:45:48 +05:30
TaskList ,
TaskItem ,
2022-10-11 01:57:18 +05:30
Video ,
2022-08-13 15:12:31 +05:30
... HTMLNodes ,
2022-07-16 23:28:13 +05:30
] ,
} ) ;
2022-07-23 23:45:48 +05:30
const {
builders : {
doc ,
paragraph ,
2022-10-11 01:57:18 +05:30
audio ,
2022-07-23 23:45:48 +05:30
bold ,
blockquote ,
bulletList ,
code ,
codeBlock ,
2022-08-13 15:12:31 +05:30
div ,
2022-10-11 01:57:18 +05:30
diagram ,
2022-07-23 23:45:48 +05:30
footnoteDefinition ,
footnoteReference ,
2022-08-27 11:52:29 +05:30
frontmatter ,
2022-07-23 23:45:48 +05:30
hardBreak ,
heading ,
horizontalRule ,
image ,
italic ,
link ,
listItem ,
orderedList ,
2022-08-13 15:12:31 +05:30
pre ,
2022-08-27 11:52:29 +05:30
referenceDefinition ,
2022-07-23 23:45:48 +05:30
strike ,
table ,
tableRow ,
tableHeader ,
tableCell ,
2022-10-11 01:57:18 +05:30
tableOfContents ,
2022-07-23 23:45:48 +05:30
taskItem ,
taskList ,
2022-10-11 01:57:18 +05:30
video ,
2022-07-23 23:45:48 +05:30
} ,
} = createDocBuilder ( {
tiptapEditor ,
names : {
2022-10-11 01:57:18 +05:30
audio : { nodeType : Audio . name } ,
2022-07-23 23:45:48 +05:30
blockquote : { nodeType : Blockquote . name } ,
bold : { markType : Bold . name } ,
bulletList : { nodeType : BulletList . name } ,
code : { markType : Code . name } ,
codeBlock : { nodeType : CodeBlockHighlight . name } ,
2022-10-11 01:57:18 +05:30
diagram : { nodeType : Diagram . name } ,
2022-07-23 23:45:48 +05:30
footnoteDefinition : { nodeType : FootnoteDefinition . name } ,
footnoteReference : { nodeType : FootnoteReference . name } ,
2022-08-27 11:52:29 +05:30
frontmatter : { nodeType : Frontmatter . name } ,
2022-07-23 23:45:48 +05:30
hardBreak : { nodeType : HardBreak . name } ,
heading : { nodeType : Heading . name } ,
horizontalRule : { nodeType : HorizontalRule . name } ,
image : { nodeType : Image . name } ,
italic : { nodeType : Italic . name } ,
link : { markType : Link . name } ,
listItem : { nodeType : ListItem . name } ,
orderedList : { nodeType : OrderedList . name } ,
paragraph : { nodeType : Paragraph . name } ,
2022-08-27 11:52:29 +05:30
referenceDefinition : { nodeType : ReferenceDefinition . name } ,
2022-07-23 23:45:48 +05:30
strike : { nodeType : Strike . name } ,
table : { nodeType : Table . name } ,
tableCell : { nodeType : TableCell . name } ,
tableHeader : { nodeType : TableHeader . name } ,
tableRow : { nodeType : TableRow . name } ,
2022-10-11 01:57:18 +05:30
tableOfContents : { nodeType : TableOfContents . name } ,
2022-07-23 23:45:48 +05:30
taskItem : { nodeType : TaskItem . name } ,
taskList : { nodeType : TaskList . name } ,
2022-10-11 01:57:18 +05:30
video : { nodeType : Video . name } ,
2022-08-13 15:12:31 +05:30
... HTMLNodes . reduce (
( builders , htmlNode ) => ( {
... builders ,
[ htmlNode . name ] : { nodeType : htmlNode . name } ,
} ) ,
{ } ,
) ,
2022-07-23 23:45:48 +05:30
} ,
} ) ;
2022-07-16 23:28:13 +05:30
describe ( 'Client side Markdown processing' , ( ) => {
2022-08-13 15:12:31 +05:30
const deserialize = async ( markdown ) => {
2022-07-16 23:28:13 +05:30
const { document } = await remarkMarkdownDeserializer ( ) . deserialize ( {
schema : tiptapEditor . schema ,
2022-08-13 15:12:31 +05:30
markdown ,
2022-07-16 23:28:13 +05:30
} ) ;
return document ;
} ;
const serialize = ( document ) =>
markdownSerializer ( { } ) . serialize ( {
doc : document ,
pristineDoc : document ,
} ) ;
2022-08-13 15:12:31 +05:30
const source = ( sourceMarkdown ) => ( {
sourceMapKey : expect . any ( String ) ,
2022-07-23 23:45:48 +05:30
sourceMarkdown ,
} ) ;
const examples = [
2022-07-16 23:28:13 +05:30
{
markdown : '__bold text__' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '__bold text__' ) , bold ( source ( '__bold text__' ) , 'bold text' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '**bold text**' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '**bold text**' ) , bold ( source ( '**bold text**' ) , 'bold text' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '<strong>bold text</strong>' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<strong>bold text</strong>' ) ,
bold ( source ( '<strong>bold text</strong>' ) , 'bold text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '<b>bold text</b>' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '<b>bold text</b>' ) , bold ( source ( '<b>bold text</b>' ) , 'bold text' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '_italic text_' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '_italic text_' ) , italic ( source ( '_italic text_' ) , 'italic text' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '*italic text*' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '*italic text*' ) , italic ( source ( '*italic text*' ) , 'italic text' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '<em>italic text</em>' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<em>italic text</em>' ) ,
italic ( source ( '<em>italic text</em>' ) , 'italic text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '<i>italic text</i>' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<i>italic text</i>' ) ,
italic ( source ( '<i>italic text</i>' ) , 'italic text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '`inline code`' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( '`inline code`' ) , code ( source ( '`inline code`' ) , 'inline code' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '**`inline code bold`**' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '**`inline code bold`**' ) ,
2022-07-23 23:45:48 +05:30
bold (
2022-08-13 15:12:31 +05:30
source ( '**`inline code bold`**' ) ,
code ( source ( '`inline code bold`' ) , 'inline code bold' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : '_`inline code italics`_' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '_`inline code italics`_' ) ,
2022-07-23 23:45:48 +05:30
italic (
2022-08-13 15:12:31 +05:30
source ( '_`inline code italics`_' ) ,
code ( source ( '`inline code italics`' ) , 'inline code italics' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
< i class = "foo" >
* bar *
< / i >
` ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<i class="foo">\n *bar*\n</i>' ) ,
italic ( source ( '<i class="foo">\n *bar*\n</i>' ) , '\n *bar*\n' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
} ,
{
markdown : `
< img src = "bar" alt = "foo" / >
` ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<img src="bar" alt="foo" />' ) ,
2022-08-27 11:52:29 +05:30
image ( {
... source ( '<img src="bar" alt="foo" />' ) ,
alt : 'foo' ,
canonicalSrc : 'bar' ,
src : 'bar' ,
} ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
2022-07-23 23:45:48 +05:30
markdown : `
- List item 1
< img src = "bar" alt = "foo" / >
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item 1' ) ,
listItem ( source ( '- List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<img src="bar" alt="foo" />' ) ,
2022-08-27 11:52:29 +05:30
image ( {
... source ( '<img src="bar" alt="foo" />' ) ,
alt : 'foo' ,
src : 'bar' ,
canonicalSrc : 'bar' ,
} ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '[GitLab](https://gitlab.com "Go to GitLab")' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '[GitLab](https://gitlab.com "Go to GitLab")' ) ,
2022-07-23 23:45:48 +05:30
link (
{
2022-08-13 15:12:31 +05:30
... source ( '[GitLab](https://gitlab.com "Go to GitLab")' ) ,
2022-07-23 23:45:48 +05:30
href : 'https://gitlab.com' ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'https://gitlab.com' ,
2022-07-23 23:45:48 +05:30
title : 'Go to GitLab' ,
} ,
'GitLab' ,
) ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '**[GitLab](https://gitlab.com "Go to GitLab")**' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '**[GitLab](https://gitlab.com "Go to GitLab")**' ) ,
2022-07-23 23:45:48 +05:30
bold (
2022-08-13 15:12:31 +05:30
source ( '**[GitLab](https://gitlab.com "Go to GitLab")**' ) ,
2022-07-23 23:45:48 +05:30
link (
{
2022-08-13 15:12:31 +05:30
... source ( '[GitLab](https://gitlab.com "Go to GitLab")' ) ,
2022-07-23 23:45:48 +05:30
href : 'https://gitlab.com' ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'https://gitlab.com' ,
2022-07-23 23:45:48 +05:30
title : 'Go to GitLab' ,
} ,
'GitLab' ,
) ,
) ,
) ,
) ,
} ,
{
markdown : 'www.commonmark.org' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'www.commonmark.org' ) ,
2022-07-23 23:45:48 +05:30
link (
{
2022-08-13 15:12:31 +05:30
... source ( 'www.commonmark.org' ) ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'http://www.commonmark.org' ,
2022-07-23 23:45:48 +05:30
href : 'http://www.commonmark.org' ,
} ,
'www.commonmark.org' ,
) ,
) ,
) ,
} ,
{
markdown : 'Visit www.commonmark.org/help for more information.' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'Visit www.commonmark.org/help for more information.' ) ,
2022-07-23 23:45:48 +05:30
'Visit ' ,
link (
{
2022-08-13 15:12:31 +05:30
... source ( 'www.commonmark.org/help' ) ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'http://www.commonmark.org/help' ,
2022-07-23 23:45:48 +05:30
href : 'http://www.commonmark.org/help' ,
} ,
'www.commonmark.org/help' ,
) ,
' for more information.' ,
) ,
) ,
} ,
{
markdown : 'hello@mail+xyz.example isn’ t valid, but hello+xyz@mail.example is.' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'hello@mail+xyz.example isn’ t valid, but hello+xyz@mail.example is.' ) ,
2022-07-23 23:45:48 +05:30
'hello@mail+xyz.example isn’ t valid, but ' ,
link (
{
2022-08-13 15:12:31 +05:30
... source ( 'hello+xyz@mail.example' ) ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'mailto:hello+xyz@mail.example' ,
2022-07-23 23:45:48 +05:30
href : 'mailto:hello+xyz@mail.example' ,
} ,
'hello+xyz@mail.example' ,
) ,
' is.' ,
) ,
) ,
} ,
{
markdown : '[https://gitlab.com>' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '[https://gitlab.com>' ) ,
2022-07-23 23:45:48 +05:30
'[' ,
link (
{
2022-08-13 15:12:31 +05:30
sourceMapKey : null ,
sourceMarkdown : null ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'https://gitlab.com' ,
2022-07-23 23:45:48 +05:30
href : 'https://gitlab.com' ,
} ,
'https://gitlab.com' ,
) ,
'>' ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
This is a paragraph with a \ \
hard line break ` ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'This is a paragraph with a\\\nhard line break' ) ,
2022-07-23 23:45:48 +05:30
'This is a paragraph with a' ,
2022-08-13 15:12:31 +05:30
hardBreak ( source ( '\\\n' ) ) ,
2022-07-23 23:45:48 +05:30
'\nhard line break' ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")' ,
2022-07-23 23:45:48 +05:30
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")' ) ,
2022-07-23 23:45:48 +05:30
image ( {
2022-08-13 15:12:31 +05:30
... source ( '![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")' ) ,
2022-07-23 23:45:48 +05:30
alt : 'GitLab Logo' ,
2022-08-27 11:52:29 +05:30
canonicalSrc : 'https://gitlab.com/logo.png' ,
2022-07-23 23:45:48 +05:30
src : 'https://gitlab.com/logo.png' ,
title : 'GitLab Logo' ,
} ) ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '---' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( horizontalRule ( source ( '---' ) ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '***' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( horizontalRule ( source ( '***' ) ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '___' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( horizontalRule ( source ( '___' ) ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '<hr>' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( horizontalRule ( source ( '<hr>' ) ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '# Heading 1' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '# Heading 1' ) , level : 1 } , 'Heading 1' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '## Heading 2' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '## Heading 2' ) , level : 2 } , 'Heading 2' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '### Heading 3' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '### Heading 3' ) , level : 3 } , 'Heading 3' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '#### Heading 4' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '#### Heading 4' ) , level : 4 } , 'Heading 4' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '##### Heading 5' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '##### Heading 5' ) , level : 5 } , 'Heading 5' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : '###### Heading 6' ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( '###### Heading 6' ) , level : 6 } , 'Heading 6' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
Heading
one
=== ===
` ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( 'Heading\none\n======' ) , level : 1 } , 'Heading\none' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
Heading
two
-- -- -- -
` ,
2022-08-13 15:12:31 +05:30
expectedDoc : doc ( heading ( { ... source ( 'Heading\ntwo\n-------' ) , level : 2 } , 'Heading\ntwo' ) ) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
- List item 1
- List item 2
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item 1\n- List item 2' ) ,
listItem ( source ( '- List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '- List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
* List item 1
* List item 2
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '* List item 1\n* List item 2' ) ,
listItem ( source ( '* List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '* List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
+ List item 1
+ List item 2
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '+ List item 1\n+ List item 2' ) ,
listItem ( source ( '+ List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '+ List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
1. List item 1
1. List item 2
` ,
expectedDoc : doc (
orderedList (
2022-08-13 15:12:31 +05:30
source ( '1. List item 1\n1. List item 2' ) ,
listItem ( source ( '1. List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '1. List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
1. List item 1
2. List item 2
` ,
expectedDoc : doc (
orderedList (
2022-08-13 15:12:31 +05:30
source ( '1. List item 1\n2. List item 2' ) ,
listItem ( source ( '1. List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '2. List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
1 ) List item 1
2 ) List item 2
` ,
expectedDoc : doc (
orderedList (
2022-08-13 15:12:31 +05:30
source ( '1) List item 1\n2) List item 2' ) ,
listItem ( source ( '1) List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '2) List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
- List item 1
- Sub list item 1
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item 1\n - Sub list item 1' ) ,
2022-07-23 23:45:48 +05:30
listItem (
2022-08-13 15:12:31 +05:30
source ( '- List item 1\n - Sub list item 1' ) ,
paragraph ( source ( 'List item 1' ) , 'List item 1' ) ,
2022-07-23 23:45:48 +05:30
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- Sub list item 1' ) ,
2022-07-23 23:45:48 +05:30
listItem (
2022-08-13 15:12:31 +05:30
source ( '- Sub list item 1' ) ,
paragraph ( source ( 'Sub list item 1' ) , 'Sub list item 1' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
- List item 1 paragraph 1
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
List item 1 paragraph 2
- List item 2
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item 1 paragraph 1\n\n List item 1 paragraph 2\n- List item 2' ) ,
2022-07-23 23:45:48 +05:30
listItem (
2022-08-13 15:12:31 +05:30
source ( '- List item 1 paragraph 1\n\n List item 1 paragraph 2' ) ,
paragraph ( source ( 'List item 1 paragraph 1' ) , 'List item 1 paragraph 1' ) ,
paragraph ( source ( 'List item 1 paragraph 2' ) , 'List item 1 paragraph 2' ) ,
2022-07-23 23:45:48 +05:30
) ,
2022-08-13 15:12:31 +05:30
listItem ( source ( '- List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
- List item with an image ! [ bar ] ( foo . png )
` ,
expectedDoc : doc (
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item with an image ![bar](foo.png)' ) ,
2022-07-23 23:45:48 +05:30
listItem (
2022-08-13 15:12:31 +05:30
source ( '- List item with an image ![bar](foo.png)' ) ,
2022-07-23 23:45:48 +05:30
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'List item with an image ![bar](foo.png)' ) ,
2022-07-23 23:45:48 +05:30
'List item with an image' ,
2022-08-27 11:52:29 +05:30
image ( {
... source ( '![bar](foo.png)' ) ,
alt : 'bar' ,
canonicalSrc : 'foo.png' ,
src : 'foo.png' ,
} ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
> This is a blockquote
` ,
expectedDoc : doc (
blockquote (
2022-08-13 15:12:31 +05:30
source ( '> This is a blockquote' ) ,
paragraph ( source ( 'This is a blockquote' ) , 'This is a blockquote' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
> - List item 1
> - List item 2
` ,
expectedDoc : doc (
blockquote (
2022-08-13 15:12:31 +05:30
source ( '> - List item 1\n> - List item 2' ) ,
2022-07-23 23:45:48 +05:30
bulletList (
2022-08-13 15:12:31 +05:30
source ( '- List item 1\n> - List item 2' ) ,
listItem ( source ( '- List item 1' ) , paragraph ( source ( 'List item 1' ) , 'List item 1' ) ) ,
listItem ( source ( '- List item 2' ) , paragraph ( source ( 'List item 2' ) , 'List item 2' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
code block
const fn = ( ) => 'GitLab' ;
` ,
expectedDoc : doc (
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'code block' ) , 'code block' ) ,
2022-07-23 23:45:48 +05:30
codeBlock (
{
2022-08-13 15:12:31 +05:30
... source ( " const fn = () => 'GitLab';" ) ,
2022-07-23 23:45:48 +05:30
class : 'code highlight' ,
language : null ,
} ,
"const fn = () => 'GitLab';" ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
\ ` \` \` javascript
const fn = ( ) => 'GitLab' ;
\ ` \` \` \
` ,
expectedDoc : doc (
codeBlock (
{
2022-08-13 15:12:31 +05:30
... source ( "```javascript\nconst fn = () => 'GitLab';\n```" ) ,
2022-07-23 23:45:48 +05:30
class : 'code highlight' ,
language : 'javascript' ,
} ,
"const fn = () => 'GitLab';" ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
~ ~ ~ javascript
const fn = ( ) => 'GitLab' ;
~ ~ ~
` ,
expectedDoc : doc (
codeBlock (
{
2022-08-13 15:12:31 +05:30
... source ( "~~~javascript\nconst fn = () => 'GitLab';\n~~~" ) ,
2022-07-23 23:45:48 +05:30
class : 'code highlight' ,
language : 'javascript' ,
} ,
"const fn = () => 'GitLab';" ,
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
{
markdown : `
2022-07-23 23:45:48 +05:30
\ ` \` \`
\ ` \` \` \
` ,
expectedDoc : doc (
codeBlock (
{
2022-08-13 15:12:31 +05:30
... source ( '```\n```' ) ,
2022-07-23 23:45:48 +05:30
class : 'code highlight' ,
language : null ,
} ,
'' ,
) ,
) ,
} ,
{
markdown : `
\ ` \` \` javascript
const fn = ( ) => 'GitLab' ;
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
\ ` \` \` \
` ,
expectedDoc : doc (
codeBlock (
{
2022-08-13 15:12:31 +05:30
... source ( "```javascript\nconst fn = () => 'GitLab';\n\n```" ) ,
2022-07-23 23:45:48 +05:30
class : 'code highlight' ,
language : 'javascript' ,
} ,
"const fn = () => 'GitLab';\n" ,
) ,
) ,
} ,
{
markdown : '~~Strikedthrough text~~' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '~~Strikedthrough text~~' ) ,
strike ( source ( '~~Strikedthrough text~~' ) , 'Strikedthrough text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
} ,
{
markdown : '<del>Strikedthrough text</del>' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<del>Strikedthrough text</del>' ) ,
strike ( source ( '<del>Strikedthrough text</del>' ) , 'Strikedthrough text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
} ,
{
markdown : '<strike>Strikedthrough text</strike>' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<strike>Strikedthrough text</strike>' ) ,
strike ( source ( '<strike>Strikedthrough text</strike>' ) , 'Strikedthrough text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
} ,
{
markdown : '<s>Strikedthrough text</s>' ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( '<s>Strikedthrough text</s>' ) ,
strike ( source ( '<s>Strikedthrough text</s>' ) , 'Strikedthrough text' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
2022-07-16 23:28:13 +05:30
} ,
2022-07-23 23:45:48 +05:30
{
markdown : `
- [ ] task list item 1
- [ ] task list item 2
` ,
expectedDoc : doc (
taskList (
{
numeric : false ,
2022-08-13 15:12:31 +05:30
... source ( '- [ ] task list item 1\n- [ ] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
taskItem (
{
checked : false ,
2022-08-13 15:12:31 +05:30
... source ( '- [ ] task list item 1' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 1' ) , 'task list item 1' ) ,
2022-07-23 23:45:48 +05:30
) ,
taskItem (
{
checked : false ,
2022-08-13 15:12:31 +05:30
... source ( '- [ ] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 2' ) , 'task list item 2' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
- [ x ] task list item 1
- [ x ] task list item 2
` ,
expectedDoc : doc (
taskList (
{
numeric : false ,
2022-08-13 15:12:31 +05:30
... source ( '- [x] task list item 1\n- [x] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
taskItem (
{
checked : true ,
2022-08-13 15:12:31 +05:30
... source ( '- [x] task list item 1' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 1' ) , 'task list item 1' ) ,
2022-07-23 23:45:48 +05:30
) ,
taskItem (
{
checked : true ,
2022-08-13 15:12:31 +05:30
... source ( '- [x] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 2' ) , 'task list item 2' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
1. [ ] task list item 1
2. [ ] task list item 2
` ,
expectedDoc : doc (
taskList (
{
numeric : true ,
2022-08-13 15:12:31 +05:30
... source ( '1. [ ] task list item 1\n2. [ ] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
taskItem (
{
checked : false ,
2022-08-13 15:12:31 +05:30
... source ( '1. [ ] task list item 1' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 1' ) , 'task list item 1' ) ,
2022-07-23 23:45:48 +05:30
) ,
taskItem (
{
checked : false ,
2022-08-13 15:12:31 +05:30
... source ( '2. [ ] task list item 2' ) ,
2022-07-23 23:45:48 +05:30
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'task list item 2' ) , 'task list item 2' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
| a | b |
| -- - | -- - |
| c | d |
` ,
expectedDoc : doc (
table (
2022-08-13 15:12:31 +05:30
source ( '| a | b |\n|---|---|\n| c | d |' ) ,
2022-07-23 23:45:48 +05:30
tableRow (
2022-08-13 15:12:31 +05:30
source ( '| a | b |' ) ,
tableHeader ( source ( '| a |' ) , paragraph ( source ( 'a' ) , 'a' ) ) ,
tableHeader ( source ( ' b |' ) , paragraph ( source ( 'b' ) , 'b' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
tableRow (
2022-08-13 15:12:31 +05:30
source ( '| c | d |' ) ,
tableCell ( source ( '| c |' ) , paragraph ( source ( 'c' ) , 'c' ) ) ,
tableCell ( source ( ' d |' ) , paragraph ( source ( 'd' ) , 'd' ) ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
< table >
< tr >
< th colspan = "2" rowspan = "5" > Header < / t h >
< / t r >
< tr >
< td colspan = "2" rowspan = "5" > Body < / t d >
< / t r >
< / t a b l e >
` ,
expectedDoc : doc (
table (
2022-08-13 15:12:31 +05:30
source (
2022-07-23 23:45:48 +05:30
'<table>\n <tr>\n <th colspan="2" rowspan="5">Header</th>\n </tr>\n <tr>\n <td colspan="2" rowspan="5">Body</td>\n </tr>\n</table>' ,
) ,
tableRow (
2022-08-13 15:12:31 +05:30
source ( '<tr>\n <th colspan="2" rowspan="5">Header</th>\n </tr>' ) ,
2022-07-23 23:45:48 +05:30
tableHeader (
{
2022-08-13 15:12:31 +05:30
... source ( '<th colspan="2" rowspan="5">Header</th>' ) ,
2022-07-23 23:45:48 +05:30
colspan : 2 ,
rowspan : 5 ,
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'Header' ) , 'Header' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
tableRow (
2022-08-13 15:12:31 +05:30
source ( '<tr>\n <td colspan="2" rowspan="5">Body</td>\n </tr>' ) ,
2022-07-23 23:45:48 +05:30
tableCell (
{
2022-08-13 15:12:31 +05:30
... source ( '<td colspan="2" rowspan="5">Body</td>' ) ,
2022-07-23 23:45:48 +05:30
colspan : 2 ,
rowspan : 5 ,
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'Body' ) , 'Body' ) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
) ,
) ,
} ,
{
markdown : `
This is a footnote [ ^ footnote ]
Paragraph
[ ^ footnote ] : Footnote definition
Paragraph
` ,
expectedDoc : doc (
paragraph (
2022-08-13 15:12:31 +05:30
source ( 'This is a footnote [^footnote]' ) ,
2022-07-23 23:45:48 +05:30
'This is a footnote ' ,
footnoteReference ( {
2022-08-13 15:12:31 +05:30
... source ( '[^footnote]' ) ,
2022-07-23 23:45:48 +05:30
identifier : 'footnote' ,
label : 'footnote' ,
} ) ,
) ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'Paragraph' ) , 'Paragraph' ) ,
2022-07-23 23:45:48 +05:30
footnoteDefinition (
{
2022-08-13 15:12:31 +05:30
... source ( '[^footnote]: Footnote definition' ) ,
2022-07-23 23:45:48 +05:30
identifier : 'footnote' ,
label : 'footnote' ,
} ,
2022-08-13 15:12:31 +05:30
paragraph ( source ( 'Footnote definition' ) , 'Footnote definition' ) ,
) ,
paragraph ( source ( 'Paragraph' ) , 'Paragraph' ) ,
) ,
} ,
{
markdown : `
< div > div < / d i v >
` ,
expectedDoc : doc ( div ( source ( '<div>div</div>' ) , paragraph ( source ( 'div' ) , 'div' ) ) ) ,
} ,
{
markdown : `
[ ! [ moon ] ( moon . jpg ) ] ( / u r i )
` ,
expectedDoc : doc (
paragraph (
source ( '[![moon](moon.jpg)](/uri)' ) ,
link (
2022-08-27 11:52:29 +05:30
{
... source ( '[![moon](moon.jpg)](/uri)' ) ,
canonicalSrc : '/uri' ,
href : '/uri' ,
} ,
image ( {
... source ( '![moon](moon.jpg)' ) ,
canonicalSrc : 'moon.jpg' ,
src : 'moon.jpg' ,
alt : 'moon' ,
} ) ,
2022-08-13 15:12:31 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
< del >
* foo *
< / d e l >
` ,
expectedDoc : doc (
paragraph (
source ( '*foo*' ) ,
strike ( source ( '<del>\n\n*foo*\n\n</del>' ) , italic ( source ( '*foo*' ) , 'foo' ) ) ,
) ,
) ,
expectedMarkdown : '*foo*' ,
} ,
{
markdown : `
~ [ moon ] ( moon . jpg ) and [ sun ] ( sun . jpg ) ~
` ,
expectedDoc : doc (
paragraph (
source ( '~[moon](moon.jpg) and [sun](sun.jpg)~' ) ,
strike (
source ( '~[moon](moon.jpg) and [sun](sun.jpg)~' ) ,
2022-08-27 11:52:29 +05:30
link (
{
... source ( '[moon](moon.jpg)' ) ,
canonicalSrc : 'moon.jpg' ,
href : 'moon.jpg' ,
} ,
'moon' ,
) ,
2022-08-13 15:12:31 +05:30
) ,
strike ( source ( '~[moon](moon.jpg) and [sun](sun.jpg)~' ) , ' and ' ) ,
strike (
source ( '~[moon](moon.jpg) and [sun](sun.jpg)~' ) ,
2022-08-27 11:52:29 +05:30
link (
{
... source ( '[sun](sun.jpg)' ) ,
href : 'sun.jpg' ,
canonicalSrc : 'sun.jpg' ,
} ,
'sun' ,
) ,
2022-08-13 15:12:31 +05:30
) ,
) ,
) ,
} ,
{
markdown : `
< del >
* * Paragraph 1 * *
_Paragraph 2_
< / d e l >
` ,
expectedDoc : doc (
paragraph (
source ( '**Paragraph 1**' ) ,
strike (
source ( '<del>\n\n**Paragraph 1**\n\n_Paragraph 2_\n\n</del>' ) ,
bold ( source ( '**Paragraph 1**' ) , 'Paragraph 1' ) ,
) ,
) ,
paragraph (
source ( '_Paragraph 2_' ) ,
strike (
source ( '<del>\n\n**Paragraph 1**\n\n_Paragraph 2_\n\n</del>' ) ,
italic ( source ( '_Paragraph 2_' ) , 'Paragraph 2' ) ,
) ,
) ,
) ,
expectedMarkdown : ` **Paragraph 1**
_Paragraph 2_ ` ,
} ,
/ * T O D O
* Implement proper editing support for HTML comments in the Content Editor
* https : //gitlab.com/gitlab-org/gitlab/-/issues/342173
* /
{
markdown : '<!-- HTML comment -->' ,
expectedDoc : doc ( paragraph ( ) ) ,
expectedMarkdown : '' ,
} ,
{
markdown : `
< ! [ CDATA [
function matchwo ( a , b )
{
if ( a < b && a < 0 ) then {
return 1 ;
} else {
return 0 ;
}
}
] ] >
` ,
expectedDoc : doc ( paragraph ( ) ) ,
expectedMarkdown : '' ,
} ,
{
markdown : `
<!-- foo -- > * bar *
* baz *
` ,
expectedDoc : doc (
paragraph ( source ( '*bar*' ) , '*bar*\n' ) ,
paragraph ( source ( '*baz*' ) , italic ( source ( '*baz*' ) , 'baz' ) ) ,
) ,
expectedMarkdown : ` *bar*
* baz * ` ,
} ,
{
markdown : `
< table > < tr > < td >
< pre >
* * Hello * * ,
_world _ .
< / p r e >
< / t d > < / t r > < / t a b l e >
` ,
expectedDoc : doc (
table (
source ( '<table><tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr></table>' ) ,
tableRow (
source ( '<tr><td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td></tr>' ) ,
tableCell (
source ( '<td>\n<pre>\n**Hello**,\n\n_world_.\n</pre>\n</td>' ) ,
pre (
source ( '<pre>\n**Hello**,\n\n_world_.\n</pre>' ) ,
paragraph ( source ( '**Hello**,' ) , '**Hello**,\n' ) ,
paragraph ( source ( '_world_.\n' ) , italic ( source ( '_world_' ) , 'world' ) , '.\n' ) ,
) ,
paragraph ( ) ,
) ,
) ,
2022-07-23 23:45:48 +05:30
) ,
) ,
} ,
2022-08-27 11:52:29 +05:30
{
markdown : `
[ GitLab ] [ gitlab - url ]
[ gitlab - url ] : https : //gitlab.com "GitLab"
` ,
expectedDoc : doc (
paragraph (
source ( '[GitLab][gitlab-url]' ) ,
link (
{
... source ( '[GitLab][gitlab-url]' ) ,
href : 'https://gitlab.com' ,
canonicalSrc : 'gitlab-url' ,
title : 'GitLab' ,
isReference : true ,
} ,
'GitLab' ,
) ,
) ,
referenceDefinition (
{
... source ( '[gitlab-url]: https://gitlab.com "GitLab"' ) ,
identifier : 'gitlab-url' ,
url : 'https://gitlab.com' ,
title : 'GitLab' ,
} ,
'[gitlab-url]: https://gitlab.com "GitLab"' ,
) ,
) ,
} ,
{
markdown : `
! [ GitLab Logo ] [ gitlab - logo ]
[ gitlab - logo ] : https : //gitlab.com/gitlab-logo.png "GitLab Logo"
` ,
expectedDoc : doc (
paragraph (
source ( '![GitLab Logo][gitlab-logo]' ) ,
image ( {
... source ( '![GitLab Logo][gitlab-logo]' ) ,
src : 'https://gitlab.com/gitlab-logo.png' ,
canonicalSrc : 'gitlab-logo' ,
alt : 'GitLab Logo' ,
title : 'GitLab Logo' ,
isReference : true ,
} ) ,
) ,
referenceDefinition (
{
... source ( '[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"' ) ,
identifier : 'gitlab-logo' ,
url : 'https://gitlab.com/gitlab-logo.png' ,
title : 'GitLab Logo' ,
} ,
'[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"' ,
) ,
) ,
} ,
{
markdown : `
-- -
title : 'layout'
-- -
` ,
expectedDoc : doc (
frontmatter (
{ ... source ( "---\ntitle: 'layout'\n---" ) , language : 'yaml' } ,
"title: 'layout'" ,
) ,
) ,
} ,
{
markdown : `
++ +
title : 'layout'
++ +
` ,
expectedDoc : doc (
frontmatter (
{ ... source ( "+++\ntitle: 'layout'\n+++" ) , language : 'toml' } ,
"title: 'layout'" ,
) ,
) ,
} ,
{
markdown : `
; ; ;
{ title : 'layout' }
; ; ;
` ,
expectedDoc : doc (
frontmatter (
{ ... source ( ";;;\n{ title: 'layout' }\n;;;" ) , language : 'json' } ,
"{ title: 'layout' }" ,
) ,
) ,
} ,
2022-10-11 01:57:18 +05:30
... SAFE _AUDIO _EXT . map ( ( extension ) => {
const src = ` http://test.host/video. ${ extension } ` ;
const markdown = ` ![audio]( ${ src } ) ` ;
return {
markdown ,
expectedDoc : doc (
paragraph (
source ( markdown ) ,
audio ( {
... source ( markdown ) ,
canonicalSrc : src ,
src ,
alt : 'audio' ,
} ) ,
) ,
) ,
} ;
} ) ,
... SAFE _VIDEO _EXT . map ( ( extension ) => {
const src = ` http://test.host/video. ${ extension } ` ;
const markdown = ` ![video]( ${ src } ) ` ;
return {
markdown ,
expectedDoc : doc (
paragraph (
source ( markdown ) ,
video ( {
... source ( markdown ) ,
canonicalSrc : src ,
src ,
alt : 'video' ,
} ) ,
) ,
) ,
} ;
} ) ,
... DIAGRAM _LANGUAGES . map ( ( language ) => {
const markdown = ` \` \` \` ${ language }
content
\ ` \` \` ` ;
return {
markdown ,
expectedDoc : doc ( diagram ( { ... source ( markdown ) , language } , 'content' ) ) ,
} ;
} ) ,
{
markdown : '[[_TOC_]]' ,
expectedDoc : doc ( tableOfContents ( source ( '[[_TOC_]]' ) ) ) ,
} ,
{
markdown : '[TOC]' ,
expectedDoc : doc ( tableOfContents ( source ( '[TOC]' ) ) ) ,
} ,
2022-07-23 23:45:48 +05:30
] ;
const runOnly = examples . find ( ( example ) => example . only === true ) ;
const runExamples = runOnly ? [ runOnly ] : examples ;
2022-08-13 15:12:31 +05:30
it . each ( runExamples ) (
'processes %s correctly' ,
async ( { markdown , expectedDoc , expectedMarkdown } ) => {
const trimmed = markdown . trim ( ) ;
const document = await deserialize ( trimmed ) ;
2022-07-16 23:28:13 +05:30
2022-08-27 11:52:29 +05:30
expect ( expectedDoc ) . not . toBe ( false ) ;
2022-08-13 15:12:31 +05:30
expect ( document . toJSON ( ) ) . toEqual ( expectedDoc . toJSON ( ) ) ;
expect ( serialize ( document ) ) . toEqual ( expectedMarkdown ? ? trimmed ) ;
} ,
) ;
/ * *
* DISCLAIMER : THIS IS A SECURITY ORIENTED TEST THAT ENSURES
* THE CLIENT - SIDE PARSER IGNORES DANGEROUS TAGS THAT ARE NOT
* EXPLICITELY SUPPORTED .
*
* PLEASE CONSIDER THIS INFORMATION WHILE MODIFYING THESE TESTS
* /
it . each ( [
{
markdown : `
< script >
alert ( "Hello world" )
< / s c r i p t >
` ,
expectedHtml : '<p></p>' ,
} ,
{
markdown : `
< foo > Hello < / f o o >
` ,
expectedHtml : '<p></p>' ,
} ,
{
markdown : `
< h1 class = "heading-with-class" > Header < / h 1 >
` ,
expectedHtml : '<h1>Header</h1>' ,
} ,
{
markdown : `
< a id = "link-id" > Header < / a > a n d o t h e r t e x t
` ,
expectedHtml :
'<p><a target="_blank" rel="noopener noreferrer nofollow">Header</a> and other text</p>' ,
} ,
{
markdown : `
< style >
body {
display : none ;
}
< / s t y l e >
` ,
expectedHtml : '<p></p>' ,
} ,
{
markdown : '<div style="transform">div</div>' ,
expectedHtml : '<div><p>div</p></div>' ,
} ,
] ) (
'removes unknown tags and unsupported attributes from HTML output' ,
async ( { markdown , expectedHtml } ) => {
const document = await deserialize ( markdown ) ;
tiptapEditor . commands . setContent ( document . toJSON ( ) ) ;
expect ( tiptapEditor . getHTML ( ) ) . toEqual ( expectedHtml ) ;
} ,
) ;
2022-08-27 11:52:29 +05:30
describe ( 'attribute sanitization' , ( ) => {
// eslint-disable-next-line no-script-url
const protocolBasedInjectionSimpleNoSpaces = "javascript:alert('XSS');" ;
// eslint-disable-next-line no-script-url
const protocolBasedInjectionSimpleSpacesBefore = "javascript: alert('XSS');" ;
const docWithImageFactory = ( urlInput , urlOutput ) => {
const input = ` <img src=" ${ urlInput } "> ` ;
return {
input ,
expectedDoc : doc (
paragraph (
source ( input ) ,
image ( {
... source ( input ) ,
src : urlOutput ,
canonicalSrc : urlOutput ,
} ) ,
) ,
) ,
} ;
} ;
const docWithLinkFactory = ( urlInput , urlOutput ) => {
const input = ` <a href=" ${ urlInput } ">foo</a> ` ;
return {
input ,
expectedDoc : doc (
paragraph (
source ( input ) ,
link ( { ... source ( input ) , href : urlOutput , canonicalSrc : urlOutput } , 'foo' ) ,
) ,
) ,
} ;
} ;
it . each `
desc | urlInput | urlOutput
$ { 'protocol-based JS injection: simple, no spaces' } | $ { protocolBasedInjectionSimpleNoSpaces } | $ { null }
$ { 'protocol-based JS injection: simple, spaces before' } | $ { "javascript :alert('XSS');" } | $ { null }
$ { 'protocol-based JS injection: simple, spaces after' } | $ { protocolBasedInjectionSimpleSpacesBefore } | $ { null }
$ { 'protocol-based JS injection: simple, spaces before and after' } | $ { "javascript : alert('XSS');" } | $ { null }
$ { 'protocol-based JS injection: UTF-8 encoding' } | $ { 'javascript:' } | $ { null }
$ { 'protocol-based JS injection: long UTF-8 encoding' } | $ { 'javascript:' } | $ { null }
$ { 'protocol-based JS injection: long UTF-8 encoding without semicolons' } | $ { 'javascript:alert('XSS')' } | $ { null }
$ { 'protocol-based JS injection: hex encoding' } | $ { 'javascript:' } | $ { null }
$ { 'protocol-based JS injection: long hex encoding' } | $ { 'javascript:' } | $ { null }
$ { 'protocol-based JS injection: hex encoding without semicolons' } | $ { 'javascript:alert('XSS')' } | $ { null }
$ { 'protocol-based JS injection: Unicode' } | $ { "\u0001java\u0003script:alert('XSS')" } | $ { null }
$ { 'protocol-based JS injection: spaces and entities' } | $ { " javascript:alert('XSS');" } | $ { null }
$ { 'vbscript' } | $ { 'vbscript:alert(document.domain)' } | $ { null }
$ { 'protocol-based JS injection: preceding colon' } | $ { ":javascript:alert('XSS');" } | $ { ":javascript:alert('XSS');" }
$ { 'protocol-based JS injection: null char' } | $ { "java\0script:alert('XSS')" } | $ { "java<76> script:alert('XSS')" }
$ { 'protocol-based JS injection: invalid URL char' } | $ { "java\\script:alert('XSS')" } | $ { "java\\script:alert('XSS')" }
` ('sanitize $ desc: \n \t URL " $ urlInput" becomes " $ urlOutput"', ({ urlInput, urlOutput }) => {
const exampleFactories = [ docWithImageFactory , docWithLinkFactory ] ;
exampleFactories . forEach ( async ( exampleFactory ) => {
const { input , expectedDoc } = exampleFactory ( urlInput , urlOutput ) ;
const document = await deserialize ( input ) ;
expect ( document . toJSON ( ) ) . toEqual ( expectedDoc . toJSON ( ) ) ;
} ) ;
} ) ;
} ) ;
2022-07-16 23:28:13 +05:30
} ) ;