import { run } from './run'; import { parse } from './parse'; import { Input } from '../parser/context'; import { html } from 'typed-dom/dom'; import { normalize } from '../debug.test'; describe('Unit: api/parse', () => { describe('parse', () => { it('result', () => { assert(run(parse('')) instanceof DocumentFragment); }); it('empty', () => { assert.deepStrictEqual( [...run(parse('')).children].map(el => el.outerHTML), ['
    ']); }); it('invisible', () => { assert.deepStrictEqual( [...run(parse(' ')).children].map(el => el.outerHTML), ['
      ']); assert.deepStrictEqual( [...run(parse('\n')).children].map(el => el.outerHTML), ['
        ']); assert.deepStrictEqual( [...run(parse('\n\n')).children].map(el => el.outerHTML), ['
          ']); assert.deepStrictEqual( [...run(parse('\\')).children].map(el => el.outerHTML), ['

          \\

          ', '
            ']); assert.deepStrictEqual( [...run(parse('\\\na')).children].map(el => el.outerHTML), ['

            \\
            a

            ', '
              ']); assert.deepStrictEqual( [...run(parse(' ')).children].map(el => el.outerHTML), ['

              	

              ', '
                ']); assert.deepStrictEqual( [...run(parse(' \na')).children].map(el => el.outerHTML), ['

                	
                a

                ', '
                  ']); assert.deepStrictEqual( [...run(parse('')).children].map(el => el.outerHTML), ['

                  <wbr>

                  ', '
                    ']); assert.deepStrictEqual( [...run(parse('\na')).children].map(el => el.outerHTML), ['

                    <wbr>
                    a

                    ', '
                      ']); assert.deepStrictEqual( [...run(parse('[%\n\n%]')).children].map(el => el.outerHTML), ['

                      [%
                      <wbr>
                      %]

                      ', '
                        ']); assert.deepStrictEqual( [...run(parse('[%\n\n%]\na')).children].map(el => el.outerHTML), ['

                        [%
                        <wbr>
                        %]

                        a

                        ', '
                          ']); }); it('linebreak', () => { assert.deepStrictEqual( [...run(parse('\\ ')).children].map(el => el.outerHTML), ['

                          \\

                          ', '
                            ']); assert.deepStrictEqual( [...run(parse('\\\n')).children].map(el => el.outerHTML), ['

                            \\

                            ', '
                              ']); assert.deepStrictEqual( [...run(parse('a\\ \nb')).children].map(el => el.outerHTML), ['

                              a
                              b

                              ', '
                                ']); assert.deepStrictEqual( [...run(parse('a\\\nb')).children].map(el => el.outerHTML), ['

                                a
                                b

                                ', '
                                  ']); assert.deepStrictEqual( [...run(parse('a\n\\ \nb')).children].map(el => el.outerHTML), ['

                                  a
                                  \\
                                  b

                                  ', '
                                    ']); assert.deepStrictEqual( [...run(parse('a\n\\\nb')).children].map(el => el.outerHTML), ['

                                    a
                                    \\
                                    b

                                    ', '
                                      ']); }); it('indent', () => { assert.deepStrictEqual( [...run(parse('\ta')).children].map(el => el.outerHTML), ['

                                      \ta

                                      ', '
                                        ']); }); it('url', () => { assert.deepStrictEqual( [...run(parse([ [ '---', 'URL: https://source/x/y', '---', ].join('\n'), '@a', '@domain/a', '@a#b', '@domain/a#b', '#a', '[#a]', '$-a\n$$\n$$', '$-a', '((a))', '{a}', '{/a}', '{^/a}', '{./a}', '{../a}', '{../../a}', '{//domain/a}', '!{a}', '!{^/a}', '!{../../a}', ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => el.outerHTML), [ '', '

                                        @a

                                        ', '

                                        @domain/a

                                        ', '

                                        @a#b

                                        ', '

                                        @domain/a#b

                                        ', '

                                        #a

                                        ', '

                                        a

                                        ', '
                                        (1)
                                        $$\n$$
                                        ', '

                                        (1)

                                        ', '

                                        *1

                                        ', '

                                        a

                                        ', '

                                        /a

                                        ', '

                                        ^/a

                                        ', '

                                        ./a

                                        ', '

                                        ../a

                                        ', '

                                        ../../a

                                        ', '

                                        //domain/a

                                        ', '
                                        a
                                        ', '
                                        ^/a
                                        ', '
                                        ../../a
                                        ', '
                                        1. a^1
                                        ', '
                                          ', ]); assert.deepStrictEqual( [...run(parse([ [ '---', 'URL: https://source/x/y', '---', ].join('\n'), '{^/a}', '{./a}', ].join('\n\n'), { host: new URL(`${location.origin}/index.md`) })).children].map(el => el.outerHTML), [ '', '

                                          ^/a

                                          ', '

                                          ./a

                                          ', '
                                            ', ]); assert.deepStrictEqual( [...run(parse([ [ '---', `URL: ${location.origin}/x/y`, '---', ].join('\n'), '{^/a}', '{./a}', ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => el.outerHTML), [ ``, '

                                            ^/a

                                            ', '

                                            ./a

                                            ', '
                                              ', ]); }); it('separation', () => { assert.deepStrictEqual( [...run(parse([ [ '---', 'URL: https://example/x', '---', ].join('\n'), [ '---', 'URL: https://example/y', '---', ].join('\n'), [ '~~~example/markdown', '---', 'URL: https://example/y', '---', '', '{#}', '~~~', ].join('\n'), '{#}', ].join('\n\n'), { host: new URL(`${location.origin}/z`) })).children].map(el => normalize(el.outerHTML)), [ ``, '
                                              ---\nURL: https://example/y\n---\n
                                              ', '', '

                                              #

                                              ', '
                                                ', ]); }); it('note', () => { const notes = { references: html('ol') }; assert.deepStrictEqual( [...run(parse('$-a\n$$\n$$\n\n(($-a[[^B]]))[[^B|$-a]]', { notes })).children].map(el => el.outerHTML), [ '
                                                (1)
                                                $$\n$$
                                                ', '

                                                *1[B]

                                                ', '
                                                1. (1)[B]^1
                                                ', ]); assert.deepStrictEqual( notes.references.outerHTML, '
                                                1. (1)^1^2
                                                '); assert.deepStrictEqual( [...run(parse([ '[[^A 1|b]]', '[[^A 1,|b]]', '[[^A 1, |b]]', '[[^Xyz 2020|b]]', '[[^Xyz 2020, 1|b]]', '[[^Xyz 2020, 1, 2|b]]', '[[^Xyz 2020, 1, fig. 1.1|b]]', '[[^Xyz 2020, 1, fig. 1.1-2.1b|b]]', '[[^Xyz 2020, 1, fig. 1.1a-b|b]]', '[[^Xyz 2020, 1-2|b]]', '[[^Xyz 2020, 1:1-2|b]]', '[[^Xyz 2020, 1n|b]]', '[[^Xyz 2020, 1n1|b]]', '[[^Xyz 2020, 1nn1-2|b]]', '[[^Xyz 2020, i|b]]', '[[^Xyz 2020, capter 1|b]]', '[[^Xyz 2020, cap. 1|b]]', '[[^Xyz 2020a|b]]', '[[^Xyz 2020a, 1|b]]', '[[^Xyz 2020-2021a|b]]', '[[^Xyz 2020-2021a, 1|b]]', '[[^Xyz, April 1, 2020|b]]', '[[^Xyz, April 1, 2020, 1|b]]', '[[^Xyz n.d.|b]]', '[[^Xyz n.d., 1|b]]', '[[^X. Y., and Z et al. 2020, 1-2|b]]', '[[^A title 2020|b]]', '[[^A title 2020, 1|b]]', '[[^Constitution, art. 2|b]]', '[[^Constitution, art. 2, sec. 1|b]]', ].join('\n\n'), { notes })).children].map(el => el.outerHTML), [ '

                                                [A 1]

                                                ', '

                                                [A 1,]

                                                ', '

                                                [A 1,]

                                                ', '

                                                [Xyz 2020]

                                                ', '

                                                [Xyz 2020, 1]

                                                ', '

                                                [Xyz 2020, 1, 2]

                                                ', '

                                                [Xyz 2020, 1, fig. 1.1]

                                                ', '

                                                [Xyz 2020, 1, fig. 1.1-2.1b]

                                                ', '

                                                [Xyz 2020, 1, fig. 1.1a-b]

                                                ', '

                                                [Xyz 2020, 1-2]

                                                ', '

                                                [Xyz 2020, 1:1-2]

                                                ', '

                                                [Xyz 2020, 1n]

                                                ', '

                                                [Xyz 2020, 1n1]

                                                ', '

                                                [Xyz 2020, 1nn1-2]

                                                ', '

                                                [Xyz 2020, i]

                                                ', '

                                                [Xyz 2020, capter 1]

                                                ', '

                                                [Xyz 2020, cap. 1]

                                                ', '

                                                [Xyz 2020a]

                                                ', '

                                                [Xyz 2020a, 1]

                                                ', '

                                                [Xyz 2020-2021a]

                                                ', '

                                                [Xyz 2020-2021a, 1]

                                                ', '

                                                [Xyz, April 1, 2020]

                                                ', '

                                                [Xyz, April 1, 2020, 1]

                                                ', '

                                                [Xyz n.d.]

                                                ', '

                                                [Xyz n.d., 1]

                                                ', '

                                                [X. Y., and Z et al. 2020, 1-2]

                                                ', '

                                                [A title 2020]

                                                ', '

                                                [A title 2020, 1]

                                                ', '

                                                [Constitution, art. 2]

                                                ', '

                                                [Constitution, art. 2, sec. 1]

                                                ', ]); }); it('normalize', () => { assert.deepStrictEqual( [...run(parse('a\\\r\nb')).children].map(el => el.outerHTML), ['

                                                a
                                                b

                                                ', '
                                                  ']); }); it('recursion', () => { assert.deepStrictEqual( [...run(parse(`${'('.repeat(100)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'('.repeat(101)}0`)).children].map(el => el.tagName), ['H1', 'PRE', 'OL']); assert.deepStrictEqual( [...run(parse(`${'['.repeat(100)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'['.repeat(101)}0`)).children].map(el => el.tagName), ['H1', 'PRE', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{'.repeat(102)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{'.repeat(103)}0`)).children].map(el => el.tagName), ['H1', 'PRE', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{ '.repeat(100)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{ '.repeat(1000)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{ '.repeat(100)}0`)).children].map(el => el.tagName), ['P', 'OL']); assert.deepStrictEqual( [...run(parse(`${'{ '.repeat(101)}0`)).children].map(el => el.tagName), ['H1', 'PRE', 'OL']); }); it('recovery', () => { assert.deepStrictEqual( [...run(parse(`${'('.repeat(101)}0\n\n*a*`)).children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')), [ '

                                                  Error: Too much recursion

                                                  ', `
                                                  ${'('.repeat(101)}0\n
                                                  `, '

                                                  a

                                                  ', '
                                                    ', ]); }); it('creation', () => { assert.deepStrictEqual( [...run(parse('.'.repeat(100000), {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.outerHTML), [`

                                                    ${'.'.repeat(100000)}

                                                    `, '
                                                      ']); }); it('creation error', () => { assert.deepStrictEqual( [...run(parse('.'.repeat(100001), {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.outerHTML.replace(/:\w+/, ':rnd')), [ '

                                                      Error: Too many creations

                                                      ', `
                                                      ${'.'.repeat(1000 - 3)}...
                                                      `, '
                                                        ', ]); }); it('backtrack 1', () => { // 最悪計算量での実行速度はCommonMarkの公式JS実装の32nに対して1-4倍程度。 // 5n = reference + link + url/math + ruby + text assert.deepStrictEqual( [...run(parse(`((([[[[#$http://[${'.'.repeat(19983)}`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.tagName), ['P', 'OL']); }); it('backtrack 1 error', () => { assert.deepStrictEqual( [...run(parse(`((([[[[#$http://[${'.'.repeat(19983 + 1)}`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.tagName), ['H1', 'PRE', 'OL']); }); it('backtrack 2', () => { assert.deepStrictEqual( [...run(parse(`((([[[[#$http://[${'.'.repeat(33313)}]]]`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.tagName), ['P', 'OL']); }); it('backtrack 2 error', () => { assert.deepStrictEqual( [...run(parse(`((([[[[#$http://[${'.'.repeat(33313 + 1)}]]]`, {}, new Input({ resources: { clock: 100000, recursions: [100] } }))).children] .map(el => el.tagName), ['H1', 'PRE', 'OL']); }); }); });