From 608674b22c8913ae4ddb9e2d4231ec0cc8c92ed5 Mon Sep 17 00:00:00 2001 From: Lars Trieloff Date: Tue, 3 Dec 2019 14:13:50 +0000 Subject: [PATCH] feat(markdown): list nested schemas in README --- lib/filterRefs.js | 23 ++++++++++++++ lib/formatInfo.js | 70 ++++++++++++++++++++++++++++++++++++++++++ lib/formatname.js | 25 +++++++++++++++ lib/markdownBuilder.js | 27 ++++++++++++++++ lib/readmeBuilder.js | 69 +++++++++++++++++++++++++++++++++++++++++ lib/validateSchemas.js | 27 ++++++++++++++++ lib/writeMarkdown.js | 52 +++++++++++++++++++++++++++++++ 7 files changed, 293 insertions(+) create mode 100644 lib/filterRefs.js create mode 100644 lib/formatInfo.js create mode 100644 lib/formatname.js create mode 100644 lib/markdownBuilder.js create mode 100644 lib/readmeBuilder.js create mode 100644 lib/validateSchemas.js create mode 100644 lib/writeMarkdown.js diff --git a/lib/filterRefs.js b/lib/filterRefs.js new file mode 100644 index 00000000..7b205839 --- /dev/null +++ b/lib/filterRefs.js @@ -0,0 +1,23 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { filter } = require('ferrum'); + +/** + * Filters a sequence of schemas to exclude all schemas that are `$ref`erences + * to other schemas + * @param {Schema[]} schemas + */ +function filterRefs(schemas) { + return filter(schemas, schema => !schema.schema.$ref); +} + +module.exports = filterRefs; diff --git a/lib/formatInfo.js b/lib/formatInfo.js new file mode 100644 index 00000000..456cb100 --- /dev/null +++ b/lib/formatInfo.js @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { map } = require('ferrum'); +const fs = require('fs'); +const path = require('path'); +const unified = require('unified'); +const parse = require('remark-parse'); +const inspect = require('unist-util-inspect'); +const stringify = require('mdast-util-to-string'); +const { formatname } = require('./formatname'); + +function formatInfo({ extension }) { + function plaindescription(schema) { + try { + if (schema.path) { + const filename = path.resolve( + path.dirname(schema.path), + `${path.basename(schema.path, extension)}description.md`, + ); + const longdesc = fs.readFileSync(filename); + return longdesc.toString(); + } + } catch {} + return schema.schema.description || ''; + } + + function shorten(str) { + return str.split('\n')[0].split('.')[0]; + } + + const parser = unified() + .use(parse); + + function parsedescription(str) { + try { + const markdown = parser.parse(str); + return { + longdescription: markdown, + shortdescription: shorten(stringify(markdown)), + description: str, + }; + } catch { + return { + longdescription: {}, + shortdescription: '', + description: shorten(str), + }; + } + } + + return schemas => map(schemas, (schema) => { + const newobj = { + ...schema, + ...parsedescription(plaindescription(schema)), + title: formatname(schema), + }; + return newobj; + }); +} + +module.exports = formatInfo; diff --git a/lib/formatname.js b/lib/formatname.js new file mode 100644 index 00000000..b3110c28 --- /dev/null +++ b/lib/formatname.js @@ -0,0 +1,25 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +function formatname({ schema, root }) { + if (schema.title) { + return schema.title; + } else if (schema.type && typeof schema.type === 'string') { + if (root) { + return `Untitled ${schema.type} from ${formatname({ schema: root })}`; + } + return `Untitled ${schema.type}`; + } else if (root) { + return `Untitled Schema from ${formatname({ schema: root })}`; + } + return 'Untitled Schema'; +} +exports.formatname = formatname; diff --git a/lib/markdownBuilder.js b/lib/markdownBuilder.js new file mode 100644 index 00000000..ed5d817b --- /dev/null +++ b/lib/markdownBuilder.js @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { each, values } = require('ferrum'); +const { + root, paragraph, text, heading, +} = require('mdast-builder'); + +function build(schemas) { + // eslint-disable-next-line no-return-assign, no-param-reassign + each(values(schemas), schema => schema.markdown = root([ + // todo add more elements + heading(1, text(schema.title)), + paragraph(text('This is a schema.')), + ])); + return schemas; +} + +module.exports = build; diff --git a/lib/readmeBuilder.js b/lib/readmeBuilder.js new file mode 100644 index 00000000..01af791c --- /dev/null +++ b/lib/readmeBuilder.js @@ -0,0 +1,69 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { + map, pairs, pipe, filter, list: flist, +} = require('ferrum'); +const { + root, paragraph, text, heading, list, listItem, link, inlineCode, +} = require('mdast-builder'); +const inspect = require('unist-util-inspect'); + + +/** + * Generate the README.md + * @param {object} opts + */ +function build({ readme = true }) { + return (schemas) => { + if (readme) { + const toplevel = flist(pipe( + pairs(schemas), + filter(([_, schema]) => schema.direct), + map(([name, schema]) => listItem(paragraph([ + link(`./${name}.schema.md`, schema.shortdescription, [text(schema.title)]), + text(' – '), + inlineCode(schema.schema.$id), + ]))), + ), Array); + + const bytype = type => flist(pipe( + pairs(schemas), + filter(([_, schema]) => !schema.direct), + filter(([_, schema]) => schema.schema.type === type), + map(([name, schema]) => listItem(paragraph([ + link(`./${name}.schema.md`, schema.shortdescription, [text(schema.title)]), + text(' – '), + inlineCode(`${schema.id}#${schema.pointer}`), + ]))), + ), Array); + + const arrays = schemas.README = { + markdown: root([ + heading(1, text('README')), + heading(2, text('Top-level Schemas')), + list('unordered', toplevel), + heading(2, text('Other Schemas')), + + heading(3, text('Objects')), + list('unordered', bytype('object')), + + heading(3, text('Arrays')), + list('unordered', bytype('array')), + ]), + }; + return schemas; + } + return schemas; + }; +} + +module.exports = build; diff --git a/lib/validateSchemas.js b/lib/validateSchemas.js new file mode 100644 index 00000000..fcb04e74 --- /dev/null +++ b/lib/validateSchemas.js @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { map } = require('ferrum'); + +function validate(validator, logger) { + return schemas => map(schemas, (schema) => { + try { + validator.addSchema(schema.schema, schema.path); + return schema; + } catch (e) { + logger.error('Ajv processing error for schema at path', schema.path); + logger.error(e); + process.exit(1); + } + }); +} + +module.exports = validate; diff --git a/lib/writeMarkdown.js b/lib/writeMarkdown.js new file mode 100644 index 00000000..31e3119b --- /dev/null +++ b/lib/writeMarkdown.js @@ -0,0 +1,52 @@ +/* + * Copyright 2019 Adobe. All rights reserved. + * This file is licensed 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 REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +const { each, pairs } = require('ferrum'); +const stringify = require('remark-stringify'); +const unified = require('unified'); +const path = require('path'); +const inspect = require('unist-util-inspect'); +const fs = require('fs-extra'); + +function writeMarkdown({ + out, debug, error, info, +}) { + const dbg = (message) => { + if (debug && typeof message === 'object') { + debug(inspect(message)); + } else if (debug) { + debug(message); + } + }; + + const processor = unified() + .use(stringify); + + fs.mkdirpSync(out); + + return (schemas) => { + each(pairs(schemas), ([name, schema]) => { + dbg(schema.markdown); + const fileName = path.resolve(out, `${name}.md`); + fs.writeFile(fileName, processor.stringify(schema.markdown), (err) => { + if (err) { + error(err); + } + // info(`${fileName} created`); + schema.outFile = fileName; + }); + }); + + return schemas; + }; +} + +module.exports = writeMarkdown;