summaryrefslogtreecommitdiff
path: root/test/doctool/test-doctool-html.js
blob: 11b28dc8a2a717d2b92a135fdc6aaa04991fd24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'use strict';

const common = require('../common');
// The doctool currently uses js-yaml from the tool/node_modules/eslint/ tree.
try {
  require('../../tools/node_modules/eslint/node_modules/js-yaml');
} catch {
  common.skip('missing js-yaml (eslint not present)');
}

const assert = require('assert');
const { readFile } = require('fs');
const fixtures = require('../common/fixtures');
const html = require('../../tools/doc/html.js');
const path = require('path');

module.paths.unshift(
  path.join(__dirname, '..', '..', 'tools', 'doc', 'node_modules'));
const unified = require('unified');
const markdown = require('remark-parse');
const remark2rehype = require('remark-rehype');
const raw = require('rehype-raw');
const htmlStringify = require('rehype-stringify');

async function toHTML({ input, filename, nodeVersion }) {
  const content = unified()
    .use(markdown)
    .use(html.firstHeader)
    .use(html.preprocessText)
    .use(html.preprocessElements, { filename })
    .use(html.buildToc, { filename, apilinks: {} })
    .use(remark2rehype, { allowDangerousHTML: true })
    .use(raw)
    .use(htmlStringify)
    .processSync(input);

  return html.toHTML({ input, content, filename, nodeVersion });
}

// Test data is a list of objects with two properties.
// The file property is the file path.
// The html property is some HTML which will be generated by the doctool.
// This HTML will be stripped of all whitespace because we don't currently
// have an HTML parser.
const testData = [
  {
    file: fixtures.path('sample_document.md'),
    html: '<ol><li>fish</li><li>fish</li></ol>' +
      '<ul><li>Redfish</li><li>Bluefish</li></ul>'
  },
  {
    file: fixtures.path('order_of_end_tags_5873.md'),
    html: '<h3>ClassMethod: Buffer.from(array) <span> ' +
      '<a class="mark" href="#foo_class_method_buffer_from_array" ' +
      'id="foo_class_method_buffer_from_array">#</a> </span> </h3>' +
      '<ul><li><code>array</code><a ' +
      'href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/' +
      'Reference/Global_Objects/Array" class="type">&#x3C;Array></a></li></ul>'
  },
  {
    file: fixtures.path('doc_with_yaml.md'),
    html: '<h1>Sample Markdown with YAML info' +
      '<span><a class="mark" href="#foo_sample_markdown_with_yaml_info" ' +
      ' id="foo_sample_markdown_with_yaml_info">#</a></span></h1>' +
      '<h2>Foobar<span><a class="mark" href="#foo_foobar" ' +
      'id="foo_foobar">#</a></span></h2>' +
      '<div class="api_metadata"><span>Added in: v1.0.0</span></div> ' +
      '<p>Describe <code>Foobar</code> in more detail here.</p>' +
      '<h2>Foobar II<span><a class="mark" href="#foo_foobar_ii" ' +
      'id="foo_foobar_ii">#</a></span></h2><div class="api_metadata">' +
      '<details class="changelog"><summary>History</summary>' +
      '<table><tbody><tr><th>Version</th><th>Changes</th></tr>' +
      '<tr><td>v5.3.0, v4.2.0</td>' +
      '<td><p><span>Added in: v5.3.0, v4.2.0</span></p></td></tr>' +
      '<tr><td>v4.2.0</td><td><p>The <code>error</code> parameter can now be' +
      'an arrow function.</p></td></tr></tbody></table></details></div> ' +
      '<p>Describe <code>Foobar II</code> in more detail here.' +
      '<a href="http://man7.org/linux/man-pages/man1/fg.1.html"><code>fg(1)' +
      '</code></a></p><h2>Deprecated thingy<span><a class="mark" ' +
      'href="#foo_deprecated_thingy" id="foo_deprecated_thingy">#</a>' +
      '</span></h2><div class="api_metadata"><span>Added in: v1.0.0</span>' +
      '<span>Deprecated since: v2.0.0</span></div><p>Describe ' +
      '<code>Deprecated thingy</code> in more detail here.' +
      '<a href="http://man7.org/linux/man-pages/man1/fg.1p.html"><code>fg(1p)' +
      '</code></a></p><h2>Something<span><a class="mark" href="#foo_something' +
      '" id="foo_something">#</a></span></h2> ' +
      '<!-- This is not a metadata comment --> ' +
      '<p>Describe <code>Something</code> in more detail here. </p>'
  },
  {
    file: fixtures.path('sample_document.md'),
    html: '<ol><li>fish</li><li>fish</li></ol>' +
      '<ul><li>Red fish</li><li>Blue fish</li></ul>',
  },
  {
    file: fixtures.path('altdocs.md'),
    html: '<li><a href="https://nodejs.org/docs/latest-v8.x/api/foo.html">8.x',
  },
];

const spaces = /\s/g;

testData.forEach(({ file, html }) => {
  // Normalize expected data by stripping whitespace.
  const expected = html.replace(spaces, '');

  readFile(file, 'utf8', common.mustCall(async (err, input) => {
    assert.ifError(err);
    const output = await toHTML({ input: input,
                                  filename: 'foo',
                                  nodeVersion: process.version });

    const actual = output.replace(spaces, '');
    // Assert that the input stripped of all whitespace contains the
    // expected markup.
    assert(actual.includes(expected),
           `ACTUAL: ${actual}\nEXPECTED: ${expected}`);
  }));
});