Skip to content

Commit

Permalink
feat(doc): change generation doc
Browse files Browse the repository at this point in the history
  • Loading branch information
aesteves60 authored and dpellier committed Jul 29, 2024
1 parent d3cfb7a commit 83011d6
Show file tree
Hide file tree
Showing 11 changed files with 585 additions and 392 deletions.
3 changes: 1 addition & 2 deletions packages/ods/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
"sass": "1.71.0",
"stencil-inline-svg": "1.1.0",
"ts-jest": "29.1.2",
"typedoc": "0.25.8",
"typedoc-plugin-markdown": "3.17.1",
"typedoc": "0.25.11",
"typescript": "5.3.3",
"wait-on": "7.2.0"
}
Expand Down
180 changes: 94 additions & 86 deletions packages/ods/scripts/generate-typedoc-md.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,65 @@ const path = require('path');
const isMultiple = process.argv[2]?.includes('multiple');
const typedocBasePath = path.resolve('dist', 'docs-api');
const pathPrefixIdx = process.argv.indexOf('--prefix');
const tableSeparator = '|';

const ReflectionKind = {
Project: 1,
Module: 2,
Namespace: 4,
Enum: 8,
EnumMember: 16,
Variable: 32,
Function: 64,
Class: 128,
Interface: 256,
Constructor: 512,
Property: 1024,
Method: 2048,
CallSignature: 4096,
IndexSignature: 8192,
ConstructorSignature: 16384,
Parameter: 32768,
TypeLiteral: 65536,
TypeParameter: 131072,
Accessor: 262144,
GetSignature: 524288,
SetSignature: 1048576,
TypeAlias: 2097152,
Reference: 4194304,
}

let pathPrefix = '';
if (pathPrefixIdx > -1) {
pathPrefix = process.argv[pathPrefixIdx + 1];
}

function convertJsonToMarkdown(jsonItems) {
const result = [];
const interfaces = []; // getInterfaces(jsonItems);
const types = getTypes(jsonItems);

const addSection = (stringArray, sectionString) => {
const res = stringArray;

if (res.length) {
result.push(sectionString);
result.push(...res);
}
};

// Create Table
result.push(
...(interfaces?.length ? ['* [**Interfaces**](#interfaces)'] : []),
...(types?.length ? ['* [**Types**](#types)'] : []),
);

addSection(interfaces, '\n## Interfaces');
addSection(types, '\n## Types');

return result.join('\n');
const classes = getClasses(jsonItems);
const enums = getEnums(jsonItems);

const hasProps = classes.props.length;
const hasMethods = classes.methods.length;
const hasEvents = classes.events.length;
const hasEnums = enums.length;

const tableOfContents = [
'## Table of Contents',
hasProps ? '[• Properties](#properties)\n' : '',
hasMethods ? '[• Methods](#methods)\n' : '',
hasEvents ? '[• Events](#events)\n' : '',
hasEnums ? '[• Enums](#enums)\n' : '',
];

return [
...tableOfContents,
hasProps ? '## Properties' : '', ...classes.props,
hasMethods ? '## Methods' : '', ...classes.methods,
hasEvents ? '## Events' : '', ...classes.events,
hasEnums ? '## Enums' : '', ...enums,
].join('\n');
}

function createSpecMd(component = '') {
//const typedocJson = require(path.resolve('docs-api', component, 'typedoc.json'));
const typedocJson = require(path.resolve(typedocBasePath, component, 'typedoc.json'));
// TODO test for prefixed project (like -ovh)
const dir = path.resolve('documentation', 'specifications', component);
Expand All @@ -70,73 +94,57 @@ function createSpecMd(component = '') {
}
}

function getInterfaces(jsonItems) {
const res = [];

jsonItems
.filter(({ kindString, children, indexSignature }) => kindString === 'Interface' && (!children || !indexSignature))
.forEach(({ name, children, indexSignature }) => {
res.push(`\n### ${name}`);

// Find default values
const defaultValues = {};

(jsonItems.find(({ kindString: defaultString, name: defaultName }) => {
return defaultString === 'Variable' && defaultName.toLowerCase() === `${name.toLowerCase()}defaultdoc`;
}))
?.declaration.children?.forEach(({ name, defaultValue }) => {
defaultValues[name] = defaultValue?.toString() || '';
});

if (indexSignature) {
res.push(tableSeparator + ['Key', 'Type', 'Description'].join(` ${tableSeparator} `) + tableSeparator);
res.push(tableSeparator + ['---', ':---:', '---'].join(`${tableSeparator}`) + tableSeparator);
res.push(tableSeparator + [
printType(indexSignature.parameters?.[0]?.type),
printType(indexSignature.type),
indexSignature.comment?.shortText,
].join(` ${tableSeparator} `) + tableSeparator);
return;
}
function getClasses(jsonItems) {
const classesDefinitions = jsonItems.filter(({ kind }) => kind === ReflectionKind.Class);

const children = classesDefinitions.flatMap(({ children }) => children);

res.push(
tableSeparator + ['Name', 'Type', 'Required', 'Default', 'Description'].join(` ${tableSeparator} `) + tableSeparator,
);
res.push(
tableSeparator + ['---', '---', ':---:', '---', '---'].join(`${tableSeparator}`) + tableSeparator,
);

children?.forEach(({ name, type, signatures, flags, comment }) => {
const commentString = (comment || (signatures && signatures[0]?.comment))?.shortText || '';

res.push(tableSeparator + [
`**\`${name}\`**`,
type ? printType(type) : printType(signatures?.[0]?.type),
!flags.isOptional ? '✴️' : '',
defaultValues[name] ? `\`${defaultValues[name]}\`` : '',
commentString.replace(/\n/g, ''),
].join(` ${tableSeparator} `) + tableSeparator);
});
const props = children
.filter(({ kind, decorators }) => kind === ReflectionKind.Property && decorators[0].escapedText === 'Prop')
.map((prop) => {
return [
`### ${prop.name}`,
`• ${prop.flags.isOptional ? '\`Optional\`': ''} **${prop.name}**: [${printType(prop.type)}] ${prop.defaultValue ? `= \`${prop.defaultValue}\`` : ''}`,
`${prop.comment?.summary?.[0].text ? '**Description**: ' + prop.comment?.summary?.[0].text : ''}`,
].join('\n\n');
});

return res;
}
const events = children
.filter(({ kind, decorators }) => kind === ReflectionKind.Property && decorators[0].escapedText === 'Event')
.map((event) => {
const returnType = `\`${event.type.name}\`\<${printType(event.type.typeArguments[0])}\>`
return [
`### ${event.name}\n\n▸ **${event.name}**(): ${returnType}`,
`${event.comment?.summary?.[0].text ? '**Description**: ' + event.comment?.summary?.[0].text : ''}`,
`#### Returns\n${returnType}`,
].join('\n\n');
});

function getTypes(jsonItems) {
const res = [];
const methods = children
.filter(({ kind, decorators }) => kind === ReflectionKind.Method && decorators?.[0]?.escapedText === 'Method')
.map((method) => {
const returnType = `\`${method.signatures[0].type.name}\`\<${printType(method.signatures[0].type.typeArguments[0])}\>`
return [
`### ${method.name}\n\n▸ **${method.name}**(): ${returnType}`,
`${method.signatures?.[0].comment.summary?.[0].text ? '**Description**: ' + method.signatures?.[0].comment.summary?.[0].text : ''}`,
`#### Returns\n${returnType}`,
].join('\n\n');
});

jsonItems
.filter((item) => item.kindString === 'Enumeration')
.forEach((enumeration) => {
res.push(`\n### ${enumeration.name}`);
res.push('| |\n|:---:|');
return {
props,
events,
methods,
};
}

if (enumeration.children) {
res.push(enumeration.children.map((property) => `| \`${property.name}\` |`).join('\n'));
}
function getEnums(jsonItems) {
return jsonItems
.filter(({ kind }) => kind === ReflectionKind.Enum)
.flatMap((enumDefinition) => {
const children = enumDefinition.children.map(({ name }) => `### ${name}\n\n• **${name}** = \`"${name}"\`\n`);
return `## Enumeration: ${enumDefinition.name}\n\n${children.join('\n')}\n`
});

return res;
}

function getTypeValue(tObj) {
Expand Down Expand Up @@ -166,7 +174,7 @@ function printType(typeObject) {
case 'array':
return `${printType(someType.elementType).replace(/^(_|`)|(_|`)$/g, '')}[]`;
case 'union':
return someType.types.map((tObj) => `\`${printType(tObj).replace(/^(_|`)|(_|`)$/g, '')}\``).join(' \\| ');
return someType.types.map((tObj) => `\`${printType(tObj).replace(/^(_|`)|(_|`)$/g, '')}\``).join(' \| ');
}
}
return '_unknown_';
Expand Down
49 changes: 49 additions & 0 deletions packages/ods/scripts/typedoc-plugin-decorator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const td = require("typedoc");
const ts = td.TypeScript;

/** @param {td.Application} app */
exports.load = function (app) {
// Add decorator info to reflections
// if you need parameters, you need app.converter.on(td.Converter.EVENT_CREATE_PARAMETER)
app.converter.on(td.Converter.EVENT_CREATE_DECLARATION, addDecoratorInfo);

// Add decorator info to serialized json
app.serializer.addSerializer({
priority: 0,
supports(item) {
return item instanceof td.DeclarationReflection;
},
toObject(item, obj, _ser) {
if (item.decorators) {
obj.decorators = item.decorators;
}
return obj;
},
});
};

/**
* @param {td.Context} context
* @param {td.DeclarationReflection} decl
*/
function addDecoratorInfo(context, decl) {
const symbol = context.project.getSymbolFromReflection(decl);
if (!symbol) {
return;
}
const declaration = symbol.valueDeclaration;
if (!declaration) {
return;
}
if (!ts.isPropertyDeclaration(declaration) && !ts.isMethodDeclaration(declaration)) {
return;
}

const decorators = declaration.modifiers?.filter(ts.isDecorator);
decl.decorators = decorators?.map((d) => {
return {
expression: d.getText(),
escapedText: d.expression.expression.escapedText,
};
});
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,60 @@
* [**Interfaces**](#interfaces)
* [**Types**](#types)

## Interfaces

### OdsSpinnerAttribute
|Name | Type | Required | Default | Description|
|---|---|:---:|---|---|
|**`contrasted`** | _boolean_ | | | contrasted or not: see component principles|
|**`inline`** | _boolean_ | | | full width or not: see component principles|
|**`mode`** | `indeterminate` | | | choose between infinite or progress spinner (infinite only for now)|
|**`size`** | `ODS_SPINNER_SIZE` | | | size: see component principles|

## Types

### ODS_SPINNER_MODE
| |
|:---:|
| `indeterminate` |

### ODS_SPINNER_SIZE
| |
|:---:|
| `lg` |
| `md` |
| `sm` |
## Table of Contents
[• Properties](#properties)

[• Methods](#methods)

[• Events](#events)

[• Enums](#enums)

## Properties
### color

**color**: [_primary_] = `ODS_SPINNER_COLOR.primary`

**Description**: test typedoc comment props
### size

**size**: [`sm` | `md` | `lg`] = `ODS_SPINNER_SIZE.md`


## Methods
### someMethodTest

**someMethodTest**(): `Promise`<`string` | `number`>

**Description**: test typedoc comment methods

#### Returns
`Promise`<`string` | `number`>
## Events
### focusEvent

**focusEvent**(): `EventEmitter`<_void_>

**Description**: test typedoc comment event

#### Returns
`EventEmitter`<_void_>
## Enums
## Enumeration: ODS_SPINNER_COLOR

### primary

**primary** = `"primary"`


## Enumeration: ODS_SPINNER_SIZE

### lg

**lg** = `"lg"`

### md

**md** = `"md"`

### sm

**sm** = `"sm"`

2 changes: 1 addition & 1 deletion packages/ods/src/components/spinner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"collection": "dist/collection/collection-manifest.json",
"scripts": {
"clean": "rimraf .stencil coverage dist docs-api www",
"doc": "typedoc --pretty --plugin typedoc-plugin-markdown --hideBreadcrumbs true --hideInPageTOC true",
"doc": "typedoc --pretty --plugin ../../../scripts/typedoc-plugin-decorator.js && node ../../../scripts/generate-typedoc-md.js",
"lint:scss": "stylelint 'src/components/**/*.scss'",
"lint:ts": "eslint 'src/**/*.{js,ts,tsx}'",
"start": "stencil build --dev --watch --serve",
Expand Down
Loading

0 comments on commit 83011d6

Please sign in to comment.