Skip to content

Commit

Permalink
Generate index.json, pages and api.md for each package. Generate _sid…
Browse files Browse the repository at this point in the history
…ebar.md
  • Loading branch information
crucialfelix committed Dec 12, 2019
1 parent c790372 commit 64f95b2
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 72 deletions.
110 changes: 68 additions & 42 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,79 @@
- [Getting started](README.md)
- npm packages
- [supercolliderjs](packages/supercolliderjs/README.md)
- [@supercollider/server](packages/server/README.md)
- [Server](packages/server/Server.md)
- [options](packages/server/options.md)
- [OSC messages](packages/server/osc_msg.md)
- [mapping](packages/server/mapping.md)
- [bin/scsynth](packages/server/bin_scsynth.md)
- internals
- [SendOSC](packages/server/SendOSC.md)
- [allocators](packages/server/internals_allocators.md)
- [Store](packages/server/internals_Store.md)
- [node-watcher](packages/server/node-watcher.md)
- [@supercollider/server-plus](packages/server-plus/README.md)
- [ServerPlus](packages/server-plus/ServerPlus.md)
- [Synth](packages/server-plus/Synth.md)
- [Group](packages/server-plus/Group.md)
- [SynthDef](packages/server-plus/SynthDef.md)
- [Buffer](packages/server-plus/Buffer.md)
- [ControlBus](packages/server-plus/ControlBus.md)
- [AudioBus](packages/server-plus/AudioBus.md)
- [@supercollider/lang](packages/lang/README.md)
- [Lang](packages/lang/sclang.md)
- [options](packages/lang/options.md)
- [boot](packages/lang/boot.md)
- [SynthDefCompiler](packages/lang/SynthDefCompiler.md)
- [SynthDefResultType](packages/lang/SynthDefResultType.md)
- [SynthDefCompileRequest](packages/lang/SynthDefCompileRequest.md)
- [Errors](packages/lang/Errors.md)
- [@supercollider/dryads](packages/dryads/README.md)
- [play](packages/dryads/index.md)
- dryads
- [Synth](packages/dryads/Synth.md)
- [API](packages/dryads/api.md)
- [SCServer](packages/dryads/SCServer.md)
- [SCLang](packages/dryads/SCLang.md)
- [Group](packages/dryads/Group.md)
- [Synth](packages/dryads/Synth.md)
- [AudioBus](packages/dryads/AudioBus.md)
- [SCSynthDef](packages/dryads/SCSynthDef.md)
- [SynthControl](packages/dryads/SynthControl.md)
- [SynthEventList](packages/dryads/SynthEventList.md)
- [SynthStream](packages/dryads/SynthStream.md)
- [SCLang](packages/dryads/SCLang.md)
- [SCServer](packages/dryads/SCServer.md)
- middleware
- [scserver](packages/dryads/middleware_scserver.md)
- [SynthEventList](packages/dryads/SynthEventList.md)
- [layer](packages/dryads/layer.md)
- [dryadic](packages/dryads/dryadic.md)
- [play](packages/dryads/play.md)
- [h](packages/dryads/h.md)
- [@supercollider/lang](packages/lang/README.md)
- [API](packages/lang/api.md)
- [SCLang](packages/lang/SCLang.md)
- [boot](packages/lang/boot.md)
- [resolveOptions](packages/lang/resolveOptions.md)
- [SynthDefCompiler](packages/lang/SynthDefCompiler.md)
- [SCLangError](packages/lang/SCLangError.md)
- [@supercollider/logger](packages/logger/README.md)
- [API](packages/logger/api.md)
- [Logger](packages/logger/Logger.md)
- [@supercollider/osc](packages/osc/README.md)
- [packing](packages/osc/packing.md)
- [types](packages/osc/types.md)
- [timetags](packages/osc/timetags.md)
- [index](packages/osc/index.md)
- [API](packages/osc/api.md)
- [packMessage](packages/osc/packMessage.md)
- [packBundle](packages/osc/packBundle.md)
- [unpack](packages/osc/unpack.md)
- [unpackMessage](packages/osc/unpackMessage.md)
- [unpackBundle](packages/osc/unpackBundle.md)
- [pack](packages/osc/pack.md)
- [dateToTimetag](packages/osc/dateToTimetag.md)
- [timetagToDate](packages/osc/timetagToDate.md)
- [deltaTimeTag](packages/osc/deltaTimeTag.md)
- [asNTPTimeTag](packages/osc/asNTPTimeTag.md)
- [@supercollider/scapi](packages/scapi/README.md)
- [SCAPI](packages/scapi/SCAPI.md)
- [API](packages/scapi/api.md)
- [SCAPI](packages/scapi/SCAPI.md)
- [@supercollider/server](packages/server/README.md)
- [API](packages/server/api.md)
- [Server](packages/server/Server.md)
- [boot](packages/server/boot.md)
- [resolveOptions](packages/server/resolveOptions.md)
- [msg](packages/server/msg.md)
- [mapping](packages/server/mapping.md)
- [ServerState](packages/server/ServerState.md)
- [watchNodeNotifications](packages/server/watchNodeNotifications.md)
- [onNodeGo](packages/server/onNodeGo.md)
- [whenNodeGo](packages/server/whenNodeGo.md)
- [onNodeEnd](packages/server/onNodeEnd.md)
- [whenNodeEnd](packages/server/whenNodeEnd.md)
- [updateNodeState](packages/server/updateNodeState.md)
- [deltaTimeTag](packages/server/deltaTimeTag.md)
- [@supercollider/server-plus](packages/server-plus/README.md)
- [API](packages/server-plus/api.md)
- [Group](packages/server-plus/Group.md)
- [Synth](packages/server-plus/Synth.md)
- [AudioBus](packages/server-plus/AudioBus.md)
- [ControlBus](packages/server-plus/ControlBus.md)
- [Buffer](packages/server-plus/Buffer.md)
- [SynthDef](packages/server-plus/SynthDef.md)
- [ServerPlus](packages/server-plus/ServerPlus.md)
- [boot](packages/server-plus/boot.md)
- [supercolliderjs](packages/supercolliderjs/README.md)
- [API](packages/supercolliderjs/api.md)
- [server](packages/supercolliderjs/server.md)
- [dryads](packages/supercolliderjs/dryads.md)
- [lang](packages/supercolliderjs/lang.md)
- [map](packages/supercolliderjs/map.md)
- [msg](packages/supercolliderjs/msg.md)
- [SCLangError](packages/supercolliderjs/SCLangError.md)
- [resolveOptions](packages/supercolliderjs/resolveOptions.md)
- Guide
- [Guide](https://crucialfelix.gitbooks.io/supercollider-js-guide/content/)
- [Examples](https://github.com/crucialfelix/supercolliderjs-examples)
- [Examples](https://github.com/crucialfelix/supercolliderjs-examples)
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@
"clean": "lerna exec -- rimraf lib && lerna exec -- rm -f tsconfig.tsbuildinfo",
"docs:api": "./tasks/typedocs.sh",
"docs:md": "node ./tasks/make-docs.js",
"docs:build": "npm run docs:api && npm run docs:md",
"docs:serve": "docsify serve docs"
"docs:build": "npm run build && npm run docs:api && npm run docs:md",
"docs:serve": "docsify serve docs",
"docs:export-index": "lerna exec -- node $(PWD)/tasks/export-index.js"
},
"eslintIgnore": [
"node_modules",
Expand Down
71 changes: 71 additions & 0 deletions tasks/export-index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Typedocs does not detect a module's exports.
* I should see if I can fix that.
*
* This script loads the index file for a package
* and converts the exports to a nested tree of names
* and saves this as index.json
*/
const fs = require("fs");
const self = require(process.cwd() + "/");

const asNames = (object, name) => {
if (!typeof object === "object") {
return name;
}

if (Array.isArray(object)) {
return object.map((x, i) => asNames(x, String(i)));
}

if (isPlainObject(object)) {
const mapped = {};
for (const key in object) {
if (object.hasOwnProperty(key)) {
const element = object[key];
const name = asNames(element, key);
// const emptyObject = name && (name.constructor === Object || Object.entries(name).length === 0);
if (name) {
mapped[key] = name;
}
}
}
return mapped;
}
// if has no name then it is an instrinsic
return object.name;
};

const result = asNames(self);
const json = JSON.stringify(result, null, 2);
fs.writeFileSync("./index.json", json);

// https://github.com/jonschlinkert/is-plain-object/blob/master/index.js
function isObjectObject(o) {
return isObject(o) === true && Object.prototype.toString.call(o) === "[object Object]";
}

function isPlainObject(o) {
if (isObjectObject(o) === false) return false;

// If has modified constructor
const ctor = o.constructor;
if (typeof ctor !== "function") return false;

// If has modified prototype
const prot = ctor.prototype;
if (isObjectObject(prot) === false) return false;

// If constructor does not have an Object-specific method
if (prot.hasOwnProperty("isPrototypeOf") === false) {
return false;
}

// Most likely a plain Object
return true;
}

// https://github.com/jonschlinkert/isobject/blob/master/index.js
function isObject(val) {
return val != null && typeof val === "object" && Array.isArray(val) === false;
}
70 changes: 64 additions & 6 deletions tasks/make-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const Mustache = require("mustache");
const path = require("path");
const fs = require("fs");
const fsp = fs.promises;
const { renderDocForName } = require("./render-api");
const { renderDocForName, renderIndexJson } = require("./render-api");

const root = path.resolve(path.join(__dirname, ".."));

Expand All @@ -15,8 +15,11 @@ const typedocRoot = "https://crucialfelix.github.io/supercolliderjs";
// TODO: should be a fixed path for each to api.md
const docsRoot = "http://localhost:3000/#";

const packageNames = async () =>
(await fsp.readdir(path.join(root, "packages"))).filter(name => name.match(/^[a-z\-]+$/));
const packageNames = async () => {
const names = (await fsp.readdir(path.join(root, "packages"))).filter(name => name.match(/^[a-z\-]+$/));
// sort favored first
return names;
};

async function fileExists(...paths) {
return fsp.stat(path.join(root, ...paths)).then(
Expand All @@ -26,6 +29,8 @@ async function fileExists(...paths) {
}

const readFile = (...paths) => fs.readFileSync(path.join(root, ...paths), { encoding: "utf-8" });
const readJson = (...paths) => JSON.parse(readFile(...paths));
const writeFile = (paths, content) => fs.writeFileSync(path.join(root, ...paths), content, { encoding: "utf-8" });

const triple = "```";

Expand Down Expand Up @@ -80,6 +85,36 @@ async function renderTpl(tpl, destPath, data) {
await fsp.writeFile(path.join(root, destPath), content);
}

const mdLink = (title, links) => `[${title}](${links.join("/")})`;
const isString = thing => typeof thing === "string";

async function generateSidebar(packages) {
const sb = [];
sb.push("- " + mdLink("Getting started", ["README.md"]));
sb.push("- npm packages");
packages.forEach(short => {
const index = readJson("packages", short, "index.json");
const { name } = readJson("packages", short, "package.json");
sb.push(` - ${mdLink(name, ["packages", short, "README.md"])}`);
sb.push(` - ` + mdLink("API", ["packages", short, "api.md"]));
// push one for each top level export
for (const [key, value] of Object.entries(index)) {
if (isString(value)) {
sb.push(` - ` + mdLink(value, ["packages", short, value + ".md"]));
} else {
// it's a module
sb.push(` - ` + mdLink(key, ["packages", short, key + ".md"]));
}
}
});
sb.push("- Guide");
sb.push(" - " + mdLink("Guide", ["https://crucialfelix.gitbooks.io/supercollider-js-guide/content/"]));
sb.push(" - " + mdLink("Examples", ["https://github.com/crucialfelix/supercolliderjs-examples"]));
const content = sb.join("\n");
// console.log(content);
writeFile(["docs", "_sidebar.md"], content);
}

async function parseSidebar() {
// auto generate md files if they are listed in the sidebar
const sidebar = readFile("docs", "_sidebar.md");
Expand Down Expand Up @@ -116,7 +151,6 @@ function generateAutodocument(package, { title, filename }) {
const BBBR = "}}}";

const fullname = filename.replace("_", "/").replace(".md", "");
console.log({ filename, fullname, title, package });

const body = `# ${BBBL}name${BBBR} ${title}
Expand All @@ -126,10 +160,29 @@ ${BBL}#api${BBR}${package}:${fullname}${BBL}/api${BBR}
return body;
}

/**
* Make api.md file for a package
*/
function generateApi(name, short, packages) {
const index = readJson("packages", short, "index.json");
// would want to know which file/url to link to for all of these
// based on the sidebar? you would need a different way to specify pages to make.
const content = renderIndexJson(index);

const body = `# ${name}
${content}
`;
// yes there is stuff there
// console.log({ content, body });

writeFile(["docs", "src", "packages", short, "api.md"], body);
}

async function main(version) {
const packages = await packageNames();

const pkg = JSON.parse(readFile("package.json"));
const pkg = readJson("package.json");

const rootData = {
name: pkg.name,
Expand All @@ -148,10 +201,12 @@ async function main(version) {
// _coverpage
await renderTplPath("docs/src/_coverpage.md", "docs/_coverpage.md", rootData);

await generateSidebar(packages);

const autos = await parseSidebar();

for (const pkgdir of packages) {
const pkg = JSON.parse(readFile("packages", pkgdir, "package.json"));
const pkg = readJson("packages", pkgdir, "package.json");
const short = pkg.name.replace("@supercollider/", "");
const data = {
...rootData,
Expand All @@ -162,6 +217,9 @@ async function main(version) {
homepage: pkg.hompage,
};

// generate api.md file for the exports of a module
generateApi(pkg.name, short, packages);

// generate autodocument for each entry in sidebar
for (const sidebarLink of autos[short] || []) {
if (!(await fileExists("docs/src/packages", short, sidebarLink.filename))) {
Expand Down
Loading

0 comments on commit 64f95b2

Please sign in to comment.