Published
Edited
Apr 21, 2021
2 forks
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
commentBlock = {
const options = {
spacing: "preserve" // preserving line breaks within @example (and, unfortunately, description)
};
const commentBlocks = parser.parse(annotatedSourceCode, options);
return commentBlocks[0];
}
Insert cell
// see: https://www.npmjs.com/package/comment-parser
parser = require("https://bundle.run/comment-parser@1.1.4")
Insert cell
// for example embedding (as highlighted source code), see: https://github.com/observablehq/htl#node-values
format = (commentBlock, methodName) => html`
<div class="markdown-body">
<p>${getSynopsis(commentBlock, methodName)}</p>
<p>${getDescription(commentBlock)}</p>
${getExample(commentBlock)}
</div>`;
Insert cell
getSynopsis = (commentBlock, methodName) => {
let literal = `<a href="#${methodName}">#</a>`;
literal += ` ${getParentName(commentBlock)}`;
literal += `.${getSignature(commentBlock, methodName)}`;
literal += ` · <a href="${getSourceUrl(6839)}">Source</a>`;
literal += `, <a href="${getPackageUrl(methodName)}">Package</a>`;
return literal;
}
Insert cell
getParentName = (commentBlock) => commentBlock.tags.find(d => d.tag === "memberOf").name
Insert cell
// for similar signature format, see: https://docs.python.org/3.3/library/functions.html
getSignature = (commentBlock, methodName) => {
const params = getParams(commentBlock);
return `<b>${methodName}</b>(${formatParams(params)})`;
}
Insert cell
getParams = (commentBlock) => commentBlock.tags.filter(d => d.tag === "param")
Insert cell
formatParams = (params) => {
let literal = "";
let previousParam = null;
for (const currentParam of params) {
if (currentParam.optional) {
literal += "[";
}
if (previousParam !== null) {
literal += ", ";
}
literal += `<i>${currentParam.name}`;
if (currentParam.default !== undefined) {
literal += ` = ${currentParam.default}`;
}

literal += "</i>"
previousParam = currentParam;
}
const openSquareBracketCount = literal.split("[").length - 1;
if (openSquareBracketCount > 0) {
literal += "]".repeat(openSquareBracketCount);
}
return literal;
}
Insert cell
getSourceUrl = (lineNumber) => `https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L${lineNumber}`
Insert cell
getPackageUrl = (methodName) => `https://www.npmjs.com/package/lodash.${methodName}`
Insert cell
getDescription = (commentBlock) => {
const inlineCode = /\`(\w+)\`/g;
const paramNames = getParams(commentBlock).map(d => d.name);
let literal = commentBlock.description.replaceAll(inlineCode, (_, p1) => {
if (paramNames.includes(p1)) {
return `<i>${p1}</i>`;
}
return `<code>${p1}</code>`;
});
return literal;
}
Insert cell
// highlighting done by https://github.com/markedjs/marked, see: https://github.com/observablehq/stdlib#markdown
getExample = (commentBlock) => {
const example = commentBlock.tags.find(d => d.tag === "example");
const code = example.description.trim();
return md`
~~~js
${code}
~~~`;
}
Insert cell
html`<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@primer/css@15.2.0/dist/product.css">`
Insert cell
html`<style>
h1,
h2,
h3,
p {
max-width: unset;
}

b {
font-weight: 600;
}

.markdown-body > p:last-child,
.markdown-body > pre:last-child {
margin-bottom: 7px !important;
}
</style>`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more