diff --git a/packages/contenttype-commonmark/src/index.ts b/packages/contenttype-commonmark/src/index.ts index 06fb8226b..86033cb22 100644 --- a/packages/contenttype-commonmark/src/index.ts +++ b/packages/contenttype-commonmark/src/index.ts @@ -15,23 +15,30 @@ const TAG_MAP: { [tagName: string]: string } = { const HANDLERS = { 'hardbreak': (state, token) => { + state.content += '\n'; state.annotations.push({ type: token.tag, - start: state.content.length, + start: state.content.length - 1, end: state.content.length, attributes: {} }); - state.content += '\n'; }, 'softbreak': (state, token) => { state.content += '\n'; + state.annotations.push({ + type: 'soft-break', + start: state.content.length - 1, + end: state.content.length, + attributes: {} + }); }, 'hr': (state, token) => { + state.content += '\uFFFC'; state.annotations.push({ type: token.tag, - start: state.content.length, + start: state.content.length - 1, end: state.content.length, attributes: {} }); @@ -132,9 +139,10 @@ const HANDLERS = { attributes.alt = fetchText(token); + state.content += '\uFFFC'; state.annotations.push({ type: token.tag, - start: state.content.length, + start: state.content.length - 1, end: state.content.length, attributes }); diff --git a/packages/contenttype-commonmark/test/atjson-contenttype-markdown-test.ts b/packages/contenttype-commonmark/test/atjson-contenttype-markdown-test.ts index 18c22d5f6..2a1edd3d7 100644 --- a/packages/contenttype-commonmark/test/atjson-contenttype-markdown-test.ts +++ b/packages/contenttype-commonmark/test/atjson-contenttype-markdown-test.ts @@ -141,11 +141,11 @@ describe('markdown -> atjson', function () { let parser = new Parser(markdown); let atjson = parser.parse(); - expect(atjson.content).toBe('\n'); + expect(atjson.content).toBe('\uFFFC\n'); let expectedAnnotations = [ - { type: 'paragraph', start: 0, end: 0, attributes: {} }, - { type: 'image', start: 0, end: 0, attributes: { src: '/url', title: 'title', alt: 'foo' } } + { type: 'paragraph', start: 0, end: 1, attributes: {} }, + { type: 'image', start: 0, end: 1, attributes: { src: '/url', title: 'title', alt: 'foo' } } ]; expect(atjson.annotations).toEqual(expectedAnnotations); @@ -184,5 +184,21 @@ describe('markdown -> atjson', function () { expect(atjson.annotations).toEqual(expectedAnnotations); }); + + it('edge-case images from commonmark tests', function () { + let markdown = '![foo]\n[]\n\n[foo]: /url "title"\n'; + + let parser = new Parser(markdown); + let atjson = parser.parse(); + + expect(atjson.content).toBe('\uFFFC\n[]\n'); + + let expectedAnnotations = [ + { type: 'paragraph', start: 0, end: atjson.content.length - 1, attributes: {} }, + { type: 'image', start: 0, end: 1, attributes: { src: '/url', alt: 'foo', title: 'title' } } + ]; + + expect(atjson.annotations).toEqual(expectedAnnotations); + }); }); diff --git a/packages/hir/test/hir-test.ts b/packages/hir/test/hir-test.ts index 5a16db9be..4dd7edbf0 100644 --- a/packages/hir/test/hir-test.ts +++ b/packages/hir/test/hir-test.ts @@ -65,6 +65,14 @@ function paragraph(...children: node[]) { }; } +function image(attributes: object, ...children: node[]) { + return { + type: 'image', + attributes: attributes, + children + }; +} + describe('@atjson/hir', function () { /** @@ -264,5 +272,23 @@ describe('@atjson/hir', function () { expect(new HIR(zerolength).toJSON()).toEqual(expected); }); -}); + + // n.b. this case is somewhat ambiguous – the image should be explicitly + // assigned to an object replacement character in the text + it('regression test from commonmark Images tests', function () { + let atjson = new AtJSON({ + content: '\uFFFC\n[]\n', + annotations: [ + { type: 'paragraph', start: 0, end: 5 } + { type: 'image', start: 0, end: 1, attributes: { src: '/url', alt: 'foo', title: 'title' } }, + ] + }); + + let expected = root( + paragraph(image({ alt: 'foo', src: '/url', title: 'title' }), '\n[]\n') + ); + + expect(new HIR(atjson).toJSON()).toEqual(expected); + }); + }); });