/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
"use strict";
var fs = require("fs");
var glob = require("glob");
var mkdirp = require("mkdirp");
var optimist = require("optimist");
var path = require("path");
var removeMd = require("remove-markdown");
var extractDocs = require("./extractDocs");
var argv = optimist.argv;
var slugify = require("../core/slugify");
/* =========== Utils =========== */
function backtickify(str) {
var escaped =
"`" +
str
.replace(/\\/g, "\\\\")
.replace(/`/g, "\\`")
.replace(/{/g, "\\{") +
"`";
// Replace require( with require\( so node-haste doesn't replace example
// require calls in the docs
return escaped.replace(/require\(/g, "require\\(");
}
function removeCommentsFromDocblock(docblock) {
return docblock
.trim("\n ")
.replace(/^\/\*+/, "")
.replace(/\*\/$/, "")
.split("\n")
.map(function(line) {
return line.trim().replace(/^\* ?/, "");
})
.join("\n");
}
function removeLineBreaks(content) {
if (content) {
return content.trim("").replace(/\n/g, "");
}
return content;
}
// Filesystem
function rmFile(file) {
try {
fs.unlinkSync(file);
} catch (e) {
/* seriously, unlink throws when the file doesn't exist :( */
}
}
function writeFileAndCreateFolder(file, content) {
mkdirp.sync(file.replace(new RegExp("/[^/]*$"), ""));
fs.writeFileSync(file, content);
}
// Sorting
function sortByRequired(props, nameA, nameB) {
var a = props[nameA];
var b = props[nameB];
if (a.required && !b.required) {
return -1;
}
if (b.required && !a.required) {
return 1;
}
if (a.deprecationMessage && !b.deprecationMessage) {
return 1;
}
if (b.deprecationMessage && !a.deprecationMessage) {
return -1;
}
return 0;
}
function sortByPlatform(props, nameA, nameB) {
var a = props[nameA];
var b = props[nameB];
if (a.platforms && !b.platforms) {
return 1;
}
if (b.platforms && !a.platforms) {
return -1;
}
// Cheap hack: use < on arrays of strings to compare the two platforms
if (a.platforms < b.platforms) {
return -1;
}
if (a.platforms > b.platforms) {
return 1;
}
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
}
// Types
function getNamedTypes(typedefs) {
const namedTypes = {};
typedefs &&
typedefs.forEach(typedef => {
if (typedef.name) {
const type = typedef.name.toLowerCase();
namedTypes[type] = 1;
}
});
return namedTypes;
}
function extractPlatformFromProps(props) {
for (var key in props) {
var prop = props[key];
var description = prop.description || "";
var platforms = description.match(/\@platform (.+)/);
var platformArray = [];
if (platforms) {
platformArray = platforms[1].replace(/ /g, "").split(",");
}
description = description.replace(/\@platform (.+)/, "");
prop.description = description;
prop.platforms = platformArray;
}
}
function renderTypehintRec(typehint) {
if (typehint.type === "simple") {
return typehint.value;
}
if (typehint.type === "generic") {
return (
renderTypehintRec(typehint.value[0]) +
"<" +
renderTypehintRec(typehint.value[1]) +
">"
);
}
return JSON.stringify(typehint);
}
function renderTypehint(typehint) {
if (typeof typehint === "object" && typehint.name) {
return renderType(typehint);
}
try {
var typehint = JSON.parse(typehint);
} catch (e) {
return typehint;
}
return renderTypehintRec(typehint);
}
function renderTypeNameLink(typeName, docPath, namedTypes) {
const ignoreTypes = [
"string",
"number",
"boolean",
"object",
"function",
"array"
];
const typeNameLower = typeName.toLowerCase();
if (ignoreTypes.indexOf(typeNameLower) !== -1 || !namedTypes[typeNameLower]) {
return typeName;
}
return "[" + typeName + "](" + docPath + "#" + typeNameLower + ")";
}
function renderTypeWithLinks(type, docTitle, namedTypes) {
if (!type || !type.names) {
return "";
}
const docPath = docTitle
? "docs/" + docTitle.toLowerCase() + ".html"
: "docs/";
return type.names.map(typeName =>
renderTypeNameLink(typeName, docPath, namedTypes)
);
}
/* =========== Markdown Generation =========== */
function splitHeader(content) {
var lines = content.split(/\r?\n/);
for (var i = 1; i < lines.length - 1; ++i) {
if (lines[i] === "---") {
break;
}
}
return {
header: i < lines.length - 1 ? lines.slice(1, i + 1).join("\n") : null,
content: lines.slice(i + 1).join("\n")
};
}
// Extract markdown metadata header
function extractMetadata(content) {
var metadata = {};
var both = splitHeader(content);
var lines = both.header.split("\n");
for (var i = 0; i < lines.length - 1; ++i) {
var keyvalue = lines[i].split(":");
var key = keyvalue[0].trim();
var value = keyvalue
.slice(1)
.join(":")
.trim();
// Handle the case where you have "Community #10"
try {
value = JSON.parse(value);
} catch (e) {}
metadata[key] = value;
}
return { metadata: metadata, rawContent: both.content };
}
function generateMarkdownTOCForReferences(references, apiDoc) {
if (!references || !references.length) {
return "";
}
let markdown = "";
references
.filter(ref => {
return ref.name[0] !== "_";
})
.map(ref => {
markdown +=
"- [`" +
ref.name +
"`](docs/" +
slugify(apiDoc) +
".html#" +
slugify(ref.name) +
")\n";
});
return markdown;
}
function buildFrontmatter(metadata) {
return [
"---",
"id: " + metadata.id,
"title: " + metadata.title,
"layout: docs", // Force all to use regular docs layout
"category: " + metadata.category,
"permalink: " + metadata.permalink,
"next: " + metadata.next,
"previous: " + metadata.previous,
"---"
];
}
function generateMarkdownForTable(rows) {
let markdown = "";
rows.forEach(items => {
markdown += "| " + items.join(" | ") + " |\n";
});
return markdown + "\n\n";
}
function renderEnumValue(value) {
// Use single quote strings even when we are given double quotes
if (value.match(/^"(.+)"$/)) {
return "'" + value.slice(1, -1) + "'";
}
return value;
}
function renderType(type) {
const baseType = renderBaseType(type);
return type.nullable ? "[" + baseType + "]" : baseType;
}
var styleReferencePattern = /^[^.]+\.propTypes\.style$/;
function renderBaseType(type) {
if (type.name === "enum") {
if (typeof type.value === "string") {
return type.value;
}
return (
"enum(" + type.value.map(v => renderEnumValue(v.value)).join(", ") + ")"
);
}
if (type.name === "$Enum") {
if (type.elements[0].signature.properties) {
return type.elements[0].signature.properties
.map(p => `'${p.key}'`)
.join(" ‖ ");
}
return type.name;
}
if (type.name === "shape") {
return (
"object: {" +
spanJoinMapper(
Object.keys(type.value),
key => key + ": " + renderType(type.value[key]),
""
) +
"}"
);
}
if (type.name === "union") {
if (type.value) {
return spanJoinMapper(type.value, renderType, ", ");
}
return spanJoinMapper(type.elements, renderType, " ‖ ");
}
if (type.name === "arrayOf") {
return "array of " + renderType(type.value);
}
if (type.name === "instanceOf") {
return type.value;
}
if (type.name === "custom") {
if (styleReferencePattern.test(type.raw)) {
var name = type.raw.substring(0, type.raw.indexOf("."));
return "[" + name + "](docs/" + slugify(name) + ".html#style)";
}
if (type.raw === "ColorPropType") {
return "[color](docs/colors.html)";
}
if (type.raw === "EdgeInsetsPropType") {
return "object: {top: number, left: number, bottom: number, right: number}";
}
return type.raw;
}
if (type.name === "stylesheet") {
return "style";
}
if (type.name === "func") {
return "function";
}
if (type.name === "signature") {
return type.raw;
}
return type.raw || type.name;
}
function spanJoinMapper(elements, callback, separator) {
return (
"" +
elements.map((rawElement, ii) => {
const el = callback(rawElement);
return ii + 1 < elements.length ? "" + el + separator + "" : el;
}) +
""
);
}
/* =========== =========== */
function generateMarkdownReferenceForMethodExamples(examples) {
if (!examples || !examples.length) {
return "";
}
return examples.map(example => {
const re = /
(.*?)<\/caption>/gi;
const result = re.exec(example);
const caption = result ? result[1] + ":" : "Example:";
const code = example
.replace(/.*?<\/caption>/gi, "")
.replace(/^\n\n/, "");
return "\n\n" + caption + "\n\n```javascript\n" + code + "\n```\n\n";
});
}
function generateMarkdownReferenceForMethodParameters(
params,
apiDoc,
namedTypes
) {
if (!params || !params.length) {
return "";
}
if (!params[0].type || !params[0].type.names) {
return "";
}
const foundDescription = params.find(p => p.description);
if (!foundDescription) {
return "";
}
let tableRows = [
["Name", "Type", "Required", "Description"],
["-", "-", "-", "-"]
];
params
.filter(param => {
return param.name[0] !== "_";
})
.map(param => {
let tableRowItems = [];
tableRowItems.push(param.name);
tableRowItems.push(renderTypeWithLinks(param.type, apiDoc, namedTypes));
tableRowItems.push(param.optional ? "Yes" : "No");
tableRowItems.push(removeLineBreaks(param.description));
tableRows.push(tableRowItems);
});
if (tableRows.length < 3) {
return "";
}
return "**Parameters:**\n\n" + generateMarkdownForTable(tableRows);
}
function generateMarkdownReferenceForMethod(method, apiDoc, namedTypes) {
let markdown = "";
markdown += "### `" + method.name + "()`\n\n";
let modifiers = "";
if (method.modifiers && method.modifiers.length > 0) {
modifiers = method.modifiers.join(" ") + " ";
}
let signatureParams = "";
const params = method.params;
if (params && params.length) {
signatureParams = params
.map(param => {
var res = "";
if (param.optional) {
res += "[" + param.name + "]";
} else {
res += param.name;
}
param.type &&
param.type.names &&
(res += ": " + param.type.names.join(", "));
return res;
})
.join(", ");
}
let methodReturns = "";
if (method.returns && method.returns.type) {
methodReturns += ": " + renderTypehint(method.returns.type);
}
markdown +=
"```javascript\n" +
modifiers +
method.name +
"(" +
signatureParams +
")" +
methodReturns +
"\n```\n\n";
if (method.description) {
markdown += method.description + "\n\n";
} else if (method.docblock) {
markdown += removeCommentsFromDocblock(method.docblock) + "\n\n";
}
markdown += generateMarkdownReferenceForMethodParameters(
method.params,
apiDoc,
namedTypes
);
markdown += generateMarkdownReferenceForMethodExamples(method.examples);
return markdown;
}
function generateMarkdownReferenceForMethods(methods, apiDoc, namedTypes) {
if (!methods || !methods.length) {
return "";
}
let markdownForMethods = [];
methods
.filter(method => {
return method.name[0] !== "_";
})
.map(method => {
markdownForMethods.push(
generateMarkdownReferenceForMethod(method, apiDoc, namedTypes)
);
});
return markdownForMethods.join("\n\n---\n\n");
}
/* =========== =========== */
function generateMarkdownForTypeDefValues(values) {
if (!values || !values.length) {
return "";
}
if (!values[0].type || !values[0].type.names) {
return "";
}
let tableRows = [["Value", "Description"], ["-", "-"]];
values.map(value => {
let tableRowItems = [];
tableRowItems.push(removeLineBreaks(value.name));
tableRowItems.push(removeLineBreaks(value.description));
tableRows.push(tableRowItems);
});
if (tableRows.length < 3) {
return "";
}
return "**Constants:**\n\n" + generateMarkdownForTable(tableRows);
}
function generateMarkdownReferenceForTypeDefs(typedefs, apiDoc, namedTypes) {
if (!typedefs || !typedefs.length) {
return "";
}
let markdownForTypeDefs = [];
typedefs.map(typedef => {
markdownForTypeDefs.push(
generateMarkdownForTypeDef(typedef, apiDoc, namedTypes)
);
});
return markdownForTypeDefs.join("\n\n---\n\n");
}
function generateMarkdownForTypeDef(typedef, apiDoc, namedTypes) {
let markdown = "";
const { name, description, type, properties, values } = typedef;
markdown += "### " + name + "\n\n";
if (description) {
markdown += description + "\n\n";
}
const tableRows = [["Type"], ["-"], [type.names.join(", ")]];
markdown += generateMarkdownForTable(tableRows);
markdown += generateMarkdownForTypeDefProperties(
properties,
apiDoc,
namedTypes
);
markdown += generateMarkdownForTypeDefValues(values);
return markdown;
}
function generateMarkdownForTypeDefProperties(properties, apiDoc, namedTypes) {
if (!properties || !properties.length) {
return "";
}
if (!properties[0].type || !properties[0].type.names) {
return "";
}
let tableRows = [["Name", "Type", "Description"], ["-", "-", "-"]];
properties
.filter(property => {
return property.name[0] !== "_";
})
.map(property => {
let tableRowItems = [];
tableRowItems.push(
property.optional ? "[" + property.name + "]" : property.name
);
tableRowItems.push(
renderTypeWithLinks(property.type, apiDoc, namedTypes)
);
tableRowItems.push(removeLineBreaks(property.description));
tableRows.push(tableRowItems);
});
if (tableRows.length < 3) {
return "";
}
return "**Properties:**\n\n" + generateMarkdownForTable(tableRows);
}
/* =========== ComponentDoc =========== */
function generateMarkdownForComponentDocProp(name, prop, props, content) {
let markdown = "";
if (name === undefined) {
return markdown;
}
const { required, description, type, flowType } = prop;
let renderedType = "";
if (type || flowType) {
renderedType = renderType(flowType || type);
}
markdown += "### `" + name + "`\n\n";
if (prop.deprecationMessage) {
markdown += "**Deprecated.** ";
markdown += prop.deprecationMessage + "\n\n";
}
markdown += description + "\n\n";
const hasPlatforms =
prop.platforms !== undefined && prop.platforms.length > 0;
let tableHeader = ["Type", "Required"];
let tableInfoRow = [renderedType, required ? "Yes" : "No"];
if (hasPlatforms) {
tableHeader.push("Platform");
tableInfoRow.push(prop.platforms.map(platform => `${platform} `));
}
const tableRows = [tableHeader, tableHeader.map(() => "-"), tableInfoRow];
markdown += generateMarkdownForTable(tableRows);
if (prop.type && prop.type.name === "stylesheet") {
const stylesheetName = prop.type.value;
const style = content.styles[stylesheetName];
extractPlatformFromProps(style.props);
markdown += generateMarkdownForComponentDocStyleProps(style);
}
markdown += "\n\n";
return markdown;
}
function generateMarkdownForComponentDocStyleProp(name, prop) {
let markdown = "";
let renderedType = "";
if (prop.type) {
renderedType = renderType(prop.type);
}
const hasPlatforms = prop.platforms !== null && prop.platforms.length > 0;
markdown += " - **`" + name + "`**: " + renderedType;
if (hasPlatforms) {
markdown +=
" (" + prop.platforms.map(platform => `_${platform}_`).join(", ") + ")";
}
markdown += "\n\n";
if (prop.description) {
markdown += " " + prop.description.replace(/\n/g, "\n ") + "\n\n";
}
return markdown;
}
function generateMarkdownForComponentDocStyleProps(style) {
let markdown = "";
if (style.composes) {
style.composes.map(name => {
var link;
if (name === "LayoutPropTypes") {
name = "Layout Props";
link = "docs/" + slugify(name) + ".html#props";
} else if (name === "ShadowPropTypesIOS") {
name = "Shadow Props";
link = "docs/" + slugify(name) + ".html#props";
} else if (name === "TransformPropTypes") {
name = "Transforms";
link = "docs/" + slugify(name) + ".html#props";
} else {
name = name.replace("StylePropTypes", " Style Props");
link = "docs/" + slugify(name) + ".html#style";
}
markdown += " - [" + name + "...](" + link + ")\n\n";
});
}
Object.keys(style.props)
.sort(sortByPlatform.bind(null, style.props))
.sort(sortByRequired.bind(null, style.props))
.map(name => {
markdown += generateMarkdownForComponentDocStyleProp(
name,
style.props[name]
);
});
return markdown;
}
function generateMarkdownTOCForComponentDocProps(props, content) {
let markdown = "";
if (content.composes) {
content.composes.map(name => {
markdown +=
"* [" + name + " props...](docs/" + slugify(name) + ".html#props)\n";
});
}
Object.keys(props)
.sort(sortByPlatform.bind(null, props))
.sort(sortByRequired.bind(null, props))
.map(name => {
markdown +=
"- [`" +
name +
"`](docs/" +
slugify(content.componentName) +
".html#" +
slugify(name) +
")\n";
});
markdown += "\n\n";
return markdown;
}
function generateMarkdownReferenceForComponentDocProps(props, content) {
let markdownForProps = [];
Object.keys(props)
.sort(sortByPlatform.bind(null, props))
.sort(sortByRequired.bind(null, props))
.map(name => {
markdownForProps.push(
generateMarkdownForComponentDocProp(name, props[name], props, content)
);
});
return markdownForProps.join("---\n\n");
}
function generateMarkdownForComponentDoc(content, apiDoc) {
let markdown = "";
const { description, props, styles, methods, typedef } = content;
// Description
if (description) {
markdown += description + "\n\n";
}
const hasProps = props;
const hasMethods =
methods && methods.filter(method => method.name[0] !== "_").length > 0;
const hasTypeDefs = typedef && typedef.length > 0;
const namedTypes = getNamedTypes(content.typedef);
if (hasProps) {
extractPlatformFromProps(props);
markdown += "### Props\n\n";
markdown +=
generateMarkdownTOCForComponentDocProps(props, content) + "\n\n";
}
if (hasMethods) {
markdown += "### Methods\n\n";
markdown += generateMarkdownTOCForReferences(methods, apiDoc) + "\n\n";
}
if (hasTypeDefs) {
markdown += "### Type Definitions\n\n";
markdown += generateMarkdownTOCForReferences(typedef, apiDoc) + "\n\n";
}
markdown += "\n\n---\n\n";
markdown += "# Reference\n\n";
if (hasProps) {
markdown += "## Props\n\n";
markdown +=
generateMarkdownReferenceForComponentDocProps(props, content) + "\n\n";
}
if (hasMethods) {
markdown += "## Methods\n\n";
markdown +=
generateMarkdownReferenceForMethods(methods, apiDoc, namedTypes) + "\n\n";
}
if (hasTypeDefs) {
markdown += "## Type Definitions\n\n";
markdown +=
generateMarkdownReferenceForTypeDefs(typedef, apiDoc, content) + "\n\n";
}
return markdown;
}
/* =========== APIDoc =========== */
function generateMarkdownForAPIDoc(content, apiDoc) {
let markdown = "";
const { description, methods, properties, classes, typedef } = content;
// Description
if (content.docblock) {
markdown += removeCommentsFromDocblock(content.docblock);
markdown += "\n\n";
} else if (
content.class &&
content.class.length &&
content.class[0].description
) {
markdown += content.class[0].description;
markdown += "\n\n";
}
const namedTypes = getNamedTypes(content.typedef);
const hasMethods =
methods &&
methods.filter(method => {
return method.name[0] !== "_";
}).length > 0;
const hasProperties = properties && properties.length > 0;
const hasClasses = classes && classes.length > 0;
const hasTypeDefs = typedef && typedef.length > 0;
if (hasMethods) {
markdown += "### Methods\n\n";
markdown += generateMarkdownTOCForReferences(methods, apiDoc) + "\n\n";
}
if (hasProperties) {
markdown += "### Properties\n\n";
markdown += generateMarkdownTOCForReferences(properties, apiDoc) + "\n\n";
}
if (hasClasses) {
markdown += "### Classes\n\n";
markdown += generateMarkdownTOCForReferences(classes, apiDoc) + "\n\n";
}
if (hasTypeDefs) {
markdown += "### Type Definitions\n\n";
markdown += generateMarkdownTOCForReferences(typedef, apiDoc) + "\n\n";
}
markdown += "\n\n---\n\n";
markdown += "# Reference\n\n";
if (hasMethods) {
markdown += "## Methods\n\n";
markdown +=
generateMarkdownReferenceForMethods(methods, apiDoc, namedTypes) + "\n\n";
}
if (hasProperties) {
markdown += "## Properties\n\n";
markdown +=
generateMarkdownReferenceForAPIDocProperties(properties) + "\n\n";
}
if (hasClasses) {
markdown += "## Classes\n\n";
markdown +=
generateMarkdownReferenceForAPIDocClasses(classes, apiDoc, namedTypes) +
"\n\n";
}
if (hasTypeDefs) {
markdown += "## Type Definitions\n\n";
markdown +=
generateMarkdownReferenceForTypeDefs(typedef, apiDoc, namedTypes) +
"\n\n";
}
return markdown;
}
function generateMarkdownReferenceForAPIDocProperty(property) {
let markdown = "";
markdown += "####" + property.name;
if (property.type || property.flowType) {
markdown += ": " + renderType(property.flowType || property.type);
}
markdown += "\n\n";
if (property.docblock) {
markdown += removeCommentsFromDocblock(property.docblock);
}
}
function generateMarkdownReferenceForAPIDocProperties(properties) {
if (!properties || !properties.length) {
return "";
}
let markdownForProperties = [];
properties
.filter(property => {
return property.name[0] !== "_";
})
.map(property => {
markdownForProperties.push(
generateMarkdownReferenceForAPIDocProperty(property)
);
});
return markdownForProperties.join("\n\n---\n\n");
}
function generateMarkdownReferenceForAPIDocClass(cls, apiDoc, namedTypes) {
let markdown = "";
markdown += "## class " + cls.name;
if (cls.docblock) {
markdown += removeCommentsFromDocblock(cls.docblock) + "\n\n";
}
if (cls.methods && cls.methods.length > 0) {
markdown +=
"### Methods\n\n" +
generateMarkdownReferenceForMethods(cls.methods, apiDoc, namedTypes);
}
if (cls.properties && cls.properties.length > 0) {
markdown +=
"### Properties\n\n" +
generateMarkdownReferenceForAPIDocProperties(cls.properties);
}
return markdown;
}
function generateMarkdownReferenceForAPIDocClasses(
classes,
apiDoc,
namedTypes
) {
if (!classes || !classes.length) {
return "";
}
let markdownForClasses = [];
classes
.filter(cls => {
return cls.name[0] !== "_" && cls.ownerProperty[0] !== "_";
})
.map(cls => {
markdownForClasses.push(
generateMarkdownReferenceForAPIDocClass(cls, apiDoc, namedTypes)
);
});
return markdownForClasses.join("\n\n---\n\n");
}
/* =========== Building Docs =========== */
function buildAutodocsFile(metadata, content) {
console.log("[" + content.type + "] generating " + metadata.title);
const body =
content.type === "component" || content.type === "style"
? generateMarkdownForComponentDoc(content, metadata.title)
: generateMarkdownForAPIDoc(content, metadata.title);
const markdown = [...buildFrontmatter(metadata), body]
.filter(function(line) {
return line;
})
.join("\n");
return markdown;
}
function buildDocsFile(metadata, rawContent) {
const markdown = [...buildFrontmatter(metadata), rawContent]
.filter(function(line) {
return line;
})
.join("\n");
return markdown;
}
function execute(options) {
if (options === undefined) {
options = {};
}
var DOCS_MD_DIR = "build/react-native-tags/docs";
glob.sync("src/react-native/docs/*.*").forEach(rmFile);
var metadatas = {
files: []
};
function handleMarkdown(content, filename) {
if (content.slice(0, 3) !== "---") {
console.error(`Skipping non-markdown file: ${filename}:`);
console.log(content);
return;
}
const res = extractMetadata(content);
const metadata = res.metadata;
const rawContent = res.rawContent;
if (metadata.sidebar !== false) {
metadatas.files.push(metadata);
}
if (metadata.permalink && metadata.permalink.match(/^https?:/)) {
return;
}
metadata.filename = filename;
var layout =
metadata.layout[0].toUpperCase() + metadata.layout.substr(1) + "Layout";
let outputFile;
if (layout === "DocsLayout") {
outputFile = buildDocsFile(metadata, rawContent);
} else if (layout == "AutodocsLayout") {
outputFile = buildAutodocsFile(metadata, JSON.parse(rawContent));
}
writeFileAndCreateFolder(
"build/react-native-docs/" + metadata.permalink.replace(/\.html$/, ".md"),
outputFile
);
}
extractDocs().forEach(function(content) {
handleMarkdown(content, null);
});
var files = glob.sync(DOCS_MD_DIR + "**/*.md");
files.forEach(function(file) {
var content = fs.readFileSync(file, { encoding: "utf8" });
handleMarkdown(content, path.basename(file));
});
// we need to pass globals for the components to be configurable
// metadata is generated in this process which has access to process.env
// but the web pages are generated in a sandbox context and have only access to CommonJS module files
metadatas.config = Object.create(null);
Object.keys(process.env)
.filter(key => key.startsWith("RN_"))
.forEach(key => {
metadatas.config[key] = process.env[key];
});
}
console.log("convert!");
execute();
module.exports = execute;