generate-readme-toc.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. const stream = require('stream');
  2. const reader = require('./reader.js');
  3. const header = `
  4. ## Table of Content
  5. <table>
  6. <thead>
  7. <th>Function</th>
  8. <th>Description</th>
  9. <th>Documentation</th>
  10. </thead>
  11. <tbody>
  12. `;
  13. const footer = `
  14. </tbody>
  15. </table>
  16. `
  17. function JSDocHeaderId({extraReturn, returnType, functionName, functionArgs}) {
  18. code = '';
  19. // function name
  20. if (extraReturn) {
  21. code += `[${returnType}, extra] = cephes.${functionName}(`;
  22. } else {
  23. code += `${returnType} = cephes.${functionName}(`;
  24. }
  25. // function arguments
  26. for (const {type, isPointer, isArray, fullType, name} of functionArgs) {
  27. if (isPointer) continue;
  28. if (isArray && type === 'double') {
  29. code += `${name}: Float64Array, `;
  30. } else if (!isArray) {
  31. code += `${name}: ${type}, `;
  32. } else {
  33. throw new Error(`unsupported type: ${fullType}`);
  34. }
  35. }
  36. // Remove training comma
  37. code = code.slice(0, -2);
  38. // finish function header
  39. code += ')';
  40. return code.replace(/[ ]/g, '-').replace(/[=,.():\[\]]/g, '').toLowerCase();
  41. }
  42. class TocGenerator extends stream.Transform {
  43. constructor() {
  44. super({ objectMode: true });
  45. this.push(header);
  46. this._previuseCategory = '';
  47. }
  48. _transform(data, encoding, done) {
  49. const {
  50. category, description,
  51. returnType, functionName, functionArgs
  52. } = data;
  53. // Check if there is extra data returned
  54. const extraReturn = functionArgs.some((arg) => arg.isPointer);
  55. //
  56. // Start code generation
  57. //
  58. let code = '';
  59. //
  60. // Add category header
  61. //
  62. if (this._previuseCategory !== category) {
  63. this._previuseCategory = category;
  64. code += ' <tr>\n';
  65. code += ` <td colspan="3"><strong>${category}</strong></td>\n`;
  66. code += ' </tr>\n';
  67. }
  68. //
  69. // function
  70. //
  71. code += ' <tr>\n';
  72. // function name
  73. code += ' <td><code>';
  74. code += `${functionName}(`;
  75. // function arguments
  76. for (const {isPointer, name} of functionArgs) {
  77. if (isPointer) continue;
  78. code += `${name}, `;
  79. }
  80. // Remove training comma
  81. code = code.slice(0, -2);
  82. // finish function
  83. code += ')';
  84. code += '</code></td>\n';
  85. //
  86. // Description
  87. //
  88. code += ` <td>${description}</td>\n`;
  89. //
  90. // Documentation
  91. //
  92. code += ' <td>';
  93. code += `<a href="http://www.netlib.org/cephes/doubldoc.html#${functionName}">c-doc</a>`;
  94. code += '&nbsp;&nbsp;&#8226;&nbsp;&nbsp;';
  95. code += `<a href="#${JSDocHeaderId({extraReturn, returnType, functionName, functionArgs})}">js-doc</a>`;
  96. code += '</td>\n';
  97. code += '</tr>\n';
  98. this.push(code);
  99. done(null);
  100. }
  101. _flush(done) {
  102. this.push(footer);
  103. done(null);
  104. }
  105. }
  106. process.stdin
  107. .pipe(reader())
  108. .pipe(new TocGenerator())
  109. .pipe(process.stdout)