From d033f4d9ae2c2771a906a78e209b13404ad1742d Mon Sep 17 00:00:00 2001 From: "Max R. Carrara" Date: Tue, 10 Sep 2024 17:19:41 +0200 Subject: [PATCH] server: pod: format pod document in general and after symbol lookup For all general cases, the `formatPodDoc` function is now used to perform various actions on a processed pod document. At the moment, this only removes `=head1 NAME` paragraphs from the document, as those are kind of unnecessary in hover docs. After a successful symbol lookup, the returned pod document is formatted in the following ways: - `=item` paragraphs of the same indentation level are converted to header paragraphs, which makes the matched symbol appear more nicely. - `=head\d` paragraphs are now "normalized" -- this means that if e.g. a subroutine signature starts at `=head4`, it will be converted to a `=head1` internally, which is then adapted as needed by the markdown converter. The above results in the docs of all looked up symbols being uniformly rendered as `h3` (`###`), with sub-headings being converted to the respective relative level. Signed-off-by: Max R. Carrara --- server/src/pod.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/server/src/pod.ts b/server/src/pod.ts index 80ae39d..9c8afdf 100644 --- a/server/src/pod.ts +++ b/server/src/pod.ts @@ -1866,6 +1866,60 @@ function matchItemRegionInPod(regex: RegExp, getNext: () => PodBlockContent | un return extractedContents; } +function formatPodDocForSymbol(podDoc: PodDocument) { + // use this as default and let converter handle the adjustment + const symbolHeaderLevel: number = 1; + + // technically there should only be one block, but playing it safe here + for (const block of podDoc.blocks) { + block.paragraphs.forEach((para, index) => { + if (isItem(para)) { + const replacementHeaderPara: HeaderParagraph = { + kind: "head", + level: symbolHeaderLevel, + contents: (para.lines ?? []).join(" "), + lineNo: para.lineNo, + }; + + block.paragraphs[index] = replacementHeaderPara; + } + }); + } + + let highestHeaderLevel: number = 6; + + for (const block of podDoc.blocks) { + for (const para of block.paragraphs) { + if (para.kind === "head" && para.level < highestHeaderLevel) { + highestHeaderLevel = para.level; + } + } + } + + // normalize header levels to `symbolHeaderLevel` + for (const block of podDoc.blocks) { + for (const para of block.paragraphs) { + if (para.kind !== "head") { + continue; + } + + para.level = para.level - (highestHeaderLevel - symbolHeaderLevel); + }; + } +} + +function formatPodDoc(podDoc: PodDocument) { + for (const block of podDoc.blocks) { + block.paragraphs = block.paragraphs.filter((para) => { + return !( + para.kind === "head" + && para.level === 1 + && para.contents.trim() === "NAME" + ); + }); + } +} + export async function getPod( elem: PerlElem, perlDoc: PerlDocument, @@ -1930,12 +1984,18 @@ export async function getPod( if (symbolName) { podDoc = lookupSymbolInPod(symbolName, podDocResult); + + if (podDoc) { + formatPodDocForSymbol(podDoc); + } } if (!podDoc) { return; } + formatPodDoc(podDoc); + let converter = new PodToMarkdownConverter(); let markdown = converter.convert(podDoc);