pict-section-content 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/retold-catalog.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"Generated": "2026-02-
|
|
2
|
+
"Generated": "2026-02-18T05:42:00.270Z",
|
|
3
3
|
"GitHubOrg": "stevenvelozo",
|
|
4
4
|
"DefaultBranch": "master",
|
|
5
5
|
"Groups": [
|
|
@@ -20,6 +20,25 @@
|
|
|
20
20
|
}
|
|
21
21
|
]
|
|
22
22
|
},
|
|
23
|
+
{
|
|
24
|
+
"Name": "Docs",
|
|
25
|
+
"Key": "docs",
|
|
26
|
+
"Description": "",
|
|
27
|
+
"Modules": [
|
|
28
|
+
{
|
|
29
|
+
"Name": "css",
|
|
30
|
+
"Repo": "css",
|
|
31
|
+
"Group": "docs",
|
|
32
|
+
"Branch": "master",
|
|
33
|
+
"HasDocs": true,
|
|
34
|
+
"HasCover": false,
|
|
35
|
+
"Sidebar": [],
|
|
36
|
+
"DocFiles": [
|
|
37
|
+
"css/docuserve.css"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
23
42
|
{
|
|
24
43
|
"Name": "Source",
|
|
25
44
|
"Key": "source",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Generated": "2026-02-18T05:42:00.361Z",
|
|
3
|
+
"DocumentCount": 0,
|
|
4
|
+
"LunrIndex": {
|
|
5
|
+
"version": "2.3.9",
|
|
6
|
+
"fields": [
|
|
7
|
+
"title",
|
|
8
|
+
"module",
|
|
9
|
+
"group",
|
|
10
|
+
"body"
|
|
11
|
+
],
|
|
12
|
+
"fieldVectors": [],
|
|
13
|
+
"invertedIndex": [],
|
|
14
|
+
"pipeline": [
|
|
15
|
+
"stemmer"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"Documents": {}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pict-section-content",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Pict content rendering section - markdown parsing, Mermaid diagrams, and KaTeX equations",
|
|
5
5
|
"main": "source/Pict-Section-Content.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/stevenvelozo/pict-section-content#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"pict-provider": "^1.0.
|
|
25
|
-
"pict-view": "^1.0.
|
|
24
|
+
"pict-provider": "^1.0.10",
|
|
25
|
+
"pict-view": "^1.0.66"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"chai": "^6.2.2",
|
|
29
29
|
"mocha": "^11.7.5",
|
|
30
|
-
"pict": "^1.0.
|
|
31
|
-
"quackage": "^1.0.
|
|
30
|
+
"pict": "^1.0.348",
|
|
31
|
+
"quackage": "^1.0.51"
|
|
32
32
|
},
|
|
33
33
|
"mocha": {
|
|
34
34
|
"diff": true,
|
|
@@ -46,6 +46,17 @@ class PictContentProvider extends libPictProvider
|
|
|
46
46
|
let tmpBlockquoteLines = [];
|
|
47
47
|
let tmpInMathBlock = false;
|
|
48
48
|
let tmpMathLines = [];
|
|
49
|
+
let tmpParagraphLines = [];
|
|
50
|
+
|
|
51
|
+
// Helper to flush accumulated paragraph lines into a single <p> tag
|
|
52
|
+
let fFlushParagraph = () =>
|
|
53
|
+
{
|
|
54
|
+
if (tmpParagraphLines.length > 0)
|
|
55
|
+
{
|
|
56
|
+
tmpHTML.push('<p>' + tmpParagraphLines.map((pLine) => { return this.parseInline(pLine, pLinkResolver); }).join(' ') + '</p>');
|
|
57
|
+
tmpParagraphLines = [];
|
|
58
|
+
}
|
|
59
|
+
};
|
|
49
60
|
|
|
50
61
|
for (let i = 0; i < tmpLines.length; i++)
|
|
51
62
|
{
|
|
@@ -63,6 +74,8 @@ class PictContentProvider extends libPictProvider
|
|
|
63
74
|
}
|
|
64
75
|
else
|
|
65
76
|
{
|
|
77
|
+
// Flush any pending paragraph
|
|
78
|
+
fFlushParagraph();
|
|
66
79
|
// Close any open list or blockquote
|
|
67
80
|
if (tmpInList)
|
|
68
81
|
{
|
|
@@ -122,6 +135,8 @@ class PictContentProvider extends libPictProvider
|
|
|
122
135
|
}
|
|
123
136
|
else
|
|
124
137
|
{
|
|
138
|
+
// Flush any pending paragraph
|
|
139
|
+
fFlushParagraph();
|
|
125
140
|
// Close any open list or blockquote
|
|
126
141
|
if (tmpInList)
|
|
127
142
|
{
|
|
@@ -153,6 +168,8 @@ class PictContentProvider extends libPictProvider
|
|
|
153
168
|
{
|
|
154
169
|
if (!tmpInBlockquote)
|
|
155
170
|
{
|
|
171
|
+
// Flush any pending paragraph
|
|
172
|
+
fFlushParagraph();
|
|
156
173
|
// Close any open list
|
|
157
174
|
if (tmpInList)
|
|
158
175
|
{
|
|
@@ -175,6 +192,7 @@ class PictContentProvider extends libPictProvider
|
|
|
175
192
|
// Horizontal rule
|
|
176
193
|
if (tmpLine.match(/^(-{3,}|\*{3,}|_{3,})\s*$/))
|
|
177
194
|
{
|
|
195
|
+
fFlushParagraph();
|
|
178
196
|
if (tmpInList)
|
|
179
197
|
{
|
|
180
198
|
tmpHTML.push(tmpListType === 'ul' ? '</ul>' : '</ol>');
|
|
@@ -188,6 +206,7 @@ class PictContentProvider extends libPictProvider
|
|
|
188
206
|
let tmpHeadingMatch = tmpLine.match(/^(#{1,6})\s+(.+)/);
|
|
189
207
|
if (tmpHeadingMatch)
|
|
190
208
|
{
|
|
209
|
+
fFlushParagraph();
|
|
191
210
|
if (tmpInList)
|
|
192
211
|
{
|
|
193
212
|
tmpHTML.push(tmpListType === 'ul' ? '</ul>' : '</ol>');
|
|
@@ -204,6 +223,7 @@ class PictContentProvider extends libPictProvider
|
|
|
204
223
|
let tmpULMatch = tmpLine.match(/^(\s*)[-*+]\s+(.*)/);
|
|
205
224
|
if (tmpULMatch)
|
|
206
225
|
{
|
|
226
|
+
fFlushParagraph();
|
|
207
227
|
if (!tmpInList || tmpListType !== 'ul')
|
|
208
228
|
{
|
|
209
229
|
if (tmpInList)
|
|
@@ -222,6 +242,7 @@ class PictContentProvider extends libPictProvider
|
|
|
222
242
|
let tmpOLMatch = tmpLine.match(/^(\s*)\d+\.\s+(.*)/);
|
|
223
243
|
if (tmpOLMatch)
|
|
224
244
|
{
|
|
245
|
+
fFlushParagraph();
|
|
225
246
|
if (!tmpInList || tmpListType !== 'ol')
|
|
226
247
|
{
|
|
227
248
|
if (tmpInList)
|
|
@@ -243,15 +264,17 @@ class PictContentProvider extends libPictProvider
|
|
|
243
264
|
tmpInList = false;
|
|
244
265
|
}
|
|
245
266
|
|
|
246
|
-
// Empty line
|
|
267
|
+
// Empty line — flush any accumulated paragraph
|
|
247
268
|
if (tmpLine.trim() === '')
|
|
248
269
|
{
|
|
270
|
+
fFlushParagraph();
|
|
249
271
|
continue;
|
|
250
272
|
}
|
|
251
273
|
|
|
252
274
|
// Table detection
|
|
253
275
|
if (tmpLine.match(/^\|/) && i + 1 < tmpLines.length && tmpLines[i + 1].match(/^\|[\s-:|]+\|/))
|
|
254
276
|
{
|
|
277
|
+
fFlushParagraph();
|
|
255
278
|
// Close any open list
|
|
256
279
|
if (tmpInList)
|
|
257
280
|
{
|
|
@@ -291,10 +314,14 @@ class PictContentProvider extends libPictProvider
|
|
|
291
314
|
continue;
|
|
292
315
|
}
|
|
293
316
|
|
|
294
|
-
//
|
|
295
|
-
|
|
317
|
+
// Accumulate paragraph lines — consecutive non-blank text lines
|
|
318
|
+
// will be joined into a single <p> tag when flushed
|
|
319
|
+
tmpParagraphLines.push(tmpLine);
|
|
296
320
|
}
|
|
297
321
|
|
|
322
|
+
// Flush any remaining accumulated paragraph
|
|
323
|
+
fFlushParagraph();
|
|
324
|
+
|
|
298
325
|
// Close any trailing open elements
|
|
299
326
|
if (tmpInList)
|
|
300
327
|
{
|
|
@@ -328,8 +355,14 @@ class PictContentProvider extends libPictProvider
|
|
|
328
355
|
|
|
329
356
|
let tmpResult = pText;
|
|
330
357
|
|
|
331
|
-
//
|
|
332
|
-
|
|
358
|
+
// Extract inline code spans into placeholders so bold/italic regexes don't mangle their contents
|
|
359
|
+
let tmpCodeSpans = [];
|
|
360
|
+
tmpResult = tmpResult.replace(/`([^`]+)`/g, (pMatch, pCode) =>
|
|
361
|
+
{
|
|
362
|
+
let tmpIndex = tmpCodeSpans.length;
|
|
363
|
+
tmpCodeSpans.push('<code>' + pCode + '</code>');
|
|
364
|
+
return '\x00CODEINLINE' + tmpIndex + '\x00';
|
|
365
|
+
});
|
|
333
366
|
|
|
334
367
|
// Inline LaTeX equations ($...$) — must be processed before other inline patterns
|
|
335
368
|
// Match single $ delimiters that aren't adjacent to spaces (to avoid false positives with currency)
|
|
@@ -369,6 +402,12 @@ class PictContentProvider extends libPictProvider
|
|
|
369
402
|
tmpResult = tmpResult.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
370
403
|
tmpResult = tmpResult.replace(/_([^_]+)_/g, '<em>$1</em>');
|
|
371
404
|
|
|
405
|
+
// Restore inline code spans from placeholders
|
|
406
|
+
tmpResult = tmpResult.replace(/\x00CODEINLINE(\d+)\x00/g, (pMatch, pIndex) =>
|
|
407
|
+
{
|
|
408
|
+
return tmpCodeSpans[parseInt(pIndex)];
|
|
409
|
+
});
|
|
410
|
+
|
|
372
411
|
return tmpResult;
|
|
373
412
|
}
|
|
374
413
|
|
|
@@ -255,6 +255,146 @@ suite
|
|
|
255
255
|
}
|
|
256
256
|
);
|
|
257
257
|
|
|
258
|
+
suite
|
|
259
|
+
(
|
|
260
|
+
'Multi-line Paragraph Handling',
|
|
261
|
+
function()
|
|
262
|
+
{
|
|
263
|
+
test
|
|
264
|
+
(
|
|
265
|
+
'parseMarkdown should join consecutive lines into a single paragraph.',
|
|
266
|
+
(fDone) =>
|
|
267
|
+
{
|
|
268
|
+
var tmpProvider = createProvider();
|
|
269
|
+
var tmpResult = tmpProvider.parseMarkdown('This is the first line\nof a single paragraph\nthat spans three lines.');
|
|
270
|
+
// All three lines should be in one <p> tag
|
|
271
|
+
Expect(tmpResult).to.contain('<p>This is the first line of a single paragraph that spans three lines.</p>');
|
|
272
|
+
fDone();
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
test
|
|
276
|
+
(
|
|
277
|
+
'parseMarkdown should separate paragraphs on blank lines.',
|
|
278
|
+
(fDone) =>
|
|
279
|
+
{
|
|
280
|
+
var tmpProvider = createProvider();
|
|
281
|
+
var tmpResult = tmpProvider.parseMarkdown('First paragraph line one\nfirst paragraph line two.\n\nSecond paragraph line one\nsecond paragraph line two.');
|
|
282
|
+
Expect(tmpResult).to.contain('<p>First paragraph line one first paragraph line two.</p>');
|
|
283
|
+
Expect(tmpResult).to.contain('<p>Second paragraph line one second paragraph line two.</p>');
|
|
284
|
+
// Should produce exactly two <p> tags
|
|
285
|
+
var tmpParagraphCount = (tmpResult.match(/<p>/g) || []).length;
|
|
286
|
+
Expect(tmpParagraphCount).to.equal(2);
|
|
287
|
+
fDone();
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
test
|
|
291
|
+
(
|
|
292
|
+
'parseMarkdown should flush paragraph before a heading.',
|
|
293
|
+
(fDone) =>
|
|
294
|
+
{
|
|
295
|
+
var tmpProvider = createProvider();
|
|
296
|
+
var tmpResult = tmpProvider.parseMarkdown('Some introductory text\nthat spans two lines.\n## A Heading');
|
|
297
|
+
Expect(tmpResult).to.contain('<p>Some introductory text that spans two lines.</p>');
|
|
298
|
+
Expect(tmpResult).to.contain('<h2');
|
|
299
|
+
Expect(tmpResult).to.contain('A Heading');
|
|
300
|
+
fDone();
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
test
|
|
304
|
+
(
|
|
305
|
+
'parseMarkdown should flush paragraph before a list.',
|
|
306
|
+
(fDone) =>
|
|
307
|
+
{
|
|
308
|
+
var tmpProvider = createProvider();
|
|
309
|
+
var tmpResult = tmpProvider.parseMarkdown('Here is a paragraph\nbefore a list.\n- Item 1\n- Item 2');
|
|
310
|
+
Expect(tmpResult).to.contain('<p>Here is a paragraph before a list.</p>');
|
|
311
|
+
Expect(tmpResult).to.contain('<ul>');
|
|
312
|
+
Expect(tmpResult).to.contain('<li>Item 1</li>');
|
|
313
|
+
fDone();
|
|
314
|
+
}
|
|
315
|
+
);
|
|
316
|
+
test
|
|
317
|
+
(
|
|
318
|
+
'parseMarkdown should flush paragraph before a code block.',
|
|
319
|
+
(fDone) =>
|
|
320
|
+
{
|
|
321
|
+
var tmpProvider = createProvider();
|
|
322
|
+
var tmpResult = tmpProvider.parseMarkdown('Some text before code\nstill the same paragraph.\n```\ncode here\n```');
|
|
323
|
+
Expect(tmpResult).to.contain('<p>Some text before code still the same paragraph.</p>');
|
|
324
|
+
Expect(tmpResult).to.contain('<pre>');
|
|
325
|
+
Expect(tmpResult).to.contain('code here');
|
|
326
|
+
fDone();
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
test
|
|
330
|
+
(
|
|
331
|
+
'parseMarkdown should flush paragraph before a blockquote.',
|
|
332
|
+
(fDone) =>
|
|
333
|
+
{
|
|
334
|
+
var tmpProvider = createProvider();
|
|
335
|
+
var tmpResult = tmpProvider.parseMarkdown('A multi-line\nparagraph here.\n> A blockquote');
|
|
336
|
+
Expect(tmpResult).to.contain('<p>A multi-line paragraph here.</p>');
|
|
337
|
+
Expect(tmpResult).to.contain('<blockquote>');
|
|
338
|
+
Expect(tmpResult).to.contain('A blockquote');
|
|
339
|
+
fDone();
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
test
|
|
343
|
+
(
|
|
344
|
+
'parseMarkdown should handle a paragraph after a code block.',
|
|
345
|
+
(fDone) =>
|
|
346
|
+
{
|
|
347
|
+
var tmpProvider = createProvider();
|
|
348
|
+
var tmpResult = tmpProvider.parseMarkdown('```\ncode\n```\nA paragraph that\nfollows the code block.');
|
|
349
|
+
Expect(tmpResult).to.contain('<pre>');
|
|
350
|
+
Expect(tmpResult).to.contain('<p>A paragraph that follows the code block.</p>');
|
|
351
|
+
fDone();
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
test
|
|
355
|
+
(
|
|
356
|
+
'parseMarkdown should handle inline formatting within multi-line paragraphs.',
|
|
357
|
+
(fDone) =>
|
|
358
|
+
{
|
|
359
|
+
var tmpProvider = createProvider();
|
|
360
|
+
var tmpResult = tmpProvider.parseMarkdown('This paragraph has **bold** on the first line\nand *italic* on the second line.');
|
|
361
|
+
Expect(tmpResult).to.contain('<strong>bold</strong>');
|
|
362
|
+
Expect(tmpResult).to.contain('<em>italic</em>');
|
|
363
|
+
// Should be a single paragraph
|
|
364
|
+
var tmpParagraphCount = (tmpResult.match(/<p>/g) || []).length;
|
|
365
|
+
Expect(tmpParagraphCount).to.equal(1);
|
|
366
|
+
fDone();
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
test
|
|
370
|
+
(
|
|
371
|
+
'parseMarkdown should handle hand-wrapped README-style paragraphs.',
|
|
372
|
+
(fDone) =>
|
|
373
|
+
{
|
|
374
|
+
var tmpProvider = createProvider();
|
|
375
|
+
var tmpInput = 'Ultravisor is a process supervisor and service\n'
|
|
376
|
+
+ 'orchestrator built on the Fable ecosystem.\n'
|
|
377
|
+
+ 'It manages the lifecycle of multiple child\n'
|
|
378
|
+
+ 'processes from a single configuration.\n'
|
|
379
|
+
+ '\n'
|
|
380
|
+
+ 'Designed for development and production\n'
|
|
381
|
+
+ 'environments alike, it provides log\n'
|
|
382
|
+
+ 'aggregation and automatic restarts.';
|
|
383
|
+
var tmpResult = tmpProvider.parseMarkdown(tmpInput);
|
|
384
|
+
var tmpParagraphCount = (tmpResult.match(/<p>/g) || []).length;
|
|
385
|
+
Expect(tmpParagraphCount).to.equal(2, 'Should produce exactly two paragraphs.');
|
|
386
|
+
// First paragraph should contain all four lines joined
|
|
387
|
+
Expect(tmpResult).to.contain('Ultravisor is a process supervisor and service');
|
|
388
|
+
Expect(tmpResult).to.contain('orchestrator built on the Fable ecosystem.');
|
|
389
|
+
// Second paragraph should contain all three lines joined
|
|
390
|
+
Expect(tmpResult).to.contain('Designed for development and production');
|
|
391
|
+
Expect(tmpResult).to.contain('aggregation and automatic restarts.');
|
|
392
|
+
fDone();
|
|
393
|
+
}
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
|
|
258
398
|
suite
|
|
259
399
|
(
|
|
260
400
|
'Inline Markdown Parsing',
|