<commit_before><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>tinymce.html.DomParser tests</title>
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen">
<script type="text/javascript" src="qunit/qunit.js"></script>
<script type="text/javascript" src="qunit/runner.js"></script>
<script type="text/javascript" src="js/utils.js"></script>
<script type="text/javascript" src="../jscripts/tiny_mce/tiny_mce.js"></script>
<script>
module("tinymce.html.DomParser");

var schema = new tinymce.html.Schema();
var serializer = new tinymce.html.Serializer({}, schema);

function countNodes(node, counter) {
	var sibling;

	if (!counter)
		counter = {};

	if (node.name in counter) {
		counter[node.name]++;
	} else
		counter[node.name] = 1;

	for (sibling = node.firstChild; sibling; sibling = sibling.next) {
		countNodes(sibling, counter);
	}

	return counter;
}

schema.addValidChildren('+body[style]');

test('Parse element', function() {
	var parser, root;

	expect(7);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<B title="title" class="class">test</B>');
	equals(serializer.serialize(root), '<b class="class" title="title">test</b>', 'Inline element');
	equals(root.firstChild.type, 1, 'Element type');
	equals(root.firstChild.name, 'b', 'Element name');
	deepEqual(root.firstChild.attributes, [{name: 'title', value: 'title'}, {name: 'class', value: 'class'}], 'Element attributes');
	deepEqual(countNodes(root), {body:1, b:1, '#text':1}, 'Element attributes (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <SCRIPT>  \t\r\n   a < b > \t\r\n   </S' + 'CRIPT>   \t\r\n  ');
	equals(serializer.serialize(root), '<script>  \t\r\n   a < b > \t\r\n   </s' + 'cript>', 'Retain code inside SCRIPT');
	deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Retain code inside SCRIPT (count)');
});

test('Whitespace', function() {
	var parser, root;

	expect(14);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <B>  \t\r\n   test  \t\r\n   </B>   \t\r\n  ');
	equals(serializer.serialize(root), ' <b> test </b> ', 'Redundant whitespace (inline element)');
	deepEqual(countNodes(root), {body:1, b:1, '#text':3}, 'Redundant whitespace (inline element) (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <P>  \t\r\n   test  \t\r\n   </P>   \t\r\n  ');
	equals(serializer.serialize(root), '<p>test</p>', 'Redundant whitespace (block element)');
	deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'Redundant whitespace (block element) (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <PRE>  \t\r\n   test  \t\r\n   </PRE>   \t\r\n  ');
	equals(serializer.serialize(root), '<pre>  \t\r\n   test  \t\r\n   </pre>', 'Whitespace around and inside PRE');
	deepEqual(countNodes(root), {body:1, pre:1, '#text':1}, 'Whitespace around and inside PRE (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <SCRIPT>  \t\r\n   test  \t\r\n   </S' + 'CRIPT>   \t\r\n  ');
	equals(serializer.serialize(root), '<script>  \t\r\n   test  \t\r\n   </s' + 'cript>', 'Whitespace around and inside SCRIPT');
	deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Whitespace around and inside SCRIPT (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <STYLE>  \t\r\n   test  \t\r\n   </STYLE>   \t\r\n  ');
	equals(serializer.serialize(root), '<style>  \t\r\n   test  \t\r\n   </style>', 'Whitespace around and inside STYLE');
	deepEqual(countNodes(root), {body:1, style:1, '#text':1}, 'Whitespace around and inside STYLE (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<ul>\n<li>Item 1\n<ul>\n<li>\n \t Indented \t \n</li>\n</ul>\n</li>\n</ul>\n');
	equals(serializer.serialize(root), '<ul><li>Item 1<ul><li>Indented</li></ul></li></ul>', 'Whitespace around and inside blocks (ul/li)');
	deepEqual(countNodes(root), {body:1, li:2, ul:2, '#text':2}, 'Whitespace around and inside blocks (ul/li) (count)');

	parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({invalid_elements : 'hr,br'}));
	root = parser.parse('\n<hr />\n<br />\n<div>\n<hr />\n<br />\n<img src="file.gif" data-mce_src="file.gif" />\n<hr />\n<br />\n</div>\n<hr />\n<br />\n');
	equals(serializer.serialize(root), '<div><img src="file.gif" data-mce_src="file.gif" /></div>', 'Whitespace where SaxParser will produce multiple whitespace nodes');
	deepEqual(countNodes(root), {body:1, div:1, img:1}, 'Whitespace where SaxParser will produce multiple whitespace nodes (ul/li) (count)');
});

test('Parse invalid contents', function() {
	var parser, root;

	expect(16);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a"><p class="b">123</p></p>');
	equals(serializer.serialize(root), '<p class="b">123</p>', 'P in P, no nodes before/after');
	deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'P in P, no nodes before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<p class="b">b</p><p class="c">c</p>d</p>');
	equals(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="a">d</p>', 'Two P in P, no nodes before/after');
	deepEqual(countNodes(root), {body: 1, p:4, '#text': 4}, 'Two P in P, no nodes before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">abc<p class="b">def</p></p>');
	equals(serializer.serialize(root), '<p class="a">abc</p><p class="b">def</p>', 'P in P with nodes before');
	deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes before (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a"><p class="b">abc</p>def</p>');
	equals(serializer.serialize(root), '<p class="b">abc</p><p class="a">def</p>', 'P in P with nodes after');
	deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<strong>b<span>c<em>d<p class="b">e</p>f</em>g</span>h</strong>i</p>');
	equals(serializer.serialize(root), '<p class="a">a<strong>b<span>c<em>d</em></span></strong></p><p class="b">e</p><p class="a"><strong><span><em>f</em>g</span>h</strong>i</p>', 'P in P wrapped in inline elements');
	deepEqual(countNodes(root), {"body":1, "p":3, "#text":9, "strong":2, "span":2, "em": 2}, 'P in P wrapped in inline elements (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<p class="b">b<p class="c">c</p>d</p>e</p>');
	equals(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="b">d</p><p class="a">e</p>', 'P in P in P with text before/after');
	deepEqual(countNodes(root), {body: 1, p:5, '#text': 5}, 'P in P in P with text before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<li>abc</li>');
	equals(serializer.serialize(root), 'abc', 'LI inside BODY');
	deepEqual(countNodes(root), {body: 1, '#text': 1}, 'LI inside BODY (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p>a<ul><li>b</li><li>c</li></ul>d</p>');
	equals(serializer.serialize(root), '<p>a</p><ul><li>b</li><li>c</li></ul><p>d</p>', 'UL inside P');
	deepEqual(countNodes(root), {body: 1, p:2, ul:1, li:2, '#text': 4}, 'UL inside P (count)');
});
</script>
</head>
<body>
	<h1 id="qunit-header">tinymce.html.DomParser tests</h1>
	<h2 id="qunit-banner"></h2>
	<div id="qunit-testrunner-toolbar"></div>
	<h2 id="qunit-userAgent"></h2>
	<ol id="qunit-tests"></ol>
	<div id="content"></div>
</body><commit_msg>Added unit tests for the addNodeFilter and addAttributeFilter functions in the DomParser class.<commit_after><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>tinymce.html.DomParser tests</title>
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen">
<script type="text/javascript" src="qunit/qunit.js"></script>
<script type="text/javascript" src="qunit/runner.js"></script>
<script type="text/javascript" src="js/utils.js"></script>
<script type="text/javascript" src="../jscripts/tiny_mce/tiny_mce.js"></script>
<script>
module("tinymce.html.DomParser");

var schema = new tinymce.html.Schema();
var serializer = new tinymce.html.Serializer({}, schema);

function countNodes(node, counter) {
	var sibling;

	if (!counter)
		counter = {};

	if (node.name in counter) {
		counter[node.name]++;
	} else
		counter[node.name] = 1;

	for (sibling = node.firstChild; sibling; sibling = sibling.next) {
		countNodes(sibling, counter);
	}

	return counter;
}

schema.addValidChildren('+body[style]');

test('Parse element', function() {
	var parser, root;

	expect(7);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<B title="title" class="class">test</B>');
	equals(serializer.serialize(root), '<b class="class" title="title">test</b>', 'Inline element');
	equals(root.firstChild.type, 1, 'Element type');
	equals(root.firstChild.name, 'b', 'Element name');
	deepEqual(root.firstChild.attributes, [{name: 'title', value: 'title'}, {name: 'class', value: 'class'}], 'Element attributes');
	deepEqual(countNodes(root), {body:1, b:1, '#text':1}, 'Element attributes (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <SCRIPT>  \t\r\n   a < b > \t\r\n   </S' + 'CRIPT>   \t\r\n  ');
	equals(serializer.serialize(root), '<script>  \t\r\n   a < b > \t\r\n   </s' + 'cript>', 'Retain code inside SCRIPT');
	deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Retain code inside SCRIPT (count)');
});

test('Whitespace', function() {
	var parser, root;

	expect(14);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <B>  \t\r\n   test  \t\r\n   </B>   \t\r\n  ');
	equals(serializer.serialize(root), ' <b> test </b> ', 'Redundant whitespace (inline element)');
	deepEqual(countNodes(root), {body:1, b:1, '#text':3}, 'Redundant whitespace (inline element) (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <P>  \t\r\n   test  \t\r\n   </P>   \t\r\n  ');
	equals(serializer.serialize(root), '<p>test</p>', 'Redundant whitespace (block element)');
	deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'Redundant whitespace (block element) (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <PRE>  \t\r\n   test  \t\r\n   </PRE>   \t\r\n  ');
	equals(serializer.serialize(root), '<pre>  \t\r\n   test  \t\r\n   </pre>', 'Whitespace around and inside PRE');
	deepEqual(countNodes(root), {body:1, pre:1, '#text':1}, 'Whitespace around and inside PRE (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <SCRIPT>  \t\r\n   test  \t\r\n   </S' + 'CRIPT>   \t\r\n  ');
	equals(serializer.serialize(root), '<script>  \t\r\n   test  \t\r\n   </s' + 'cript>', 'Whitespace around and inside SCRIPT');
	deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Whitespace around and inside SCRIPT (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('  \t\r\n  <STYLE>  \t\r\n   test  \t\r\n   </STYLE>   \t\r\n  ');
	equals(serializer.serialize(root), '<style>  \t\r\n   test  \t\r\n   </style>', 'Whitespace around and inside STYLE');
	deepEqual(countNodes(root), {body:1, style:1, '#text':1}, 'Whitespace around and inside STYLE (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<ul>\n<li>Item 1\n<ul>\n<li>\n \t Indented \t \n</li>\n</ul>\n</li>\n</ul>\n');
	equals(serializer.serialize(root), '<ul><li>Item 1<ul><li>Indented</li></ul></li></ul>', 'Whitespace around and inside blocks (ul/li)');
	deepEqual(countNodes(root), {body:1, li:2, ul:2, '#text':2}, 'Whitespace around and inside blocks (ul/li) (count)');

	parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({invalid_elements : 'hr,br'}));
	root = parser.parse('\n<hr />\n<br />\n<div>\n<hr />\n<br />\n<img src="file.gif" data-mce_src="file.gif" />\n<hr />\n<br />\n</div>\n<hr />\n<br />\n');
	equals(serializer.serialize(root), '<div><img src="file.gif" data-mce_src="file.gif" /></div>', 'Whitespace where SaxParser will produce multiple whitespace nodes');
	deepEqual(countNodes(root), {body:1, div:1, img:1}, 'Whitespace where SaxParser will produce multiple whitespace nodes (count)');
});

test('Parse invalid contents', function() {
	var parser, root;

	expect(16);

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a"><p class="b">123</p></p>');
	equals(serializer.serialize(root), '<p class="b">123</p>', 'P in P, no nodes before/after');
	deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'P in P, no nodes before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<p class="b">b</p><p class="c">c</p>d</p>');
	equals(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="a">d</p>', 'Two P in P, no nodes before/after');
	deepEqual(countNodes(root), {body: 1, p:4, '#text': 4}, 'Two P in P, no nodes before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">abc<p class="b">def</p></p>');
	equals(serializer.serialize(root), '<p class="a">abc</p><p class="b">def</p>', 'P in P with nodes before');
	deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes before (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a"><p class="b">abc</p>def</p>');
	equals(serializer.serialize(root), '<p class="b">abc</p><p class="a">def</p>', 'P in P with nodes after');
	deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<strong>b<span>c<em>d<p class="b">e</p>f</em>g</span>h</strong>i</p>');
	equals(serializer.serialize(root), '<p class="a">a<strong>b<span>c<em>d</em></span></strong></p><p class="b">e</p><p class="a"><strong><span><em>f</em>g</span>h</strong>i</p>', 'P in P wrapped in inline elements');
	deepEqual(countNodes(root), {"body":1, "p":3, "#text":9, "strong":2, "span":2, "em": 2}, 'P in P wrapped in inline elements (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p class="a">a<p class="b">b<p class="c">c</p>d</p>e</p>');
	equals(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="b">d</p><p class="a">e</p>', 'P in P in P with text before/after');
	deepEqual(countNodes(root), {body: 1, p:5, '#text': 5}, 'P in P in P with text before/after (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<li>abc</li>');
	equals(serializer.serialize(root), 'abc', 'LI inside BODY');
	deepEqual(countNodes(root), {body: 1, '#text': 1}, 'LI inside BODY (count)');

	parser = new tinymce.html.DomParser({}, schema);
	root = parser.parse('<p>a<ul><li>b</li><li>c</li></ul>d</p>');
	equals(serializer.serialize(root), '<p>a</p><ul><li>b</li><li>c</li></ul><p>d</p>', 'UL inside P');
	deepEqual(countNodes(root), {body: 1, p:2, ul:1, li:2, '#text': 4}, 'UL inside P (count)');
});

test('addNodeFilter', function() {
	var parser, result;

	expect(7);

	parser = new tinymce.html.DomParser({}, schema);
	parser.addNodeFilter('#comment', function(nodes, name, args) {
		result = {nodes : nodes, name : name, args : args};
	});
	parser.parse('text<!--text1-->text<!--text2-->');

	deepEqual(result.args, {}, 'Parser args');
	equals(result.name, '#comment', 'Parser filter result name');
	equals(result.nodes.length, 2, 'Parser filter result node');
	equals(result.nodes[0].name, '#comment', 'Parser filter result node(0) name');
	equals(result.nodes[0].value, 'text1', 'Parser filter result node(0) value');
	equals(result.nodes[1].name, '#comment', 'Parser filter result node(1) name');
	equals(result.nodes[1].value, 'text2', 'Parser filter result node(1) value');
});

test('addNodeFilter multiple names', function() {
	var parser, results = {};

	expect(14);

	parser = new tinymce.html.DomParser({}, schema);
	parser.addNodeFilter('#comment,#text', function(nodes, name, args) {
		results[name] = {nodes : nodes, name : name, args : args};
	});
	parser.parse('text1<!--text1-->text2<!--text2-->');

	deepEqual(results['#comment'].args, {}, 'Parser args');
	equals(results['#comment'].name, '#comment', 'Parser filter result name');
	equals(results['#comment'].nodes.length, 2, 'Parser filter result node');
	equals(results['#comment'].nodes[0].name, '#comment', 'Parser filter result node(0) name');
	equals(results['#comment'].nodes[0].value, 'text1', 'Parser filter result node(0) value');
	equals(results['#comment'].nodes[1].name, '#comment', 'Parser filter result node(1) name');
	equals(results['#comment'].nodes[1].value, 'text2', 'Parser filter result node(1) value');
	deepEqual(results['#text'].args, {}, 'Parser args');
	equals(results['#text'].name, '#text', 'Parser filter result name');
	equals(results['#text'].nodes.length, 2, 'Parser filter result node');
	equals(results['#text'].nodes[0].name, '#text', 'Parser filter result node(0) name');
	equals(results['#text'].nodes[0].value, 'text1', 'Parser filter result node(0) value');
	equals(results['#text'].nodes[1].name, '#text', 'Parser filter result node(1) name');
	equals(results['#text'].nodes[1].value, 'text2', 'Parser filter result node(1) value');
});

test('addNodeFilter with parser args', function() {
	var parser, result;

	expect(1);

	parser = new tinymce.html.DomParser({}, schema);
	parser.addNodeFilter('#comment', function(nodes, name, args) {
		result = {nodes : nodes, name : name, args : args};
	});
	parser.parse('text<!--text1-->text<!--text2-->', {value: 1});

	deepEqual(result.args, {value: 1}, 'Parser args');
});

test('addAttributeFilter', function() {
	var parser, result;

	expect(7);

	parser = new tinymce.html.DomParser({}, schema);
	parser.addAttributeFilter('src', function(nodes, name, args) {
		result = {nodes : nodes, name : name, args : args};
	});
	parser.parse('<b>a<img src="1.gif" />b<img src="1.gif" />c</b>');

	deepEqual(result.args, {}, 'Parser args');
	equals(result.name, 'src', 'Parser filter result name');
	equals(result.nodes.length, 2, 'Parser filter result node');
	equals(result.nodes[0].name, 'img', 'Parser filter result node(0) name');
	equals(result.nodes[0].attr('src'), '1.gif', 'Parser filter result node(0) attr');
	equals(result.nodes[1].name, 'img', 'Parser filter result node(1) name');
	equals(result.nodes[1].attr('src'), '1.gif', 'Parser filter result node(1) attr');
});

test('addAttributeFilter multiple', function() {
	var parser, results = {};

	expect(14);

	parser = new tinymce.html.DomParser({}, schema);
	parser.addAttributeFilter('src,href', function(nodes, name, args) {
		results[name] = {nodes : nodes, name : name, args : args};
	});
	parser.parse('<b><a href="1.gif">a</a><img src="1.gif" />b<img src="1.gif" /><a href="2.gif">c</a></b>');

	deepEqual(results['src'].args, {}, 'Parser args');
	equals(results['src'].name, 'src', 'Parser filter result name');
	equals(results['src'].nodes.length, 2, 'Parser filter result node');
	equals(results['src'].nodes[0].name, 'img', 'Parser filter result node(0) name');
	equals(results['src'].nodes[0].attr('src'), '1.gif', 'Parser filter result node(0) attr');
	equals(results['src'].nodes[1].name, 'img', 'Parser filter result node(1) name');
	equals(results['src'].nodes[1].attr('src'), '1.gif', 'Parser filter result node(1) attr');
	deepEqual(results['href'].args, {}, 'Parser args');
	equals(results['href'].name, 'href', 'Parser filter result name');
	equals(results['href'].nodes.length, 2, 'Parser filter result node');
	equals(results['href'].nodes[0].name, 'a', 'Parser filter result node(0) name');
	equals(results['href'].nodes[0].attr('href'), '1.gif', 'Parser filter result node(0) attr');
	equals(results['href'].nodes[1].name, 'a', 'Parser filter result node(1) name');
	equals(results['href'].nodes[1].attr('href'), '2.gif', 'Parser filter result node(1) attr');
});
</script>
</head>
<body>
	<h1 id="qunit-header">tinymce.html.DomParser tests</h1>
	<h2 id="qunit-banner"></h2>
	<div id="qunit-testrunner-toolbar"></div>
	<h2 id="qunit-userAgent"></h2>
	<ol id="qunit-tests"></ol>
	<div id="content"></div>
</body>
{'fraction_non_alphanumeric': 0.23545214679779325, 'fraction_numerical': 0.012712880786759414, 'mean_word_length': 5.2301255230125525, 'pattern_counts': {'":': 12, '<': 403, '<?xml version=': 0, '>': 403, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '107373', 'n_tokens_mistral': 7942, 'n_tokens_neox': 7745, 'n_words': 1733}