1'use strict'; 2 3const common = require('../common'); 4// The doctool currently uses js-yaml from the tool/node_modules/eslint/ tree. 5try { 6 require('../../tools/node_modules/eslint/node_modules/js-yaml'); 7} catch { 8 common.skip('missing js-yaml (eslint not present)'); 9} 10 11const assert = require('assert'); 12const fs = require('fs'); 13const path = require('path'); 14const fixtures = require('../common/fixtures'); 15const json = require('../../tools/doc/json.js'); 16 17module.paths.unshift( 18 path.join(__dirname, '..', '..', 'tools', 'doc', 'node_modules')); 19const unified = require('unified'); 20const markdown = require('remark-parse'); 21 22function toJSON(input, filename, cb) { 23 function nullCompiler() { 24 this.Compiler = (tree) => tree; 25 } 26 27 unified() 28 .use(markdown) 29 .use(json.jsonAPI, { filename }) 30 .use(nullCompiler) 31 .process(input, cb); 32} 33 34// Outputs valid json with the expected fields when given simple markdown 35// Test data is a list of objects with two properties. 36// The file property is the file path. 37// The json property is some json which will be generated by the doctool. 38const testData = [ 39 { 40 file: fixtures.path('sample_document.md'), 41 json: { 42 type: 'module', 43 source: 'foo', 44 modules: [{ 45 textRaw: 'Sample Markdown', 46 name: 'sample_markdown', 47 modules: [{ 48 textRaw: 'Seussian Rhymes', 49 name: 'seussian_rhymes', 50 desc: '<ol>\n<li>fish</li>\n<li>fish</li>\n</ol>\n' + 51 '<ul>\n<li>Red fish</li>\n<li>Blue fish</li>\n</ul>', 52 type: 'module', 53 displayName: 'Seussian Rhymes' 54 }], 55 type: 'module', 56 displayName: 'Sample Markdown' 57 }] 58 } 59 }, 60 { 61 file: fixtures.path('order_of_end_tags_5873.md'), 62 json: { 63 type: 'module', 64 source: 'foo', 65 modules: [{ 66 textRaw: 'Title', 67 name: 'title', 68 modules: [{ 69 textRaw: 'Subsection', 70 name: 'subsection', 71 classMethods: [{ 72 textRaw: 'Static method: Buffer.from(array)', 73 type: 'classMethod', 74 name: 'from', 75 signatures: [ 76 { 77 params: [{ 78 textRaw: '`array` {Array}', 79 name: 'array', 80 type: 'Array' 81 }] 82 } 83 ] 84 }], 85 type: 'module', 86 displayName: 'Subsection' 87 }], 88 type: 'module', 89 displayName: 'Title' 90 }] 91 } 92 }, 93 { 94 file: fixtures.path('doc_with_yaml.md'), 95 json: { 96 type: 'module', 97 source: 'foo', 98 modules: [ 99 { 100 textRaw: 'Sample Markdown with YAML info', 101 name: 'sample_markdown_with_yaml_info', 102 modules: [ 103 { 104 textRaw: 'Foobar', 105 name: 'foobar', 106 meta: { 107 added: ['v1.0.0'], 108 changes: [] 109 }, 110 desc: '<p>Describe <code>Foobar</code> in more detail ' + 111 'here.</p>', 112 type: 'module', 113 displayName: 'Foobar' 114 }, 115 { 116 textRaw: 'Foobar II', 117 name: 'foobar_ii', 118 meta: { 119 added: ['v5.3.0', 'v4.2.0'], 120 changes: [ 121 { 'version': 'v4.2.0', 122 'pr-url': 'https://github.com/nodejs/node/pull/3276', 123 'description': 'The `error` parameter can now be ' + 124 'an arrow function.' 125 } 126 ] 127 }, 128 desc: '<p>Describe <code>Foobar II</code> in more detail ' + 129 'here. fg(1)</p>', 130 type: 'module', 131 displayName: 'Foobar II' 132 }, 133 { 134 textRaw: 'Deprecated thingy', 135 name: 'deprecated_thingy', 136 meta: { 137 added: ['v1.0.0'], 138 deprecated: ['v2.0.0'], 139 changes: [] 140 }, 141 desc: '<p>Describe <code>Deprecated thingy</code> in more ' + 142 'detail here. fg(1p)</p>', 143 type: 'module', 144 displayName: 'Deprecated thingy' 145 }, 146 { 147 textRaw: 'Something', 148 name: 'something', 149 desc: '<!-- This is not a metadata comment -->\n<p>' + 150 'Describe <code>Something</code> in more detail here.</p>', 151 type: 'module', 152 displayName: 'Something' 153 } 154 ], 155 type: 'module', 156 displayName: 'Sample Markdown with YAML info' 157 } 158 ] 159 } 160 }, 161 { 162 file: fixtures.path('doc_with_backticks_in_headings.md'), 163 json: { 164 type: 'module', 165 source: 'foo', 166 modules: [ 167 { 168 textRaw: 'Fhqwhgads', 169 name: 'fhqwhgads', 170 properties: [ 171 { 172 name: 'fullName', 173 textRaw: '`Fqhqwhgads.fullName`' 174 } 175 ], 176 classMethods: [ 177 { 178 name: 'again', 179 signatures: [ 180 { 181 params: [] 182 } 183 ], 184 textRaw: 'Static method: `Fhqwhgads.again()`', 185 type: 'classMethod' 186 } 187 ], 188 classes: [ 189 { 190 textRaw: 'Class: `ComeOn`', 191 type: 'class', 192 name: 'ComeOn' 193 } 194 ], 195 ctors: [ 196 { 197 name: 'Fhqwhgads', 198 signatures: [ 199 { 200 params: [] 201 } 202 ], 203 textRaw: 'Constructor: `new Fhqwhgads()`', 204 type: 'ctor' 205 } 206 ], 207 methods: [ 208 { 209 textRaw: '`everybody.to(limit)`', 210 type: 'method', 211 name: 'to', 212 signatures: [{ params: [] }] 213 } 214 ], 215 events: [ 216 { 217 textRaw: "Event: `'FHQWHfest'`", 218 type: 'event', 219 name: 'FHQWHfest', 220 params: [] 221 } 222 ], 223 type: 'module', 224 displayName: 'Fhqwhgads' 225 } 226 ] 227 } 228 } 229]; 230 231testData.forEach((item) => { 232 fs.readFile(item.file, 'utf8', common.mustCall((err, input) => { 233 assert.ifError(err); 234 toJSON(input, 'foo', common.mustCall((err, output) => { 235 assert.ifError(err); 236 assert.deepStrictEqual(output.json, item.json); 237 })); 238 })); 239}); 240