| // 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 util = require("./util"); |
| |
| // constants |
| var DEFAULT_PREFIX = ""; |
| 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("WARNING! Possible 404 in ToC: \"" + filePath + "\""); |
| 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, |
| }; |