better format md

* merge all files in one
* order files by path order
* remove path on title and add a more precise table of content
This commit is contained in:
Jordan Blasenhauer 2024-05-18 22:58:07 +02:00
parent e1e10b4cbc
commit 5171c5f6fb
2 changed files with 476 additions and 5 deletions

368
jsdoc/output/COMPONENTS.md Normal file
View file

@ -0,0 +1,368 @@
## Builder.vue
This component is a wrapper to create a complete page using containers and widgets.
We have to define each container and each widget inside it.
This is an abstract component that will be used to create any kind of page content (base dashboard elements like menu and news excluded)
### Parameters
* `builder` **[array][4]** Array of containers and widgets
### Examples
```javascript
[
{
"type": "card", // this can be a "card", "modal", "table"... etc
"containerClass": "", // tailwind css grid class (items-start, ...)
"containerColumns" : {"pc": 12, "tablet": 12, "mobile": 12},
"title" : "My awesome card", // container title
// Each widget need a name (here type) and associated data
// We need to send specific data for each widget type
widgets: [
{
type : "Checkbox",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id:"test-check", value: "yes", label: "Checkbox", name: "checkbox", required: true, version: "v1.0.0", hideLabel: false, headerClass: "text-red-500" }
}, {
type : "Select",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id: 'test-select', value: 'yes', values: ['yes', 'no'], name: 'test-select', disabled: false, required: true, label: 'Test select', tabId: '1',}
}
]
}
]
```
## Forms
### Field
#### Checkbox.vue
This component is used to create a complete checkbox field input with error handling and label.
We can also add popover to display more information.
It is mainly use in forms.
##### Parameters
* `id` **[string][4]** 
* `name` **[string][4]** 
* `label` **[string][4]** 
* `value` **[string][4]** 
* `disabled` **[boolean][5]** (optional, default `false`)
* `required` **[boolean][5]** (optional, default `false`)
* `columns` **[object][6]** (optional, default `{"pc":"12","tab":"12","mob":"12}`)
* `hideLabel` **[boolean][5]** (optional, default `false`)
* `containerClass` **[string][4]** (optional, default `""`)
* `headerClass` **[string][4]** (optional, default `""`)
* `inpClass` **[string][4]** (optional, default `""`)
* `tabId` **([string][4] | [number][7])** (optional, default `""`)
##### Examples
```javascript
{
columns : {"pc": 6, "tablet": 12, "mobile": 12},
id:"test-check",
value: "yes",
label: "Checkbox",
name: "checkbox",
required: true,
hideLabel: false,
headerClass: "text-red-500"
}
```
#### Datepicker.vue
This component is used to create a complete datepicker field input with error handling and label.
You can define a default date, a min and max date, and a format.
We can also add popover to display more information.
It is mainly use in forms.
##### Parameters
* `id` **[string][4]** 
* `name` **[string][4]** 
* `label` **[string][4]** 
* `defaultDate` **([string][4] | [number][5] | [date][6])** Default date when instanciate (optional, default `null`)
* `noPickBeforeStamp` **([string][4] | [number][5])** Impossible to pick a date before this date (optional, default `""`)
* `noPickAfterStamp` **([string][4] | [number][5])** Impossible to pick a date after this date (optional, default `""`)
* `hideLabel` **[boolean][7]** (optional, default `false`)
* `columns` **([object][8] | [boolean][7])** (optional, default `{"pc":"12","tab":"12","mob":"12}`)
* `disabled` **[boolean][7]** (optional, default `false`)
* `required` **[boolean][7]** (optional, default `false`)
* `headerClass` **[string][4]** (optional, default `""`)
* `containerClass` **[string][4]** (optional, default `""`)
* `tabId` **([string][4] | [number][5])** (optional, default `""`)
##### Examples
```javascript
{
id: 'test-date',
columns : {"pc": 6, "tablet": 12, "mobile": 12},
disabled: false,
required: true,
defaultDate: 1735682600000,
noPickBeforeStamp: 1735682600000,
noPickAfterStamp: 1735689600000,
inpClass: "text-center",
}
```
#### Input.vue
This component is used to create a complete input field input with error handling and label.
We can add a clipboard button to copy the input value.
We can also add a password button to show the password.
We can also add popover to display more information.
It is mainly use in forms.
##### Parameters
* `id` **[string][4]** 
* `name` **[string][4]** 
* `type` **[string][4]** text, email, password, number, tel, url
* `value` **[string][4]** 
* `label` **[string][4]** 
* `disabled` **[boolean][5]** (optional, default `false`)
* `required` **[boolean][5]** (optional, default `false`)
* `placeholder` **[string][4]** (optional, default `""`)
* `pattern` **[string][4]** (optional, default `"(?.*)"`)
* `clipboard` **[boolean][5]** allow to copy the input value (optional, default `false`)
* `readonly` **[boolean][5]** allow to read only the input value (optional, default `false`)
* `hideLabel` **[boolean][5]** (optional, default `false`)
* `containerClass` **[string][4]** (optional, default `""`)
* `inpClass` **[string][4]** (optional, default `""`)
* `headerClass` **[string][4]** (optional, default `""`)
* `tabId` **([string][4] | [number][6])** (optional, default `""`)
##### Examples
```javascript
{
id: 'test-input',
value: 'yes',
type: "text",
name: 'test-input',
disabled: false,
required: true,
label: 'Test input',
pattern : "(test)",
}
```
#### Select.vue
This component is used to create a complete select field input with error handling and label.
We can be more precise by adding values that need to be selected to be valid.
We can also add popover to display more information.
It is mainly use in forms.
##### Parameters
* `id` **[string][4]** 
* `name` **[string][4]** 
* `value` **[string][4]** 
* `label` **[string][4]** 
* `values` **[array][5]** 
* `disabled` **[boolean][6]** (optional, default `false`)
* `required` **[boolean][6]** (optional, default `false`)
* `requiredValues` **[array][5]** values that need to be selected to be valid, works only if required is true (optional, default `[]`)
* `columns` **([object][7] | [boolean][6])** (optional, default `{"pc":"12","tab":"12","mob":"12}`)
* `hideLabel` **[boolean][6]** (optional, default `false`)
* `containerClass` **[string][4]** (optional, default `""`)
* `inpClass` **[string][4]** (optional, default `""`)
* `headerClass` **[string][4]** (optional, default `""`)
* `tabId` **([string][4] | [number][8])** (optional, default `""`)
##### Examples
```javascript
{
id: 'test-input',
value: 'yes',
values : ['yes', 'no'],
name: 'test-input',
disabled: false,
required: true,
requiredValues : ['no'], // need required to be checked
label: 'Test select',
}
```
### Header
#### Field.vue
This component is used with field in order to link a label to field type.
We can add popover to display more information.
Always use with field component.
##### Parameters
* `label` **[string][4]** 
* `name` **[string][4]** 
* `required` **[boolean][5]** (optional, default `false`)
* `hideLabel` **[boolean][5]** (optional, default `false`)
* `headerClass` **[string][4]** (optional, default `""`)
##### Examples
```javascript
{
label: 'Test',
version : "0.1.0",
name: 'test-input',
required: true,
}
```
## Icons
### Button
#### Add.vue
This component is used to create a complete svg icon for a button.
This svg is related to a add action button.
##### Parameters
* `iconColor` **[string][4]** (optional, default `"white"`)
##### Examples
```javascript
{
iconColor: 'white',
}
```
## Widget
### Button.vue
This component is a standard button.
You can link this button to the event store on click with eventAttr.
This will allow you to share a value with other components, for example switching form on a click.
The eventAttr object must contain the store name and the value to send on click at least.
It can also contain the target id element and the expanded value, this will add additionnal accessibility attributs to the button.
#### Parameters
* `id` **[string][4]** 
* `text` **[string][4]** Content of the button
* `type` **[string][4]** Can be of type button || submit (optional, default `"button"`)
* `disabled` **[boolean][5]** (optional, default `false`)
* `hideText` **[boolean][5]** Hide text to only display icon (optional, default `false`)
* `color` **[string][4]** (optional, default `"primary"`)
* `size` **[string][4]** Can be of size sm || normal || lg || xl (optional, default `"normal"`)
* `iconName` **[string][4]** Name in lowercase of icons store on /Icons/Button (optional, default `""`)
* `iconColor` **[string][4]** (optional, default `""`)
* `eventAttr` **[object][6]** Store event on click {"store" : \<store\_name>, "default" : \<default\_value>, "value" : \<value\_stored\_on\_click>, "target"<optional> : \<target\_id\_element>, "valueExpanded" : "expanded\_value"} (optional, default `{}`)
* `tabId` **([string][4] | [number][7])** (optional, default `""`)
#### Examples
```javascript
{
id: "open-modal-btn",
text: "Open modal",
disabled: false,
hideText: true,
color: "green",
size: "normal",
iconName: "modal",
iconColor: "white",
eventAttr: {"store" : "modal", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},7
}
```
### Container.vue
This component is a basic container that can be used to wrap other components.
In case we are working with grid system, we can add columns to position the container.
We can define additional class too.
This component is mainly use as widget container.
#### Parameters
* `containerClass` **[string][4]** Additional class (optional, default `""`)
* `columns` **([object][5] | [boolean][6])** Work with grid system { pc: 12, tablet: 12, mobile: 12} (optional, default `false`)
#### Examples
```javascript
{
containerClass: "w-full h-full bg-white rounded shadow-md",
columns: { pc: 12, tablet: 12, mobile: 12}
}
```
### Flex.vue
This component is a basic container that can be used to wrap other components.
Per default, it aligns the components horizontally using flex.
We can define additional class too.
This component is mainly use as widget container or for groups of widget.
#### Parameters
* `flexClass` **[string][4]** Additional class (optional, default `"flex-start"`)
#### Examples
```javascript
{
flexClass: "flex-start"
}
```
### Grid.vue
This component is a basic container that can be used to wrap other components.
This container is based on a grid system and will return a grid container with 12 columns.
In case we are working with grid system, we can add columns to position the container.
We can define additional class too.
This component is mainly use as widget container or as a child of a GridLayout.
#### Parameters
* `gridClass` **[string][4]** Additional class (optional, default `"items-start"`)
* `columns` **([object][5] | [boolean][6])** Work with grid system { pc: 12, tablet: 12, mobile: 12} (optional, default `false`)
#### Examples
```javascript
{
columns: { pc: 12, tablet: 12, mobile: 12},
gridClass: "items-start"
}
```
### GridLayout.vue
This component is used for top level page layout.
This will determine the position of layout components based on the grid system.
We can create card, modal, table and others top level layout using this component.
This component is mainly use as Grid parent component.
#### Parameters
* `type` **[string][4]** Type of layout component, we can have : card, table, modal and others (optional, default `"card"`)
* `title` **[string][4]** Title of the layout component, will be displayed at the top if exists. Type of layout component will determine the style of the title. (optional, default `""`)
* `columns` **[object][5]** Work with grid system { pc: 12, tablet: 12, mobile: 12} (optional, default `{"pc":12,"tablet":12,"mobile":12}`)
* `gridLayoutClass` **[string][4]** Additional class (optional, default `"items-start"`)
#### Examples
```javascript
{
type: "card",
title: "Test",
columns: { pc: 12, tablet: 12, mobile: 12},
gridLayoutClass: "items-start"
}
```

View file

@ -25,7 +25,6 @@ function getDirectoriesRecursive(srcpath) {
// Get the script part of a Vue file and create a JS file
function vue2js() {
const folders = getDirectoriesRecursive(inputFolder);
console.log(folders);
// Read every subfolders from the input folder and get all files
folders.forEach((folder) => {
const files = fs.readdirSync(path.join(folder), {
@ -61,16 +60,16 @@ function js2md() {
ouputFolder,
file.name
)} -f md > ${path.join(ouputFolder, file.name.replace(".js", ".md"))}`;
console.log(command + "\n");
// Run the command
const { execSync } = require("child_process");
execSync(command, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
// console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
// console.log(`stdout: ${stdout}`);
// console.error(`stderr: ${stderr}`);
});
});
// Remove all JS files when all processes are done
@ -94,6 +93,110 @@ function formatMd() {
data = data.substring(index);
fs.writeFileSync(path.join(ouputFolder, file.name), data, "utf8");
});
// Create order using the tag title path of each file
const order = [];
files.forEach((file, id) => {
// Get the title from first line
const data = fs.readFileSync(path.join(ouputFolder, file.name), "utf8");
const filePath = data.split("\n")[0].replace("## ", "");
order.push({ path: filePath, file: file });
});
// Sort order by path
order.sort((a, b) => {
return a.path.localeCompare(b.path);
});
// Create a md file to merge
const merge = path.join(ouputFolder, "COMPONENTS.md");
fs.writeFileSync(merge, "", "utf8");
// Append each file in the order
order.forEach((item) => {
let data = fs.readFileSync(path.join(ouputFolder, item.file.name), "utf8");
fs.appendFileSync(merge, data, "utf8");
});
// Get data from merge
let data = fs.readFileSync(merge, "utf8");
let isLevel = true;
let currAttemps = 0;
const maxAttemps = 6;
while (isLevel && currAttemps < maxAttemps) {
currAttemps++;
const titles = [];
let tag = "#";
for (let i = 0; i < currAttemps; i++) {
tag += "#";
}
tag += " ";
console.log(tag);
// Each time, get the first level title and add it to the titles array
data.split("\n").forEach((line) => {
if (line.startsWith(tag) && line.includes("/")) {
const firstLevel = line.split("/")[0];
if (!titles.includes(firstLevel.replace(tag, "").trim()))
titles.push(firstLevel.replace(tag, ""));
}
});
// Create a top title at the first occurrence
// And remove from component the first level string
titles.forEach((title) => {
let isTitleSet = false;
data.split("\n").forEach((line) => {
// For title
if (line.startsWith(tag) && line.includes("/")) {
// Add a top title before the current line
if (!isTitleSet && line.includes(`${title}/`)) {
data = data.replace(
line,
`${tag} ${title}\n\n${line
.replace(tag, "#" + tag)
.replace(`${title}/`, "")}`
);
isTitleSet = true;
return;
}
if (line.includes(`${title}/`)) {
data = data.replace(
line,
line.replace(tag, "#" + tag).replace(`${title}/`, "")
);
}
return;
}
});
});
}
// Update the child of .vue component title
let componentTag = "";
let dataSplit = data.split("\n");
data.split("\n").forEach((line, id) => {
if (line.startsWith("#") && line.includes(".vue")) {
componentTag = line.split(" ")[0];
return;
}
if (
(line.startsWith("#") && line.includes("Parameters")) ||
(line.startsWith("#") && line.includes("Examples"))
) {
const elTag = line.split(" ")[0];
// get line per id
const updateLine = line.replace(elTag, `${componentTag}#`);
dataSplit[id] = updateLine;
}
});
// Update the data adn merge
data = dataSplit.join("\n");
// Remove 3 first lines
data = data.split("\n").slice(3).join("\n");
fs.writeFileSync(merge, data, "utf8");
}
// Check that input folder exists