@tkeron/html-parser 0.1.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +1 -7
  2. package/bun.lock +5 -0
  3. package/index.ts +4 -0
  4. package/package.json +7 -1
  5. package/src/css-selector.ts +1 -1
  6. package/src/dom-simulator.ts +41 -17
  7. package/src/encoding.ts +39 -0
  8. package/src/index.ts +9 -0
  9. package/src/parser.ts +509 -143
  10. package/src/serializer.ts +450 -0
  11. package/src/tokenizer.ts +190 -118
  12. package/tests/advanced.test.ts +121 -108
  13. package/tests/custom-elements-head.test.ts +105 -0
  14. package/tests/dom-extended.test.ts +12 -12
  15. package/tests/dom-manipulation.test.ts +9 -10
  16. package/tests/dom.test.ts +32 -27
  17. package/tests/helpers/tokenizer-adapter.test.ts +70 -0
  18. package/tests/helpers/tokenizer-adapter.ts +65 -0
  19. package/tests/helpers/tree-adapter.test.ts +39 -0
  20. package/tests/helpers/tree-adapter.ts +60 -0
  21. package/tests/html5lib-data/tokenizer/namedEntities.test +42422 -0
  22. package/tests/html5lib-data/tokenizer/pendingSpecChanges.test +9 -0
  23. package/tests/html5lib-data/tree-construction/adoption01.dat +354 -0
  24. package/tests/html5lib-data/tree-construction/adoption02.dat +39 -0
  25. package/tests/html5lib-data/tree-construction/domjs-unsafe.dat +0 -0
  26. package/tests/html5lib-data/tree-construction/entities02.dat +309 -0
  27. package/tests/html5lib-data/tree-construction/html5test-com.dat +301 -0
  28. package/tests/html5lib-data/tree-construction/math.dat +104 -0
  29. package/tests/html5lib-data/tree-construction/namespace-sensitivity.dat +22 -0
  30. package/tests/html5lib-data/tree-construction/noscript01.dat +237 -0
  31. package/tests/html5lib-data/tree-construction/ruby.dat +302 -0
  32. package/tests/html5lib-data/tree-construction/scriptdata01.dat +372 -0
  33. package/tests/html5lib-data/tree-construction/svg.dat +104 -0
  34. package/tests/html5lib-data/tree-construction/template.dat +1673 -0
  35. package/tests/html5lib-data/tree-construction/tests10.dat +853 -0
  36. package/tests/html5lib-data/tree-construction/tests11.dat +523 -0
  37. package/tests/html5lib-data/tree-construction/tests20.dat +842 -0
  38. package/tests/html5lib-data/tree-construction/tests21.dat +306 -0
  39. package/tests/html5lib-data/tree-construction/tests23.dat +168 -0
  40. package/tests/html5lib-data/tree-construction/tests24.dat +79 -0
  41. package/tests/html5lib-data/tree-construction/tests5.dat +210 -0
  42. package/tests/html5lib-data/tree-construction/tests6.dat +663 -0
  43. package/tests/html5lib-data/tree-construction/tests_innerHTML_1.dat +844 -0
  44. package/tests/parser.test.ts +173 -193
  45. package/tests/serializer-core.test.ts +16 -0
  46. package/tests/serializer-data/core.test +125 -0
  47. package/tests/serializer-data/injectmeta.test +66 -0
  48. package/tests/serializer-data/optionaltags.test +965 -0
  49. package/tests/serializer-data/options.test +60 -0
  50. package/tests/serializer-data/whitespace.test +51 -0
  51. package/tests/serializer-injectmeta.test.ts +16 -0
  52. package/tests/serializer-optionaltags.test.ts +16 -0
  53. package/tests/serializer-options.test.ts +16 -0
  54. package/tests/serializer-whitespace.test.ts +16 -0
  55. package/tests/tokenizer-namedEntities.test.ts +20 -0
  56. package/tests/tokenizer-pendingSpecChanges.test.ts +20 -0
  57. package/tests/tokenizer.test.ts +25 -32
  58. package/tests/tree-construction-adoption01.test.ts +37 -0
  59. package/tests/tree-construction-adoption02.test.ts +34 -0
  60. package/tests/tree-construction-domjs-unsafe.test.ts +24 -0
  61. package/tests/tree-construction-entities02.test.ts +33 -0
  62. package/tests/tree-construction-html5test-com.test.ts +32 -0
  63. package/tests/tree-construction-math.test.ts +18 -0
  64. package/tests/tree-construction-namespace-sensitivity.test.ts +18 -0
  65. package/tests/tree-construction-noscript01.test.ts +18 -0
  66. package/tests/tree-construction-ruby.test.ts +21 -0
  67. package/tests/tree-construction-scriptdata01.test.ts +21 -0
  68. package/tests/tree-construction-svg.test.ts +21 -0
  69. package/tests/tree-construction-template.test.ts +21 -0
  70. package/tests/tree-construction-tests10.test.ts +21 -0
  71. package/tests/tree-construction-tests11.test.ts +21 -0
  72. package/tests/tree-construction-tests20.test.ts +18 -0
  73. package/tests/tree-construction-tests21.test.ts +18 -0
  74. package/tests/tree-construction-tests23.test.ts +18 -0
  75. package/tests/tree-construction-tests24.test.ts +18 -0
  76. package/tests/tree-construction-tests5.test.ts +21 -0
  77. package/tests/tree-construction-tests6.test.ts +21 -0
  78. package/tests/tree-construction-tests_innerHTML_1.test.ts +21 -0
  79. package/tests/custom-elements.test.ts +0 -745
  80. package/tests/official/README.md +0 -87
  81. package/tests/official/acid/acid-tests.test.ts +0 -309
  82. package/tests/official/final-output/final-output.test.ts +0 -361
  83. package/tests/official/html5lib/tokenizer-utils.ts +0 -192
  84. package/tests/official/html5lib/tokenizer.test.ts +0 -171
  85. package/tests/official/html5lib/tree-construction-utils.ts +0 -194
  86. package/tests/official/html5lib/tree-construction.test.ts +0 -250
  87. package/tests/official/validator/validator-tests.test.ts +0 -237
  88. package/tests/official/validator-nu/validator-nu.test.ts +0 -335
  89. package/tests/official/whatwg/whatwg-tests.test.ts +0 -205
  90. package/tests/official/wpt/wpt-tests.test.ts +0 -409
@@ -1,361 +0,0 @@
1
- import { describe, it, expect } from 'bun:test';
2
- import { parseHTML } from '../../../index';
3
-
4
-
5
- function normalizeText(text: string): string {
6
- return text
7
- .replace(/\s+/g, ' ')
8
- .trim();
9
- }
10
-
11
- describe('Final HTML Output Validation', () => {
12
- describe('Complete HTML Structure', () => {
13
- it('should parse and create DOM structure correctly', () => {
14
- const html = '<div class="container"><p>Hello World</p></div>';
15
-
16
- const document = parseHTML(html);
17
-
18
- expect(document).toBeDefined();
19
- expect(document.nodeType).toBe(9);
20
-
21
- const div = document.querySelector('div');
22
- expect(div).toBeDefined();
23
- expect(div?.className).toBe('container');
24
-
25
- const p = document.querySelector('p');
26
- expect(p).toBeDefined();
27
- expect(p?.textContent).toBe('Hello World');
28
- });
29
-
30
- it('should handle nested elements correctly', () => {
31
- const html = '<div><span><strong>Bold text</strong></span></div>';
32
-
33
- const document = parseHTML(html);
34
-
35
- const div = document.querySelector('div');
36
- expect(div).toBeDefined();
37
-
38
- const span = div?.querySelector('span');
39
- expect(span).toBeDefined();
40
-
41
- const strong = span?.querySelector('strong');
42
- expect(strong).toBeDefined();
43
- expect(strong?.textContent).toBe('Bold text');
44
- });
45
-
46
- it('should handle self-closing tags correctly', () => {
47
- const html = '<div><img src="test.jpg" alt="Test"><br><hr></div>';
48
-
49
- const document = parseHTML(html);
50
-
51
- const img = document.querySelector('img');
52
- expect(img).toBeDefined();
53
- expect(img?.getAttribute('src')).toBe('test.jpg');
54
- expect(img?.getAttribute('alt')).toBe('Test');
55
-
56
- const br = document.querySelector('br');
57
- expect(br).toBeDefined();
58
-
59
- const hr = document.querySelector('hr');
60
- expect(hr).toBeDefined();
61
- });
62
-
63
- it('should handle attributes correctly', () => {
64
- const html = '<div id="main" class="container" data-value="test">Content</div>';
65
-
66
- const document = parseHTML(html);
67
-
68
- const div = document.querySelector('div');
69
- expect(div).toBeDefined();
70
- expect(div?.getAttribute('id')).toBe('main');
71
- expect(div?.getAttribute('class')).toBe('container');
72
- expect(div?.getAttribute('data-value')).toBe('test');
73
- expect(div?.textContent).toBe('Content');
74
- });
75
-
76
- it('should handle text content correctly', () => {
77
- const html = '<p>This is a <strong>bold</strong> text with <em>emphasis</em>.</p>';
78
-
79
- const document = parseHTML(html);
80
-
81
- const p = document.querySelector('p');
82
- expect(p).toBeDefined();
83
- expect(normalizeText(p?.textContent || '')).toBe('This is a bold text with emphasis.');
84
-
85
- const strong = document.querySelector('strong');
86
- expect(strong?.textContent).toBe('bold');
87
-
88
- const em = document.querySelector('em');
89
- expect(em?.textContent).toBe('emphasis');
90
- });
91
-
92
- it('should handle comments correctly', () => {
93
- const html = '<div><!-- This is a comment --><p>Content</p></div>';
94
-
95
- const document = parseHTML(html);
96
-
97
- const div = document.querySelector('div');
98
- expect(div).toBeDefined();
99
-
100
- const p = document.querySelector('p');
101
- expect(p).toBeDefined();
102
- expect(p?.textContent).toBe('Content');
103
-
104
-
105
- const commentNode = div?.childNodes[0];
106
- expect(commentNode?.nodeType).toBe(8);
107
- });
108
- });
109
-
110
- describe('DOM Structure Validation', () => {
111
- it('should maintain correct parent-child relationships', () => {
112
- const html = '<div><p><span>Nested</span></p></div>';
113
-
114
- const document = parseHTML(html);
115
-
116
- const div = document.querySelector('div');
117
- expect(div).toBeDefined();
118
- expect(div?.children.length).toBe(1);
119
-
120
- const p = div?.children[0];
121
- expect(p?.tagName).toBe('P');
122
- expect(p?.children.length).toBe(1);
123
-
124
- const span = p?.children[0];
125
- expect(span?.tagName).toBe('SPAN');
126
- expect(span?.textContent).toBe('Nested');
127
- });
128
-
129
- it('should handle mixed content correctly', () => {
130
- const html = '<div>Text before <span>span content</span> text after</div>';
131
-
132
- const document = parseHTML(html);
133
-
134
- const div = document.querySelector('div');
135
- expect(div).toBeDefined();
136
- expect(div?.childNodes.length).toBe(3);
137
-
138
-
139
- expect(div?.childNodes[0]?.nodeType).toBe(3);
140
- expect(div?.childNodes[0]?.textContent).toBe('Text before ');
141
-
142
-
143
- expect(div?.childNodes[1]?.nodeType).toBe(1);
144
- expect((div?.childNodes[1] as Element)?.tagName).toBe('SPAN');
145
-
146
-
147
- expect(div?.childNodes[2]?.nodeType).toBe(3);
148
- expect(div?.childNodes[2]?.textContent).toBe(' text after');
149
- });
150
-
151
- it('should handle void elements correctly', () => {
152
- const html = '<div><img src="test.jpg"><br><input type="text"></div>';
153
-
154
- const document = parseHTML(html);
155
-
156
- const img = document.querySelector('img');
157
- expect(img).toBeDefined();
158
- expect(img?.getAttribute('src')).toBe('test.jpg');
159
-
160
- const br = document.querySelector('br');
161
- expect(br).toBeDefined();
162
-
163
- const input = document.querySelector('input');
164
- expect(input).toBeDefined();
165
- expect(input?.getAttribute('type')).toBe('text');
166
- });
167
- });
168
-
169
- describe('HTML5 Semantic Structure', () => {
170
- it('should handle complete HTML5 document structure', () => {
171
- const html = `<!DOCTYPE html>
172
- <html>
173
- <head>
174
- <title>Test Document</title>
175
- </head>
176
- <body>
177
- <header>
178
- <nav>Navigation</nav>
179
- </header>
180
- <main>
181
- <article>
182
- <section>Content</section>
183
- </article>
184
- </main>
185
- <footer>Footer</footer>
186
- </body>
187
- </html>`;
188
-
189
- const document = parseHTML(html);
190
-
191
- expect(document).toBeDefined();
192
- expect(document.documentElement?.tagName).toBe('HTML');
193
-
194
- const head = document.querySelector('head');
195
- expect(head).toBeDefined();
196
-
197
- const title = document.querySelector('title');
198
- expect(title?.textContent).toBe('Test Document');
199
-
200
- const body = document.querySelector('body');
201
- expect(body).toBeDefined();
202
-
203
- const header = document.querySelector('header');
204
- expect(header).toBeDefined();
205
-
206
- const nav = document.querySelector('nav');
207
- expect(nav?.textContent).toBe('Navigation');
208
-
209
- const main = document.querySelector('main');
210
- expect(main).toBeDefined();
211
-
212
- const article = document.querySelector('article');
213
- expect(article).toBeDefined();
214
-
215
- const section = document.querySelector('section');
216
- expect(section?.textContent).toBe('Content');
217
-
218
- const footer = document.querySelector('footer');
219
- expect(footer?.textContent).toBe('Footer');
220
- });
221
-
222
- it('should handle HTML5 form elements', () => {
223
- const html = `<form>
224
- <fieldset>
225
- <legend>Contact Information</legend>
226
- <label for="email">Email:</label>
227
- <input type="email" id="email" required>
228
- <label for="phone">Phone:</label>
229
- <input type="tel" id="phone">
230
- <button type="submit">Submit</button>
231
- </fieldset>
232
- </form>`;
233
-
234
- const document = parseHTML(html);
235
-
236
- const form = document.querySelector('form');
237
- expect(form).toBeDefined();
238
-
239
- const fieldset = document.querySelector('fieldset');
240
- expect(fieldset).toBeDefined();
241
-
242
- const legend = document.querySelector('legend');
243
- expect(legend?.textContent).toBe('Contact Information');
244
-
245
- const emailInput = document.querySelector('input[type="email"]');
246
- expect(emailInput).toBeDefined();
247
- expect(emailInput?.getAttribute('id')).toBe('email');
248
- expect(emailInput?.hasAttribute('required')).toBe(true);
249
-
250
- const phoneInput = document.querySelector('input[type="tel"]');
251
- expect(phoneInput).toBeDefined();
252
- expect(phoneInput?.getAttribute('id')).toBe('phone');
253
-
254
- const submitButton = document.querySelector('button[type="submit"]');
255
- expect(submitButton).toBeDefined();
256
- expect(submitButton?.textContent).toBe('Submit');
257
- });
258
- });
259
-
260
- describe('Error Handling and Edge Cases', () => {
261
- it('should handle malformed HTML gracefully', () => {
262
- const malformedHTML = '<div><p>Unclosed paragraph<div>Another div</div>';
263
-
264
- const document = parseHTML(malformedHTML);
265
-
266
- expect(document).toBeDefined();
267
- expect(document.nodeType).toBe(9);
268
-
269
- const divs = document.querySelectorAll('div');
270
- expect(divs.length).toBeGreaterThan(0);
271
- });
272
-
273
- it('should handle empty elements', () => {
274
- const html = '<div></div><p></p><span></span>';
275
-
276
- const document = parseHTML(html);
277
-
278
- const div = document.querySelector('div');
279
- expect(div).toBeDefined();
280
- expect(div?.textContent).toBe('');
281
-
282
- const p = document.querySelector('p');
283
- expect(p).toBeDefined();
284
- expect(p?.textContent).toBe('');
285
-
286
- const span = document.querySelector('span');
287
- expect(span).toBeDefined();
288
- expect(span?.textContent).toBe('');
289
- });
290
-
291
- it('should handle special characters in text', () => {
292
- const html = '<p>Special chars: &lt; &gt; &amp; &quot; &#39;</p>';
293
-
294
- const document = parseHTML(html);
295
-
296
- const p = document.querySelector('p');
297
- expect(p).toBeDefined();
298
- expect(p?.textContent).toContain('Special chars:');
299
-
300
- });
301
-
302
- it('should handle multiple top-level elements', () => {
303
- const html = '<div>First</div><p>Second</p><span>Third</span>';
304
-
305
- const document = parseHTML(html);
306
-
307
- const div = document.querySelector('div');
308
- expect(div?.textContent).toBe('First');
309
-
310
- const p = document.querySelector('p');
311
- expect(p?.textContent).toBe('Second');
312
-
313
- const span = document.querySelector('span');
314
- expect(span?.textContent).toBe('Third');
315
- });
316
- });
317
-
318
- describe('DOM API Compliance', () => {
319
- it('should support basic DOM queries', () => {
320
- const html = '<div id="test" class="container"><p class="text">Hello</p></div>';
321
-
322
- const document = parseHTML(html);
323
-
324
-
325
- const byId = document.getElementById('test');
326
- expect(byId).toBeDefined();
327
- expect(byId?.tagName).toBe('DIV');
328
-
329
-
330
- const bySelector = document.querySelector('.container');
331
- expect(bySelector).toBeDefined();
332
- expect(bySelector?.id).toBe('test');
333
-
334
-
335
- const byClass = document.querySelectorAll('.text');
336
- expect(byClass.length).toBe(1);
337
- expect(byClass[0]?.textContent).toBe('Hello');
338
- });
339
-
340
- it('should support element traversal', () => {
341
- const html = '<div><p>First</p><p>Second</p><p>Third</p></div>';
342
-
343
- const document = parseHTML(html);
344
-
345
- const div = document.querySelector('div');
346
- expect(div).toBeDefined();
347
-
348
- const children = div?.children;
349
- expect(children?.length).toBe(3);
350
-
351
- const firstP = children?.[0];
352
- expect(firstP?.textContent).toBe('First');
353
-
354
- const secondP = children?.[1];
355
- expect(secondP?.textContent).toBe('Second');
356
-
357
- const thirdP = children?.[2];
358
- expect(thirdP?.textContent).toBe('Third');
359
- });
360
- });
361
- });
@@ -1,192 +0,0 @@
1
- import { expect, describe, it } from 'bun:test';
2
- import { tokenize, TokenType } from '../../../src/tokenizer';
3
- import type { Token } from '../../../src/tokenizer';
4
-
5
-
6
- export interface HTML5libTokenizerTest {
7
- description: string;
8
- input: string;
9
- output: HTML5libTokenOutput[];
10
- initialStates?: string[];
11
- lastStartTag?: string;
12
- errors?: HTML5libError[];
13
- doubleEscaped?: boolean;
14
- }
15
-
16
- export interface HTML5libTokenizerTestSuite {
17
- tests: HTML5libTokenizerTest[];
18
- }
19
-
20
- export type HTML5libTokenOutput =
21
- | ['StartTag', string, Record<string, string>]
22
- | ['StartTag', string, Record<string, string>, boolean]
23
- | ['EndTag', string]
24
- | ['Comment', string]
25
- | ['Character', string]
26
- | ['DOCTYPE', string, string | null, string | null, boolean];
27
-
28
- export interface HTML5libError {
29
- code: string;
30
- line: number;
31
- col: number;
32
- }
33
-
34
-
35
- export function convertHTML5libToken(html5libToken: HTML5libTokenOutput): Partial<Token> {
36
- const type = html5libToken[0];
37
- const nameOrData = html5libToken[1];
38
-
39
- switch (type) {
40
- case 'DOCTYPE':
41
- return {
42
- type: TokenType.DOCTYPE,
43
- value: nameOrData || '',
44
- attributes: {}
45
- };
46
- case 'StartTag':
47
- const attributes = html5libToken[2];
48
- const selfClosing = html5libToken[3];
49
- return {
50
- type: TokenType.TAG_OPEN,
51
- value: nameOrData || '',
52
- attributes: (typeof attributes === 'object' && attributes !== null) ? attributes : {},
53
- isSelfClosing: typeof selfClosing === 'boolean' ? selfClosing : false
54
- };
55
- case 'EndTag':
56
- return {
57
- type: TokenType.TAG_CLOSE,
58
- value: nameOrData || '',
59
- attributes: {},
60
- isClosing: true
61
- };
62
- case 'Comment':
63
- return {
64
- type: TokenType.COMMENT,
65
- value: nameOrData || '',
66
- attributes: {}
67
- };
68
- case 'Character':
69
- return {
70
- type: TokenType.TEXT,
71
- value: nameOrData || '',
72
- attributes: {}
73
- };
74
- default:
75
- throw new Error(`Unknown HTML5lib token type: ${type}`);
76
- }
77
- }
78
-
79
-
80
- export function convertToHTML5libToken(token: Token): HTML5libTokenOutput {
81
- switch (token.type) {
82
- case TokenType.DOCTYPE:
83
- return ['DOCTYPE', token.value, null, null, true];
84
- case TokenType.TAG_OPEN:
85
- if (token.isSelfClosing) {
86
- return ['StartTag', token.value, token.attributes || {}, true];
87
- } else {
88
- return ['StartTag', token.value, token.attributes || {}];
89
- }
90
- case TokenType.TAG_CLOSE:
91
- return ['EndTag', token.value];
92
- case TokenType.COMMENT:
93
- return ['Comment', token.value];
94
- case TokenType.TEXT:
95
- return ['Character', token.value];
96
- default:
97
- throw new Error(`Unknown token type: ${token.type}`);
98
- }
99
- }
100
-
101
-
102
- export function normalizeCharacterTokens(tokens: Token[]): Token[] {
103
- const normalized: Token[] = [];
104
- let currentText = '';
105
-
106
- for (const token of tokens) {
107
- if (token.type === TokenType.TEXT) {
108
- currentText += token.value;
109
- } else {
110
- if (currentText) {
111
- normalized.push({
112
- type: TokenType.TEXT,
113
- value: currentText,
114
- position: token.position,
115
- attributes: {}
116
- });
117
- currentText = '';
118
- }
119
- if (token.type !== TokenType.EOF) {
120
- normalized.push(token);
121
- }
122
- }
123
- }
124
-
125
- if (currentText) {
126
- normalized.push({
127
- type: TokenType.TEXT,
128
- value: currentText,
129
- position: { line: 1, column: 1, offset: 0 },
130
- attributes: {}
131
- });
132
- }
133
-
134
- return normalized;
135
- }
136
-
137
-
138
- export function runHTML5libTokenizerTest(test: HTML5libTokenizerTest): void {
139
- const { description, input, output: expectedOutput, initialStates = ['Data state'] } = test;
140
-
141
-
142
- let processedInput = input;
143
- if (test.doubleEscaped) {
144
- processedInput = processedInput.replace(/\\u([0-9a-fA-F]{4})/g, (match, hex) => {
145
- return String.fromCharCode(parseInt(hex, 16));
146
- });
147
- }
148
-
149
- for (const initialState of initialStates) {
150
- it(`${description} (${initialState})`, () => {
151
-
152
- const tokens = tokenize(processedInput);
153
-
154
-
155
- const normalizedTokens = normalizeCharacterTokens(tokens);
156
-
157
-
158
- const actualOutput = normalizedTokens.map(convertToHTML5libToken);
159
-
160
-
161
- let processedExpectedOutput = expectedOutput;
162
- if (test.doubleEscaped) {
163
- processedExpectedOutput = expectedOutput.map(token => {
164
- if (typeof token[1] === 'string') {
165
- token[1] = token[1].replace(/\\u([0-9a-fA-F]{4})/g, (match, hex) => {
166
- return String.fromCharCode(parseInt(hex, 16));
167
- });
168
- }
169
- return token;
170
- });
171
- }
172
-
173
-
174
- expect(actualOutput).toEqual(processedExpectedOutput);
175
- });
176
- }
177
- }
178
-
179
-
180
- export function runHTML5libTokenizerTestSuite(testSuite: HTML5libTokenizerTestSuite, suiteName: string): void {
181
- describe(`HTML5lib Tokenizer Tests: ${suiteName}`, () => {
182
- testSuite.tests.forEach(test => {
183
- runHTML5libTokenizerTest(test);
184
- });
185
- });
186
- }
187
-
188
-
189
- export async function loadHTML5libTokenizerTests(testData: string, suiteName: string): Promise<void> {
190
- const testSuite: HTML5libTokenizerTestSuite = JSON.parse(testData);
191
- runHTML5libTokenizerTestSuite(testSuite, suiteName);
192
- }