Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions src/colibri/documenter/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,94 @@ import * as translator_lib from "./translator";
import * as md from "./markdown_table";
const showdown = require('showdown');

/**
* Detect and convert unordered list patterns in comments to markdown format
* @param description The description text to process
* @returns The description with unordered lists converted to markdown format
*/
export function convert_unordered_lists_to_markdown(description: string): string {
if (!description) {
return "";
}

const lines = description.split('\n');
const result: string[] = [];
let i = 0;

while (i < lines.length) {
const line = lines[i];
const trimmedLine = line.trim();

// Check if current line starts a list (- or * followed by space)
const listMatch = trimmedLine.match(/^[*-]\s+(.+)$/);
if (listMatch) {
// Found start of a list, collect all list items
const listItems: string[] = [];
let j = i; // Store start position for backtracking

while (i < lines.length) {
const currentLine = lines[i];
const currentTrimmed = currentLine.trim();
const currentListMatch = currentTrimmed.match(/^[*-]\s+(.+)$/);

if (currentListMatch) {
// This is a list item
listItems.push(currentListMatch[1]);
i++;
} else if (currentTrimmed === '') {
// Empty line ends the list
break;
} else if (listItems.length > 0 && /^\s+/.test(currentLine) && currentTrimmed !== '') {
// Continuation of previous list item (indented line with content)
listItems[listItems.length - 1] += ' ' + currentTrimmed;
i++;
} else {
// Non-list line, end the list
break;
}
}

// Only convert to list if we have at least 2 items
if (listItems.length >= 2) {
// Add empty line before list if needed
if (result.length > 0 && result[result.length - 1].trim() !== '') {
result.push('');
}

// Add list items in markdown format
for (const item of listItems) {
result.push(`* ${item}`);
}

// Add empty line after list if there's more content
if (i < lines.length) {
result.push('');
}
} else {
// Not enough items for a list, treat as regular lines by rewinding
i = j;
result.push(lines[i]);
i++;
}
} else {
// Regular line, add as-is
result.push(lines[i]);
i++;
}
}

return result.join('\n');
}

export function normalize_description(description: string): string {
if(!description){
return "";
}
let desc_inst = description.replace(/\n\s*\n/g, '<br> ');

// Convert unordered lists to markdown format first
let desc_inst = convert_unordered_lists_to_markdown(description);

desc_inst = desc_inst.replace(/\n\s*\n/g, '<br> ');
desc_inst = desc_inst.replace(/\n/g, ' ');
desc_inst = desc_inst.replace(/<br \/>/g, ' ');
return desc_inst;
Expand All @@ -36,7 +119,11 @@ export function normalize_description_markdown(description: string): string {
if(!description){
return "";
}
const sections = description.split(/(```[\s\S]*?```)/);

// Convert unordered lists to markdown format first
let processed_description = convert_unordered_lists_to_markdown(description);

const sections = processed_description.split(/(```[\s\S]*?```)/);

for (let i = 0; i < sections.length; i++) {
if (!sections[i].startsWith('```')) {
Expand Down
6 changes: 6 additions & 0 deletions tests/documenter/complete/entity.verilogSource
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//!
//! Example of description beakline
//!
//! Example of unordered list:
//! * Normal operation mode
//! * Low power mode
//! * Debug mode
//! * Test mode
//!
//! Example of Wavedrom
//! image:
//! { signal: [
Expand Down
5 changes: 5 additions & 0 deletions tests/documenter/complete/entity.vhdlSource
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ use ieee.std_logic_1164.all;
--! @version 1.0.1
--! @brief Some description can be added here
--!
--! Example of unordered list:
--! * Normal operation mode
--! * Low power mode
--! * Debug mode
--! * Test mode
--!
--! Example of multiline code snipet:
--! ``` C
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,28 @@ also in multi-lines

Example of description beakline

Example of unordered list:

* Normal operation mode
* Low power mode
* Debug mode
* Test mode


Example of Wavedrom
image:



![alt text](wavedrom_fpUS0.svg "title")
![alt text](wavedrom_fgD90.svg "title")



Example of bitfield:



![alt text](wavedrom_jn9w1.svg "title")
![alt text](wavedrom_D2eS1.svg "title")



Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
This is an entity description 5
multiline.

Example of unordered list:

* Normal operation mode
* Low power mode
* Debug mode
* Test mode


Example of multiline code snipet:

Expand Down
161 changes: 161 additions & 0 deletions tests/documenter/unordered_list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Test cases for the unordered list feature
import { convert_unordered_lists_to_markdown } from "../../src/colibri/documenter/utils";

describe('Unordered List Conversion Tests', () => {

test('Basic asterisk list conversion', () => {
const input = `This is a description with a list:
* First item
* Second item
* Third item
End of description.`;

const expected = `This is a description with a list:

* First item
* Second item
* Third item

End of description.`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Basic dash list conversion', () => {
const input = `Configuration options:
- Option A
- Option B
- Option C`;

const expected = `Configuration options:

* Option A
* Option B
* Option C`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Mixed list markers should work', () => {
const input = `Mixed list:
* Item with asterisk
- Item with dash
* Another asterisk item`;

const expected = `Mixed list:

* Item with asterisk
* Item with dash
* Another asterisk item`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Single item should not be converted to list', () => {
const input = `Single item:
* Only one item
Regular text continues.`;

const expected = `Single item:
* Only one item
Regular text continues.`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Multi-line list items', () => {
const input = `Complex list:
* First item with continuation
on the next line
* Second item also spans
multiple lines
* Third item`;

const expected = `Complex list:

* First item with continuation on the next line
* Second item also spans multiple lines
* Third item`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Empty lines should terminate list', () => {
const input = `List with break:
* First item
* Second item

* This starts a new list
* Fourth item`;

const expected = `List with break:

* First item
* Second item


* This starts a new list
* Fourth item`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('No conversion for non-list content', () => {
const input = `Regular description without lists.
This is just normal text.
No special formatting here.`;

const expected = `Regular description without lists.
This is just normal text.
No special formatting here.`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('Empty or null input', () => {
expect(convert_unordered_lists_to_markdown("")).toBe("");
expect(convert_unordered_lists_to_markdown(null as any)).toBe("");
expect(convert_unordered_lists_to_markdown(undefined as any)).toBe("");
});

test('List at beginning of text', () => {
const input = `* First item
* Second item
* Third item
Regular text follows.`;

const expected = `* First item
* Second item
* Third item

Regular text follows.`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});

test('List at end of text', () => {
const input = `Description text here.
Available options:
* Option 1
* Option 2
* Option 3`;

const expected = `Description text here.
Available options:

* Option 1
* Option 2
* Option 3`;

const result = convert_unordered_lists_to_markdown(input);
expect(result).toBe(expected);
});
});
Loading