core-types-graphql
Version:
core-types ⬌ GraphQL conversion
115 lines (114 loc) • 3.52 kB
JavaScript
import { ensureArray } from "core-types";
/**
* Turns annotations into Markdown comments, which is the standard GraphQL
* comment format.
*/
export function stringifyAnnotations(node, ctx) {
const { description, examples, default: _default, comment } = node;
const exampleArray = ensureArray(examples);
const fullComment = [
description,
...(examples == undefined ? [] : [
formatExamples(exampleArray, ctx)
]),
...(_default === undefined ? [] : [
formatDefault(_default, ctx)
]),
...(ctx.options.includeComment ? [comment] : []),
]
.filter(v => v)
.join("\n\n")
.trim();
return fullComment;
}
function enquoteCode(code, ctx) {
if (code.includes("`"))
return code;
if (code.includes("\n"))
return "```\n" + code + "\n```";
else
return "`" + code + "`";
}
function formatExamples(examples, ctx) {
const lines = examples.map(example => "# example\n" + indent(enquoteCode(example, ctx)))
.join("\n")
.trim();
return lines;
}
function formatDefault(_default, ctx) {
return `# default\n${indent(enquoteCode(_default, ctx))}`;
}
function indent(text) {
return text
.split("\n")
.map(line => ` ${line}`)
.join("\n");
}
export function parseDescription(descriptionText) {
descriptionText =
(descriptionText && typeof descriptionText === 'object')
? parseString(descriptionText)
: descriptionText;
if (!descriptionText)
return {};
const description = [];
const examples = [];
const _default = [];
let where = 'description';
descriptionText
.split("\n")
.forEach(line => {
if (line.match(/^#+\s*example$/)) {
where = 'examples';
examples.push([]);
return;
}
else if (line.match(/^#+\s*default$/)) {
where = 'default';
return;
}
else if (where === 'examples')
examples[examples.length - 1].push(line);
else if (where === 'default')
_default.push(line);
else // 'description'
description.push(line);
});
return {
...(description.length === 0 ? {} :
{ description: joinUnindentedBlock(description).trim() }),
...(examples.length === 0
? {}
: examples.length === 1
? { examples: joinUnindentedBlock(examples[0]) }
:
{
examples: examples
.map(example => joinUnindentedBlock(example))
}),
...(_default.length === 0 ? {} :
{ default: joinUnindentedBlock(_default) }),
};
}
function joinUnindentedBlock(lines) {
return unindentEqual(lines).join("\n");
}
export function unindentEqual(lines) {
if (lines.length === 0 || lines[0].length === 0)
return lines;
const char = lines[0].charAt(0);
if (char !== ' ' && char !== '\t')
return lines;
const re = new RegExp(`^(${char}+)`);
const initial = lines[0].match(re)[1].length;
const indent = lines.reduce((prev, cur) => {
const m = cur.match(re);
if (!m || m[1].length === 0)
return 0;
return Math.min(prev, m[1].length);
}, initial);
return lines.map(line => line.slice(indent));
}
export function parseString(str) {
return str?.value;
}