| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| 'use strict'; |
| |
| var fs = require('fs'); |
| var path = require('path'); |
| |
| var yaml = require('js-yaml'); |
| var optimist = require('optimist'); |
| var chalk = require('chalk'); |
| |
| var util = require('./util'); |
| |
| // constants |
| var VERBOSE_BY_DEFAULT = false; |
| |
| // globals |
| var verbose = VERBOSE_BY_DEFAULT; |
| |
| // helpers |
| function augmentEntry (originalEntry, prefix) { |
| var augmentedEntry = {}; |
| |
| // skip entries that have no URI |
| if (!originalEntry.url) { |
| return originalEntry; |
| } |
| |
| // get the path to the file to which this entry points |
| var filePath = path.join(prefix, originalEntry.url).replace('.html', '.md'); |
| |
| // skip entries that don't point to a valid file |
| if (!fs.existsSync(filePath)) { |
| console.warn(chalk.red('WARNING! Possible 404 in ToC: "' + filePath + '"; create the file to fix')); |
| return originalEntry; |
| } |
| |
| // read in the referenced file and get its front matter |
| var fileContents = fs.readFileSync(filePath).toString(); |
| var frontMatterString = util.getFrontMatterString(fileContents); |
| var frontMatter = yaml.load(frontMatterString); |
| |
| augmentedEntry.name = decideOnName(originalEntry, frontMatter); |
| augmentedEntry.url = originalEntry.url; |
| |
| if (frontMatter.description) { |
| augmentedEntry.description = frontMatter.description; |
| } |
| |
| return augmentedEntry; |
| } |
| |
| function decideOnName (originalEntry, frontMatter) { |
| // raise a warning for old-style ToC entry names |
| if (originalEntry.name && verbose === true) { |
| console.warn("'name' property will be ignored"); |
| } |
| |
| // error out if there is no name |
| if (!frontMatter.toc_title && !frontMatter.title) { |
| throw Error("can't find out name for ToC entry"); |
| } |
| |
| // use entry's name, and if it's not defined use the front matter name |
| return frontMatter.toc_title || frontMatter.title; |
| } |
| |
| // public API |
| function augmentToc (originalToc, prefix) { |
| var augmentedToc = []; |
| |
| if (typeof prefix === 'undefined') { |
| throw new Error('missing prefix for ToC'); |
| } |
| |
| // go through all original entries |
| for (var i = 0; i < originalToc.length; i++) { |
| var originalEntry = originalToc[i]; |
| var augmentedEntry = {}; |
| |
| // recurse for entries with children, replacing their children with |
| // their augmented equivalents |
| if (originalEntry.children) { |
| if (typeof originalEntry.name === 'undefined') { |
| throw new Error('entries with children must have a name'); |
| } |
| |
| augmentedEntry.name = originalEntry.name; |
| augmentedEntry.children = augmentToc(originalEntry.children, prefix); |
| |
| // replace regular entries with their augmented equivalents |
| } else { |
| augmentedEntry = augmentEntry(originalEntry, prefix); |
| } |
| |
| augmentedToc.push(augmentedEntry); |
| } |
| |
| return augmentedToc; |
| } |
| |
| function augmentString (srcTocString, prefix) { |
| var srcToc = yaml.load(srcTocString); |
| var augmentedToc = augmentToc(srcToc, prefix); |
| var augmentedTocString = yaml.dump(augmentedToc, { indent: 4 }); |
| |
| return augmentedTocString; |
| } |
| |
| function main () { |
| // get args |
| var argv = optimist |
| .usage('Usage: $0 [options]') |
| .demand('srcToc').describe('srcToc', 'the source ToC for the given directory') |
| .demand('srcRoot').describe('srcRoot', 'the directory containing files described by the ToC') |
| .boolean('verbose').describe('verbose', 'if true, print more helpful information').default('verbose', VERBOSE_BY_DEFAULT) |
| .alias('v', 'verbose') |
| .argv; |
| |
| var srcTocPath = argv.srcToc; |
| var srcRootPath = argv.srcRoot; |
| |
| // set globals |
| verbose = argv.verbose; |
| |
| // get augmented ToC |
| var srcTocString = fs.readFileSync(srcTocPath); |
| var augmentedTocString = augmentString(srcTocString, srcRootPath); |
| |
| console.log(util.generatedBy(__filename)); |
| console.log(augmentedTocString); |
| } |
| |
| if (require.main === module) { |
| main(); |
| } |
| |
| module.exports = { |
| augmentToc: augmentToc, |
| augmentString: augmentString |
| }; |