# src/view/MainComment.ts

`1<comment>/**
2 * Processing of comments.
3 */</comment>
4
5<comment>/** */</comment>
6import { m, Vnode } from 'hslayout';
7import { markDown } from '../markdown';
8import { example } from './MainExample';
9
10<comment>/**
11 * Main comment processing. The result appears directly below the title in the main panel.
12 * Function parameters are not reported in short form here since it is assumed they will be listed
13 * individually below the main comment
14 * @param mdl the module to scan for comments
15 * @return a vnode representing the comment entries
16 */</comment>
17export function commentLong(mdl:any):Vnode {
18 let content:any[] = [];
19 if (mdl.comment) {
20 content.push(textOrShortTextOrDescription(mdl.comment, false));
21 content.push(returns(mdl.comment, false));
22 content.push(commentRemainder(mdl.comment));
23 }
24 return m('.hs-item-comment', content);
25}
26
27<comment>/**
28 * Shortended comment processing. This form is used to report on subitems below the main panel item.
29 * If `short` is true, only the first paragraph of the main comment will be returned. Otherwise,
30 * this function creates a full comment including an inline list of parameters and the return value
31 * @param mdl the module to scan for comments
32 * @param short if true, only the first paragraph of the main comment is processed.
33 * @return a vnode representing the comment entries
34 */</comment>
35export function comment(mdl:any, short=false):Vnode {
36 let content:any[] = [];
37 if (mdl.comment) {
38 content.push(textOrShortTextOrDescription(mdl.comment, short));
39 if (!short) {
40 content.push(otherCommentTags(mdl.comment));
41 if (mdl.parameters) {
42 content = content.concat(mainCommentParams(mdl.parameters));
43 }
44 }
45 content.push(returns(mdl.comment, false));
46 content.push(commentRemainder(mdl.comment));
47 }
48 return m('.hs-item-comment', content);
49}
50
51<comment>/**
52 * Report the item's description. This can come in different forms that are all handled here:
53 * - comment.shortText: <description>
54 * - comment.text: <description>
55 * - comment.tags[{tag:'description}, text:<description>]
56 * Any resulting comment will be translated from markdown to html and returned as a `Vnode`.
57 * @param comment the comment object to parse
58 * @param short boolean; if true, only the first paragraph of the description will be returned
59 */</comment>
60function textOrShortTextOrDescription(comment:any, short:boolean):Vnode {
61 let text = (comment.shortText || '');
62 if (comment.text) { text += '\n'+ (comment.text || ''); }
63 if (comment.tags) {
64 comment.tags.map((tag:any) => {if (tag.tag==='description') { text = tag.text;}} );
65 }
66 text = text.replace(/<example([\S\s]*?)<\/example>/gi, short? '' : example);
67 return m('.hs-item-comment-desc', prettifyCode(text, short));
68}
69
70<comment>/**
71 * creates the `returns` message for a function or method.
72 */</comment>
73function returns(comment:any, short:boolean):Vnode {
74 let text = comment.returns;
75 return m('.hs-item-comment-return', !text? '': [
76 m('span.hs-item-comment-tag', 'returns:'),
77 m('span.hs-item-comment-text', text)
78 ]);
79}
80
81function commentRemainder(comment:any):string|Vnode {
82 return m('', Object.keys(comment).map((tag:any) => {
83 switch(tag) {
84 case 'tags': // already handled
85 case 'shortText': // already handled
86 case 'text': // already handled
87 case 'description': // already handled
88 case 'returns': // already handled
89 return '';
90 default: return m('.hs-item-comment-special', [
91 m('span.hs-item-comment-tag', tag),
92 m('span.hs-item-comment-text', comment[tag])
93 ]);;
94 }
95 }));
96}
97
98function otherCommentTags(comment:any):string|Vnode {
99 return m('', !comment.tags? [] : comment.tags.map((tag:any) => {
100 switch(tag.tag) {
101 case 'description': return ''; // skip since already handled
102 default: return m('.hs-item-comment-special', [
103 m('span.hs-item-comment-tag', tag.tag),
104 m('span.hs-item-comment-text', tag.text)
105 ]);
106 }
107 }));
108}
109
110function mainCommentParams(params:any):Vnode {
111 return m('.hs-item-comment-params', params.map((par:any) =>
112 m('.hs-item-comment-param', [
113 m('span.hs-item-comment-tag', par.name+':'),
114 m('span.hs-item-comment-text', !par.comment? '' :
115 ((par.defaultValue!==undefined)? `[default: ${par.defaultValue}] ` : '') + par.comment.text
116 )
117 ])
118 ));
119}
120
121<comment>/**
122 * finds segments of ``...`` in `comment` and replaces them with a prettified version.
123 * Currently the function performs operations in this sequence:
124 * - add indentation for brackets {...}
125 * - wrap the <code>...</code> part within <pre>...</pre> brackets
126 * - apply markdown syntax
127 * - wrap results in a trusted mithril node
128 * @param comment the comment comment
129 * @param short only return the first paragraph
130 */</comment>
131function prettifyCode(comment:string, short:boolean):Vnode {
132// const indentSpaces = 2;
133 let result = comment;
134
135 function braceIndenting(text:string): string {
136 let indent = 0;
137 const result = text
138 .substring(6, text.length-7) <comment>// remove `and` </comment>
139 .trim()
140 .replace(/(<)/g, '<').replace(/(>)/g, '>')
141 .split('\n')
142 .map((l:string) => {
143 let oldIndent = indent;
144 let k = l.trim();
145 indent += Math.max(-1, Math.min(1, k.split('{').length - k.split('}').length));
146 indent += Math.max(-1, Math.min(1, k.split('[').length - k.split(']').length));
147 return '<span class="hs-code-indent">'.repeat(((indent < oldIndent)?indent:oldIndent)) + k;
148 })
149 .join('\n')
150 .trim();
151 return '

    ' + result + '

';
152 }
153
154 result = result.replace(/`([\S\s]*?)<\/code>/gi, braceIndenting);
155 return m.trust(markDown(result, short, m.route.get()));
156}
157
``