docusaurus/lib/server/readMetadata.js
Joel Marcey 77535d80f2 The complete move to MIT license (#115)
- headers in .js files
- update README and LICENSE year

Testing:

grep BSD, Patents, patents turned up nothing
2017-10-05 11:14:49 -07:00

336 lines
8.5 KiB
JavaScript

/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const CWD = process.cwd();
const path = require("path");
const fs = require("fs");
const glob = require("glob");
const chalk = require("chalk");
const siteConfig = require(CWD + "/siteConfig.js");
const versionFallback = require("./versionFallback.js");
const ENABLE_VERSIONING = fs.existsSync(CWD + "/versions.json");
let languages;
if (fs.existsSync(CWD + "/languages.js")) {
languages = require(CWD + "/languages.js");
} else {
languages = [
{
enabled: true,
name: "English",
tag: "en"
}
];
}
// returns map from id to object containing sidebar ordering info
function readSidebar() {
let allSidebars;
if (fs.existsSync(CWD + "/sidebars.json")) {
allSidebars = require(CWD + "/sidebars.json");
} else {
allSidebars = {};
}
Object.assign(allSidebars, versionFallback.sidebarData());
const order = {};
Object.keys(allSidebars).forEach(sidebar => {
const categories = allSidebars[sidebar];
let ids = [];
let categoryOrder = [];
Object.keys(categories).forEach(category => {
ids = ids.concat(categories[category]);
for (let i = 0; i < categories[category].length; i++) {
categoryOrder.push(category);
}
});
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
let previous, next;
if (i > 0) previous = ids[i - 1];
if (i < ids.length - 1) next = ids[i + 1];
order[id] = {
previous: previous,
next: next,
sidebar: sidebar,
category: categoryOrder[i]
};
}
});
return order;
}
// split markdown header
function splitHeader(content) {
const lines = content.split("\n");
let i = 1;
for (; i < lines.length - 1; ++i) {
if (lines[i] === "---") {
break;
}
}
return {
header: lines.slice(1, i + 1).join("\n"),
content: lines.slice(i + 1).join("\n")
};
}
// Extract markdown metadata header
function extractMetadata(content) {
const metadata = {};
const both = splitHeader(content);
// if no content returned, then that means there was no header, and both.header is the content
if (!both.content) {
return {metadata, rawContent: both.header};
}
const lines = both.header.split("\n");
for (let i = 0; i < lines.length - 1; ++i) {
const keyvalue = lines[i].split(":");
const key = keyvalue[0].trim();
let value = keyvalue.slice(1).join(":").trim();
try {
value = JSON.parse(value);
} catch (e) {}
metadata[key] = value;
}
return {metadata, rawContent: both.content};
}
// process the metadata for a document found in the docs folder
function processMetadata(file) {
const result = extractMetadata(fs.readFileSync(file, "utf8"));
const regexSubFolder = /docs\/(.*)\/.*/;
let language = "en";
const match = regexSubFolder.exec(file);
if (match) {
language = match[1];
}
const metadata = result.metadata;
const rawContent = result.rawContent;
metadata.source = path.basename(file);
if (!metadata.id) {
metadata.id = path.basename(file, path.extname(file));
}
if (metadata.id.includes("/")) {
throw new Error('Document id cannot include "/".');
}
if (!metadata.title) {
metadata.title = metadata.id;
}
if (languages.length === 1 && !siteConfig.useEnglishUrl) {
metadata.permalink = "docs/" + metadata.id + ".html";
} else {
metadata.permalink = "docs/" + language + "/" + metadata.id + ".html";
}
if (ENABLE_VERSIONING) {
metadata.version = "next";
if (languages.length === 1 && !siteConfig.useEnglishUrl) {
metadata.permalink = metadata.permalink.replace("docs/", "docs/next/");
} else {
metadata.permalink = metadata.permalink.replace(
"docs/" + language + "/",
"docs/" + language + "/next/"
);
}
}
// change ids previous, next
metadata.localized_id = metadata.id;
metadata.id = language + "-" + metadata.id;
metadata.language = language;
const order = readSidebar();
const id = metadata.localized_id;
if (order[id]) {
metadata.sidebar = order[id].sidebar;
metadata.category = order[id].category;
if (order[id].next) {
metadata.next_id = order[id].next;
metadata.next = language + "-" + order[id].next;
}
if (order[id].previous) {
metadata.previous_id = order[id].previous;
metadata.previous = language + "-" + order[id].previous;
}
}
return {metadata, rawContent: rawContent};
}
// process metadata for all docs and save into core/metadata.js
function generateDocsMetadata() {
const order = readSidebar();
const regexSubFolder = /translated_docs\/(.*)\/.*/;
const enabledLanguages = [];
languages.filter(lang => lang.enabled).map(lang => {
enabledLanguages.push(lang.tag);
});
const metadatas = {};
// metadata for english files
let files = glob.sync(CWD + "/../docs/**");
files.forEach(file => {
let language = "en";
const extension = path.extname(file);
if (extension === ".md" || extension === ".markdown") {
const res = processMetadata(file);
if (!res) {
return;
}
let metadata = res.metadata;
metadatas[metadata.id] = metadata;
}
});
// metadata for non-english docs
files = glob.sync(CWD + "/translated_docs/**");
files.forEach(file => {
let language = "en";
const match = regexSubFolder.exec(file);
if (match) {
language = match[1];
}
if (enabledLanguages.indexOf(language) === -1) {
return;
}
const extension = path.extname(file);
if (extension === ".md" || extension === ".markdown") {
const res = processMetadata(file);
if (!res) {
return;
}
let metadata = res.metadata;
metadatas[metadata.id] = metadata;
}
});
// metadata for versioned docs
const versionData = versionFallback.docData();
versionData.forEach(metadata => {
const id = metadata.localized_id;
if (order[id]) {
metadata.sidebar = order[id].sidebar;
metadata.category = order[id].category;
if (order[id].next) {
metadata.next_id = order[id].next.replace(
"version-" + metadata.version + "-",
""
);
metadata.next = metadata.language + "-" + order[id].next;
}
if (order[id].previous) {
metadata.previous_id = order[id].previous.replace(
"version-" + metadata.version + "-",
""
);
metadata.previous = metadata.language + "-" + order[id].previous;
}
}
metadatas[metadata.id] = metadata;
});
fs.writeFileSync(
__dirname + "/../core/metadata.js",
"/**\n" +
" * @generated\n" +
" */\n" +
"module.exports = " +
JSON.stringify(metadatas, null, 2) +
";"
);
}
// process metadata for blog posts and save into core/MetadataBlog.js
function generateBlogMetadata() {
const metadatas = [];
let files = glob.sync(CWD + "/blog/**/*.*");
if (!files || files.length == 0) {
console.error(
`${chalk.yellow(
CWD + "/blog/ appears to be empty"
)} Make sure you've put your blog files in your Docusaurus 'website' folder.`
);
}
files.sort().reverse().forEach(file => {
const extension = path.extname(file);
if (extension !== ".md" && extension !== ".markdown") {
return;
}
// Transform
// 2015-08-13-blog-post-name-0.5.md
// into
// 2015/08/13/blog-post-name-0-5.html
const filePath = path
.basename(file)
.replace("-", "/")
.replace("-", "/")
.replace("-", "/")
.replace(/\./g, "-")
.replace(/\-md$/, ".html");
const result = extractMetadata(fs.readFileSync(file, {encoding: "utf8"}));
const rawContent = result.rawContent;
const metadata = Object.assign(
{path: filePath, content: rawContent},
result.metadata
);
metadata.id = metadata.title;
// Extract, YYYY, MM, DD from the file name
let filePathDateArr = path.basename(file).toString().split("-");
metadata.date = new Date(
filePathDateArr[0] +
"-" +
filePathDateArr[1] +
"-" +
filePathDateArr[2] +
"T06:00:00.000Z"
);
metadatas.push(metadata);
});
fs.writeFileSync(
__dirname + "/../core/MetadataBlog.js",
"/**\n" +
" * @generated\n" +
" */\n" +
"module.exports = " +
JSON.stringify(metadatas, null, 2) +
";"
);
}
module.exports = {
readSidebar,
extractMetadata,
processMetadata,
generateDocsMetadata,
generateBlogMetadata
};