1 | import { HIR } from '@atjson/hir';
|
2 | import OffsetSource from '@atjson/offset-annotations';
|
3 | import * as fs from 'fs';
|
4 | import * as path from 'path';
|
5 | import PRISMSource from '../src';
|
6 |
|
7 | describe('@atjson/source-prism', () => {
|
8 | it('parses xml declaration', () => {
|
9 | let doc = PRISMSource.fromRaw('<?xml version="1.0" encoding="utf-8"?>');
|
10 |
|
11 | expect(doc.where({}).toJSON()).toMatchObject([
|
12 | {
|
13 | type: '-atjson-parse-token',
|
14 | start: 0,
|
15 | end: doc.content.length,
|
16 | attributes: {
|
17 | '-atjson-reason': '<?xml>'
|
18 | }
|
19 | }
|
20 | ]);
|
21 | });
|
22 |
|
23 | it('does not require xml declaration', () => {
|
24 | let doc = PRISMSource.fromRaw('<body>some text</body>');
|
25 |
|
26 | expect(doc.where({}).sort().toJSON()).toMatchObject([
|
27 | { type: '-atjson-parse-token', start: 0, end: 6, attributes: { '-atjson-reason': '<body>' } },
|
28 | { type: '-html-body', start: 0, end: 22 },
|
29 | { type: '-atjson-parse-token', start: 15, end: 22, attributes: { '-atjson-reason': '</body>' } }
|
30 | ]);
|
31 | });
|
32 |
|
33 | it('parses xml tags', () => {
|
34 | let doc = PRISMSource.fromRaw(`<?xml version="1.0" encoding="utf-8"?><pam:message><pam:article><head /><body>text</body></pam:article></pam:message>`);
|
35 | let hir = new HIR(doc);
|
36 |
|
37 | expect(hir.toJSON()).toMatchObject({
|
38 | children: [
|
39 | {
|
40 | type: 'message',
|
41 | children: [
|
42 | {
|
43 | type: 'article',
|
44 | children: [
|
45 | { type: 'head' },
|
46 | { type: 'body', children: ['text'] }
|
47 | ]
|
48 | }
|
49 | ]
|
50 | }
|
51 | ]
|
52 | });
|
53 |
|
54 | expect(doc.where({}).sort().toJSON()).toMatchObject([
|
55 | { type: '-atjson-parse-token', start: 0, end: 38, attributes: { '-atjson-reason': '<?xml>' } },
|
56 | { type: '-atjson-parse-token', start: 38, end: 51, attributes: { '-atjson-reason': '<pam:message>' } },
|
57 | { type: '-pam-message', start: 38, end: 117 },
|
58 | { type: '-atjson-parse-token', start: 51, end: 64, attributes: { '-atjson-reason': '<pam:article>' } },
|
59 | { type: '-pam-article', start: 51, end: 103 },
|
60 | { type: '-html-head', start: 64, end: 72 },
|
61 | { type: '-atjson-parse-token', start: 64, end: 72, attributes: { '-atjson-reason': '<head/>' } },
|
62 | { type: '-atjson-parse-token', start: 72, end: 78, attributes: { '-atjson-reason': '<body>' } },
|
63 | { type: '-html-body', start: 72, end: 89 },
|
64 | { type: '-atjson-parse-token', start: 82, end: 89, attributes: { '-atjson-reason': '</body>' } },
|
65 | { type: '-atjson-parse-token', start: 89, end: 103, attributes: { '-atjson-reason': '</pam:article>' } },
|
66 | { type: '-atjson-parse-token', start: 103, end: 117, attributes: { '-atjson-reason': '</pam:message>' } }
|
67 | ]);
|
68 | });
|
69 |
|
70 | describe('xml entities', () => {
|
71 | test.each([
|
72 | [ '∀', '∀' ],
|
73 | [ '“', '“' ],
|
74 | [ '"', '"' ],
|
75 | [ '&', '&' ],
|
76 | [ ''', '\'' ],
|
77 | [ '<', '<' ],
|
78 | [ '>', '>' ],
|
79 | [ '’', '’' ]
|
80 | ])('converts %s to %s', (entity, expected) => {
|
81 | let doc = PRISMSource.fromRaw(`<?xml version="1.0" encoding="utf-8"?><body>${entity}</body>`);
|
82 |
|
83 | expect(doc.content).toEqual(`<?xml version="1.0" encoding="utf-8"?><body>${expected}</body>`);
|
84 | });
|
85 |
|
86 | it('repositions annotations after replacing entities', () => {
|
87 | let doc = PRISMSource.fromRaw('<pam:article><head><dc:title>Title</dc:title></head><body><p>∀x∈Λ, x∨¬x∎</p></body></pam:article>');
|
88 |
|
89 | expect(doc.content).toEqual('<pam:article><head><dc:title>Title</dc:title></head><body><p>∀x∈Λ, x∨¬x∎</p></body></pam:article>');
|
90 | expect(doc.where({}).sort().toJSON()).toMatchObject([
|
91 | { type: '-atjson-parse-token', start: 0, end: 13, attributes: { '-atjson-reason': '<pam:article>' } },
|
92 | { type: '-pam-article', start: 0, end: 97 },
|
93 | { type: '-atjson-parse-token', start: 13, end: 19, attributes: { '-atjson-reason': '<head>' } },
|
94 | { type: '-html-head', start: 13, end: 52 },
|
95 | { type: '-atjson-parse-token', start: 19, end: 29, attributes: { '-atjson-reason': '<dc:title>' } },
|
96 | { type: '-dc-title', start: 19, end: 45 },
|
97 | { type: '-atjson-parse-token', start: 34, end: 45, attributes: { '-atjson-reason': '</dc:title>' } },
|
98 | { type: '-atjson-parse-token', start: 45, end: 52, attributes: { '-atjson-reason': '</head>' } },
|
99 | { type: '-atjson-parse-token', start: 52, end: 58, attributes: { '-atjson-reason': '<body>' } },
|
100 | { type: '-html-body', start: 52, end: 83 },
|
101 | { type: '-atjson-parse-token', start: 58, end: 61, attributes: { '-atjson-reason': '<p>' } },
|
102 | { type: '-html-p', start: 58, end: 76 },
|
103 | { type: '-atjson-parse-token', start: 72, end: 76, attributes: { '-atjson-reason': '</p>' } },
|
104 | { type: '-atjson-parse-token', start: 76, end: 83, attributes: { '-atjson-reason': '</body>' } },
|
105 | { type: '-atjson-parse-token', start: 83, end: 97, attributes: { '-atjson-reason': '</pam:article>' } }
|
106 | ]);
|
107 | });
|
108 | });
|
109 |
|
110 | describe('prism snapshots', () => {
|
111 | test.each([
|
112 | [ 'gq-fresh-paint.xml' ],
|
113 | [ 'gq-santoni.xml' ],
|
114 | [ 'gq-yuketen.xml' ]
|
115 | ])('parses %s', xmlFile => {
|
116 | let fixturePath = path.join(__dirname, 'fixtures', xmlFile);
|
117 | let xml = fs.readFileSync(fixturePath).toString();
|
118 |
|
119 | let doc = PRISMSource.fromRaw(xml);
|
120 | let hir = new HIR(doc);
|
121 |
|
122 | expect(hir.toJSON()).toMatchSnapshot();
|
123 | expect(doc.convertTo(OffsetSource).toJSON()).toMatchSnapshot();
|
124 | });
|
125 | });
|
126 | });
|