Skip to content

Commit

Permalink
Auto-generate API references
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardHelm committed Nov 6, 2024
1 parent 352694f commit a99df1c
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 238 deletions.
3 changes: 3 additions & 0 deletions apps/docs/.eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const CleanCSS = require('clean-css');
const fs = require('fs');
const path = require('path');
const packageInstallation = require('./shortcodes/packageInstallation');
const apiReference = require('./shortcodes/apiReference');
const glob = require('glob');
const { nxViteTsPaths } = require('@nx/vite/plugins/nx-tsconfig-paths.plugin');
const { spawnSync } = require('child_process');
Expand Down Expand Up @@ -132,6 +133,8 @@ module.exports = function (eleventyConfig) {

eleventyConfig.addShortcode('packageInstallation', packageInstallation);

eleventyConfig.addShortcode('apiReference', apiReference);

eleventyConfig.on('eleventy.before', resetExampleIndex);

eleventyConfig.on('eleventy.after', async ({ dir, runMode }) => {
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"projectType": "application",
"sourceRoot": "apps/vivid-demo/src",
"tags": [],
"implicitDependencies": ["components", "styles"],
"implicitDependencies": ["components", "styles", "wrapper-gen"],
"targets": {
"buildMeta": {
"executor": "nx:run-commands",
Expand Down
139 changes: 139 additions & 0 deletions apps/docs/shortcodes/apiReference.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
const markdownLibrary = require('../libraries/markdown-it');
const markdownTable = require('markdown-table');
const fs = require('fs');

const metadata = JSON.parse(
fs.readFileSync(`dist/libs/wrapper-gen/component-metadata.json`, 'utf-8')
);

const escapeMarkdown = (text = '') => text.replace(/([<>{}])/gm, '\\$1');

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High documentation

This does not escape backslash characters in the input.

const escapeType = (text = '') => text.replace(/([|])/gm, '\\$1');

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High documentation

This does not escape backslash characters in the input.

const escapeDescription = (text) => escapeMarkdown(text).replace(/\n/g, ' ');

const withImportsResolved = (type) =>
type.flatMap((t) => (t.resolvedType ? t.resolvedType : [t]));

const MaxEnumMembersToShow = 12;
function generateEnumType(type) {
let members = type.map((t) => t.text.replace(/['"]/g, '`'));
if (members.length > MaxEnumMembersToShow) {
members = members.slice(0, MaxEnumMembersToShow);
members.push(`... ${type.length - MaxEnumMembersToShow} more ...`);
}
return members.join('<br/>');
}

function generateTableWithType(objects, typeHeader = 'Type') {
return markdownTable([
['Name', typeHeader, 'Description'],
...objects.map(({ name, type, description }) => {
const resolvedType = withImportsResolved(type);
return [
`**${name}**`,
(resolvedType.length === 1
? `\`${resolvedType[0].text}\``
: `*Enum*:<br/>${generateEnumType(resolvedType)}`
).replace(/\|/g, '\\|'),

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High documentation

This does not escape backslash characters in the input.
escapeDescription(description),
];
}),
]);
}

function generateTable(slots) {
return markdownTable([
['Name', 'Description'],
...slots.map(({ name, description }) => [
`**${name}**`,
escapeDescription(description),
]),
]);
}

function generateMethodsTable(methods) {
const getTypeString = (types) =>
withImportsResolved(types)
.map((t) => t.text)
.join(' \\| ');
return markdownTable([
['Name', 'Type', 'Description'],
...methods.map(({ name, args, returnType, description }) => [
`**${name}**`,
`\`(${args.map(
({ name: argName, type }) => `${argName}: ${getTypeString(type)}`
)}) => ${getTypeString(returnType)}\``,
escapeDescription(description),
]),
]);
}

function generateVueModelsTable(vueModels, attributes) {
const getTypeString = (types) =>
withImportsResolved(types)
.map((t) => t.text)
.join(' \\| ');
return markdownTable([
['Name', 'Type', 'Description'],
...vueModels.map(({ name, attributeName }) => {
const attribute = attributes.find((attr) => attr.name === attributeName);

return [
`**${name}**`,
`\`${getTypeString(attribute.type)}\``,
escapeDescription(attribute.description),
];
}),
]);
}

function generateDocPageForComponent({
description,
attributes,
events,
slots,
methods,
vueModels,
}) {
let text = `## API Reference
${escapeMarkdown(description)}\n`;
if (attributes.length > 0) {
text += `\n### Props
${generateTableWithType(attributes)}\n`;
}

if (events.length > 0) {
text += `\n### Events
${generateTableWithType(events, 'Event Type')}\n`;
}

if (slots.length > 0) {
text += `\n### Slots
${generateTable(slots)}\n`;
}

if (methods.length > 0) {
text += `\n### Methods
${generateMethodsTable(methods)}\n`;
}

if (vueModels.length > 0) {
text += `\n### V-Models
${generateVueModelsTable(vueModels, attributes)}\n`;
}

return text;
}

module.exports = function apiReference(componentName) {
const def = metadata.find((def) => def.name === componentName);

return markdownLibrary.render(generateDocPageForComponent(def));
};
67 changes: 1 addition & 66 deletions libs/components/src/lib/button/README.md

Large diffs are not rendered by default.

29 changes: 1 addition & 28 deletions libs/components/src/lib/card/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,31 +188,4 @@ The number of lines is controlled by css variable `--subtitle-line-clamp`.

## API Reference

### Properties

<div class="table-wrapper">

| Name | Type | Description |
| -------------- | ----------------------------------------- | ----------------------------- |
| **appearance** | `elevated` (default), `outlined`, `ghost` | Sets the element's appearance |
| **elevation** | `2`, `4` (default), `8`, `12`, `16`, `24` | Sets the element's elevation |
| **headline** | `string` | Sets the element's headline |
| **icon** | `string` | Sets the element's icon |
| **subtitle** | `string` | Sets the element's subtitle |
| **text** | `string` | Sets the element's text |

</div>

### Slots

<div class="table-wrapper">

| Name | Description |
| ----------- | ------------------------------------------------------------ |
| **Graphic** | Add graphic element to card. Overrides the icon property |
| **Media** | Use to display images or video content above the card header |
| **Meta** | Use for adding action content, of info in the card header |
| **Footer** | Content in the card footer. |
| **Main** | Override a card's predefined template |

</div>
{% apiReference "card" %}
21 changes: 1 addition & 20 deletions libs/components/src/lib/icon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,4 @@ If the component is used without a `connotation`, it will use the current text c

## API Reference

### Properties

| Name | Type | Description |
| ---------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| **aria-current** | _Enum_:<br/>`page`<br/>`step`<br/>`location`<br/>`date`<br/>`time`<br/>`true`<br/>`false` | Indicates the element that represents the current item within a container or set of related elements. |
| **connotation** | _Enum_:<br/>`accent`<br/>`cta`<br/>`success`<br/>`alert`<br/>`warning`<br/>`information` | The connotation the icon should have. |
| **size** | _Enum_:<br/>-6<br/>-5<br/>-4<br/>-3<br/>-2<br/>-1<br/>0<br/>1<br/>2<br/>3<br/>4<br/>5 | |
| **name** | _Enum_:<br/>`[icon-name]` | Indicates which icon to resolve. See the Vivid Icon Gallery for available icons: https://icons.vivid.vonage.com/ |

### Events

| Name | Event Type | Description |
| --------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **click** | `MouseEvent` | Fires when a pointing device button (such as a mouse's primary mouse button) is both pressed and released while the pointer is located inside the element. |

### Slots

| Name | Description |
| ----------- | ------------- |
| **default** | Default slot. |
{% apiReference "icon" %}
28 changes: 1 addition & 27 deletions libs/components/src/lib/option/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,30 +141,4 @@ If the option is represented as a tag in a [Searchable Select](/components/searc
## API Reference
### Properties
<div class="table-wrapper">
| Name | Type | Description |
| ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **disabled** | `boolean` | Sets the option to be disabled |
| **icon** | _Enum_:<br/>`[icon-name]` | A decorative icon for the element. See the [Vivid Icon Gallery](/icons/icons-gallery/) for available icons and `icon-name`s |
| **label** | `string` | Text to be displayed instead of `text` when the option is selected |
| **selected** | `boolean` | Sets the option to be selected |
| **text** | `string` | Sets the option's text |
| **value** | `string` | Value to be submited as part of the form data |
</div>
### Slots
### Slots
<div class="table-wrapper">
| Name | Description |
| ------------ | ------------------------------------------------------------------------- |
| **icon** | Add an icon before the option's text |
| **tag-icon** | Icon to be displayed in the tag when selected inside of Searchable Select |
</div>
{% apiReference "option" %}
46 changes: 1 addition & 45 deletions libs/components/src/lib/select/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,48 +258,4 @@ Use `--select-height` to customize the `max-height` of the dropdown.
## API Reference
### Properties
<div class="table-wrapper">
| Name | Type | Description |
| ------------------ | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **appearance** | `fieldset` (default), `ghost` | Sets the element's appearance |
| **disabled** | `boolean` | Sets the element's disabled state. A disabled element will not be included during form submission. |
| **error-text** | `string` | Sets the element's error text |
| **fixed-dropdown** | `boolean` | Sets the position strategy of the dropdown to fixed |
| **helper-text** | `string` | Sets the element's helper text |
| **icon** | _Enum_:<br/>`[icon-name]` | A decorative icon for the element. See the [Vivid Icon Gallery](/icons/icons-gallery/) for available icons and `icon-name`s |
| **label** | `string` | Sets the element's label |
| **multiple** | `boolean` | Sets the element to allow multiple selections |
| **open** | `boolean` | Sets the element's menu to be open |
| **placeholder** | `string` | Sets the text to be displayed when no option is selected |
| **scale** | `normal` (default), `condensed` | Sets the display size of the input element |
| **shape** | `rounded` (default), `pill` | Sets the shape of the select element |
| **success-text** | `string` | Sets the element's success text |
</div>
### Events
<div class="table-wrapper">
| Name | Type | Bubbles | Composed | Description |
| ---------- | ------------------------ | ------- | -------- | ----------------------------------------------- |
| **input** | `CustomEvent<undefined>` | No | Yes | Fired when an option is selected or unselected. |
| **change** | `CustomEvent<undefined>` | No | Yes | Fired when an option is selected or unselected. |
</div>
### Slots
<div class="table-wrapper">
| Name | Description |
| --------------- | ------------------------------------------------------------------ |
| **default** | Default slot meant for Option component to provide the option list |
| **helper-text** | Add HTML content for helper text |
| **icon** | Add an icon to the component. |
| **meta** | Show meta information after the selected option label |
</div>
{% apiReference "select" %}
Loading

0 comments on commit a99df1c

Please sign in to comment.