augment_toc.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. 'use strict';
  18. var fs = require('fs');
  19. var path = require('path');
  20. var yaml = require('js-yaml');
  21. var optimist = require('optimist');
  22. var chalk = require('chalk');
  23. var util = require('./util');
  24. // constants
  25. var VERBOSE_BY_DEFAULT = false;
  26. // globals
  27. var verbose = VERBOSE_BY_DEFAULT;
  28. // helpers
  29. function augmentEntry (originalEntry, prefix) {
  30. var augmentedEntry = {};
  31. // skip entries that have no URI
  32. if (!originalEntry.url) {
  33. return originalEntry;
  34. }
  35. // get the path to the file to which this entry points
  36. var filePath = path.join(prefix, originalEntry.url).replace('.html', '.md');
  37. // skip entries that don't point to a valid file
  38. if (!fs.existsSync(filePath)) {
  39. console.warn(chalk.red('WARNING! Possible 404 in ToC: "' + filePath + '"; create the file to fix'));
  40. return originalEntry;
  41. }
  42. // read in the referenced file and get its front matter
  43. var fileContents = fs.readFileSync(filePath).toString();
  44. var frontMatterString = util.getFrontMatterString(fileContents);
  45. var frontMatter = yaml.load(frontMatterString);
  46. augmentedEntry.name = decideOnName(originalEntry, frontMatter);
  47. augmentedEntry.url = originalEntry.url;
  48. if (frontMatter.description) {
  49. augmentedEntry.description = frontMatter.description;
  50. }
  51. return augmentedEntry;
  52. }
  53. function decideOnName (originalEntry, frontMatter) {
  54. // raise a warning for old-style ToC entry names
  55. if (originalEntry.name && verbose === true) {
  56. console.warn("'name' property will be ignored");
  57. }
  58. // error out if there is no name
  59. if (!frontMatter.toc_title && !frontMatter.title) {
  60. throw Error("can't find out name for ToC entry");
  61. }
  62. // use entry's name, and if it's not defined use the front matter name
  63. return frontMatter.toc_title || frontMatter.title;
  64. }
  65. // public API
  66. function augmentToc (originalToc, prefix) {
  67. var augmentedToc = [];
  68. if (typeof prefix === 'undefined') {
  69. throw new Error('missing prefix for ToC');
  70. }
  71. // go through all original entries
  72. for (var i = 0; i < originalToc.length; i++) {
  73. var originalEntry = originalToc[i];
  74. var augmentedEntry = {};
  75. // recurse for entries with children, replacing their children with
  76. // their augmented equivalents
  77. if (originalEntry.children) {
  78. if (typeof originalEntry.name === 'undefined') {
  79. throw new Error('entries with children must have a name');
  80. }
  81. augmentedEntry.name = originalEntry.name;
  82. augmentedEntry.children = augmentToc(originalEntry.children, prefix);
  83. // replace regular entries with their augmented equivalents
  84. } else {
  85. augmentedEntry = augmentEntry(originalEntry, prefix);
  86. }
  87. augmentedToc.push(augmentedEntry);
  88. }
  89. return augmentedToc;
  90. }
  91. function augmentString (srcTocString, prefix) {
  92. var srcToc = yaml.load(srcTocString);
  93. var augmentedToc = augmentToc(srcToc, prefix);
  94. var augmentedTocString = yaml.dump(augmentedToc, { indent: 4 });
  95. return augmentedTocString;
  96. }
  97. function main () {
  98. // get args
  99. var argv = optimist
  100. .usage('Usage: $0 [options]')
  101. .demand('srcToc').describe('srcToc', 'the source ToC for the given directory')
  102. .demand('srcRoot').describe('srcRoot', 'the directory containing files described by the ToC')
  103. .boolean('verbose').describe('verbose', 'if true, print more helpful information').default('verbose', VERBOSE_BY_DEFAULT)
  104. .alias('v', 'verbose')
  105. .argv;
  106. var srcTocPath = argv.srcToc;
  107. var srcRootPath = argv.srcRoot;
  108. // set globals
  109. verbose = argv.verbose;
  110. // get augmented ToC
  111. var srcTocString = fs.readFileSync(srcTocPath);
  112. var augmentedTocString = augmentString(srcTocString, srcRootPath);
  113. console.log(util.generatedBy(__filename));
  114. console.log(augmentedTocString);
  115. }
  116. if (require.main === module) {
  117. main();
  118. }
  119. module.exports = {
  120. augmentToc: augmentToc,
  121. augmentString: augmentString
  122. };