in kit/preprocessors/docstring.js [9:190]
markup: async ({ content, filename }) => {
const REGEX_DOCSTRING = generateTagRegex("docstring", true);
const REGEX_NAME = generateTagRegex("name");
const REGEX_ANCHOR = generateTagRegex("anchor");
const REGEX_SIGNATURE = generateTagRegex("parameters");
const REGEX_PARAMSDESC = generateTagRegex("paramsdesc");
const REGEX_PARAMSGROUPS = generateTagRegex("paramgroups");
const REGEX_RETDESC = generateTagRegex("retdesc");
const REGEX_RETTYPE = generateTagRegex("rettype");
const REGEX_YIELDESC = generateTagRegex("yieldesc");
const REGEX_YIELDTYPE = generateTagRegex("yieldtype");
const REGEX_RAISEDESC = generateTagRegex("raises");
const REGEX_RAISETYPE = generateTagRegex("raisederrors");
const REGEX_SOURCE = generateTagRegex("source");
const REGEX_TIP = /<Tip( warning={true})?>(((?!<Tip( warning={true})?>).)*)<\/Tip>/gms;
const REGEX_CHANGED =
/<(Added|Changed|Deprecated) version="([0-9.v]+)" ?\/?>((((?!<(Added|Changed|Deprecated) version="([0-9.v]+)"\/?>).)*)<\/(Added|Changed|Deprecated)>)?/gms;
const REGEX_IS_GETSET_DESC = /<isgetsetdescriptor>/ms;
content = await replaceAsync(content, REGEX_DOCSTRING, async (_, docstringBody) => {
docstringBody = renderSvelteChars(docstringBody);
const name = docstringBody.match(REGEX_NAME)[1];
const anchor = docstringBody.match(REGEX_ANCHOR)[1];
const signature = docstringBody.match(REGEX_SIGNATURE)[1];
let svelteComponent = `<Docstring name={${JSON.stringify(
unescapeUnderscores(name)
)}} anchor={${JSON.stringify(anchor)}} parameters={${signature}} `;
if (docstringBody.match(REGEX_PARAMSDESC)) {
let content = docstringBody.match(REGEX_PARAMSDESC)[1];
// escape }} by adding void character `‌` in between
content = content.replace(/}}/g, "}‌}");
let { code } = await mdsvexPreprocess.markup({ content, filename });
// render <Tip> components that are inside parameter descriptions
code = code.replace(REGEX_TIP, (_, isWarning, tipContent) => {
const color = isWarning ? "orange" : "green";
return `<div
class="course-tip ${
color === "orange" ? "course-tip-orange" : ""
} bg-gradient-to-br dark:bg-gradient-to-r before:border-${color}-500 dark:before:border-${color}-800 from-${color}-50 dark:from-gray-900 to-white dark:to-gray-950 border border-${color}-50 text-${color}-700 dark:text-gray-400"
>
${tipContent}
</div>`;
});
// render <Added>, <Changed>, <Deprecated> components that are inside parameter descriptions
code = code.replace(REGEX_CHANGED, (_, componentType, version, __, descriptionContent) => {
const color = /Added|Changed/.test(componentType) ? "green" : "orange";
if (!descriptionContent) {
descriptionContent = "";
}
return `<div
class="course-tip ${
color === "orange" ? "course-tip-orange" : ""
} bg-gradient-to-br dark:bg-gradient-to-r before:border-${color}-500 dark:before:border-${color}-800 from-${color}-50 dark:from-gray-900 to-white dark:to-gray-950 border border-${color}-50 text-${color}-700 dark:text-gray-400"
>
<p class="font-medium">${componentType} in ${version}</p>
${descriptionContent}
</div>`;
});
const dom = htmlparser2.parseDocument(code);
const lists = domUtils.getElementsByTagName("ul", dom);
if (lists.length) {
const list = lists[0];
const result = [];
for (const childEl of list.childNodes.filter(({ type }) => type === "tag")) {
const nameEl = domUtils.getElementsByTagName("strong", childEl)[0];
const name = domUtils.innerText(nameEl);
const paramAnchor = `${anchor}.${name}`;
let description = domUtils.getInnerHTML(childEl).trim();
// strip enclosing paragraph tags <p> & </p>
if (description.startsWith("<p>")) {
description = description.slice("<p>".length);
}
if (description.endsWith("</p>")) {
description = description.slice(0, -"</p>".length);
}
result.push({ anchor: paramAnchor, description, name });
}
svelteComponent += ` parametersDescription={${JSON.stringify(result)}} `;
}
}
if (docstringBody.match(REGEX_SOURCE)) {
const source = docstringBody.match(REGEX_SOURCE)[1];
svelteComponent += ` source={${JSON.stringify(source)}} `;
}
if (docstringBody.match(REGEX_RETDESC)) {
const retDesc = docstringBody.match(REGEX_RETDESC)[1];
const { code } = await mdsvexPreprocess.markup({ content: retDesc, filename });
svelteComponent += ` returnDescription={${JSON.stringify(code)}} `;
}
if (docstringBody.match(REGEX_RETTYPE)) {
const retType = docstringBody.match(REGEX_RETTYPE)[1];
const { code } = await mdsvexPreprocess.markup({ content: retType, filename });
svelteComponent += ` returnType={${JSON.stringify(code)}} `;
}
if (docstringBody.match(REGEX_YIELDESC)) {
const yieldDesc = docstringBody.match(REGEX_YIELDESC)[1];
const { code } = await mdsvexPreprocess.markup({ content: yieldDesc, filename });
svelteComponent += ` returnDescription={${JSON.stringify(code)}} `;
}
if (docstringBody.match(REGEX_YIELDTYPE)) {
const yieldType = docstringBody.match(REGEX_YIELDTYPE)[1];
const { code } = await mdsvexPreprocess.markup({ content: yieldType, filename });
svelteComponent += ` returnType={${JSON.stringify(code)}} isYield={true} `;
}
if (docstringBody.match(REGEX_RAISEDESC)) {
const raiseDesc = docstringBody.match(REGEX_RAISEDESC)[1];
const { code } = await mdsvexPreprocess.markup({ content: raiseDesc, filename });
svelteComponent += ` raiseDescription={${JSON.stringify(code)}} `;
}
if (docstringBody.match(REGEX_RAISETYPE)) {
const raiseType = docstringBody.match(REGEX_RAISETYPE)[1];
const { code } = await mdsvexPreprocess.markup({ content: raiseType, filename });
svelteComponent += ` raiseType={${JSON.stringify(code)}} `;
}
if (docstringBody.match(REGEX_IS_GETSET_DESC)) {
svelteComponent += ` isGetSetDescriptor={true} `;
}
if (docstringBody.match(REGEX_PARAMSGROUPS)) {
const nParamGroups = parseInt(docstringBody.match(REGEX_PARAMSGROUPS)[1]);
if (nParamGroups > 0) {
const parameterGroups = [];
for (let groupId = 1; groupId <= nParamGroups; groupId++) {
const REGEX_GROUP_TITLE = new RegExp(
`<paramsdesc${groupId}title>(((?!<paramsdesc${groupId}title>).)*)</paramsdesc${groupId}title>`,
"ms"
);
const REGEX_GROUP_CONTENT = new RegExp(
`<paramsdesc${groupId}>(((?!<paramsdesc${groupId}>).)*)</paramsdesc${groupId}>`,
"ms"
);
const title = docstringBody.match(REGEX_GROUP_TITLE)[1];
const content = docstringBody.match(REGEX_GROUP_CONTENT)[1];
const { code } = await mdsvexPreprocess.markup({ content, filename });
const dom = htmlparser2.parseDocument(code);
const lists = domUtils.getElementsByTagName("ul", dom);
const result = [];
if (lists.length) {
const list = lists[0];
for (const childEl of list.childNodes.filter(({ type }) => type === "tag")) {
const nameEl = domUtils.getElementsByTagName("strong", childEl)[0];
const name = domUtils.innerText(nameEl);
const paramAnchor = `${anchor}.${name}`;
let description = domUtils.getInnerHTML(childEl).trim();
// strip enclosing paragraph tags <p> & </p>
if (description.startsWith("<p>")) {
description = description.slice("<p>".length);
}
if (description.endsWith("</p>")) {
description = description.slice(0, -"</p>".length);
}
result.push({ anchor: paramAnchor, description, name });
}
}
parameterGroups.push({ title, parametersDescription: result });
}
svelteComponent += ` parameterGroups={${JSON.stringify(parameterGroups)}} `;
}
}
svelteComponent += ` />\n`;
return svelteComponent;
});
return { code: content };
},