mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
build: add script to generate component index
- move typedefs for correct type parsing
This commit is contained in:
parent
c8b0b008c7
commit
5968e22bd9
14 changed files with 5518 additions and 207 deletions
5167
COMPONENT_INDEX.md
Normal file
5167
COMPONENT_INDEX.md
Normal file
File diff suppressed because it is too large
Load diff
110
scripts/rollup/generate-index.js
Normal file
110
scripts/rollup/generate-index.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
const toLink = (text) => text.toLowerCase().replace(/\s+/g, "-");
|
||||||
|
|
||||||
|
const toMdLink = (text) => `[${text}](#${toLink(text)})`;
|
||||||
|
|
||||||
|
const formatType = (type) => `<code>${type.replace(/\|/g, "|")}</code>`;
|
||||||
|
|
||||||
|
const HEADER_PROPS = "| Prop name | Type | Default value |\n| :- | :- | :- |\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use library component metadata to generate component documentation in markdown format.
|
||||||
|
* @param {Map<string, { component: { exported_props: Map<string, any>; slots: Map<string, any>; } typedefs: {name: string; type: string;}[] }>} components
|
||||||
|
* @param {Map<string, string[]>} groups
|
||||||
|
* @param {{name: string; version: string; homepage: string;}} pkg
|
||||||
|
*/
|
||||||
|
export function generateIndex(components, groups, pkg) {
|
||||||
|
let code = `# Component Index\n\n`;
|
||||||
|
|
||||||
|
code += `> ${components.size} components exported from ${pkg.name} ${pkg.version}\n\n`;
|
||||||
|
|
||||||
|
groups.forEach((group, component_group) => {
|
||||||
|
if (group.length > 1) {
|
||||||
|
code += `- ${component_group}\n`;
|
||||||
|
group.forEach((component) => {
|
||||||
|
code += ` - ${toMdLink(component)}\n`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
code += `- ${toMdLink(component_group)}\n`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
code += "---\n";
|
||||||
|
|
||||||
|
components.forEach((component, moduleName) => {
|
||||||
|
const {
|
||||||
|
typedefs,
|
||||||
|
component: { exported_props, slots, forwarded_events, dispatched_events },
|
||||||
|
} = component;
|
||||||
|
|
||||||
|
code += `## ${moduleName}\n\n`;
|
||||||
|
code += `### Import path\n\n`;
|
||||||
|
code += `\`\`\`js\nimport { ${moduleName} } from "${pkg.name}";\n\`\`\`\n\n`;
|
||||||
|
|
||||||
|
code += "### Props\n\n";
|
||||||
|
|
||||||
|
if (exported_props.size > 0) {
|
||||||
|
if (typedefs.length > 0) {
|
||||||
|
let definitions = "";
|
||||||
|
|
||||||
|
typedefs.forEach(({ name, type }) => {
|
||||||
|
const typedef = type.startsWith("{")
|
||||||
|
? `interface ${name} ${type}`
|
||||||
|
: `type ${name} = ${type};`;
|
||||||
|
|
||||||
|
definitions += `${typedef}\n\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
code += `\`\`\`ts\n// \`${moduleName}\` type definitions\n\n${definitions}\n\`\`\`\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
code += HEADER_PROPS;
|
||||||
|
|
||||||
|
exported_props.forEach((prop, name) => {
|
||||||
|
code += `| ${name}${
|
||||||
|
prop.kind === "const" ? " (`constant`)" : ""
|
||||||
|
} | ${formatType(prop.type)} | ${prop.value || "--"}|\n`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
code += "No exported props.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "### Slots\n\n";
|
||||||
|
|
||||||
|
if (slots.size > 0) {
|
||||||
|
if (slots.get("default")) {
|
||||||
|
code += "- `<slot>...</slot>`\n";
|
||||||
|
} else {
|
||||||
|
slots.forEach((slot, name) => {
|
||||||
|
if (slot.default) return;
|
||||||
|
code += `- \`<slot name="${name}">...</slot>\`\n`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
code += "No slots.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "### Forwarded events\n\n";
|
||||||
|
|
||||||
|
if (forwarded_events.size > 0) {
|
||||||
|
forwarded_events.forEach((event, name) => {
|
||||||
|
code += `- \`on:${name}\`\n`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
code += "No forwarded events.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "### Dispatched events\n\n";
|
||||||
|
|
||||||
|
if (dispatched_events.size > 0) {
|
||||||
|
dispatched_events.forEach((event, name) => {
|
||||||
|
code += `- \`on:${name}\`\n`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
code += "No dispatched events.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "---\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
return { code };
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ export function generateTypes(components, pkg) {
|
||||||
// Type definitions for ${pkg.name} ${pkg.version}
|
// Type definitions for ${pkg.name} ${pkg.version}
|
||||||
// Project: ${pkg.homepage}
|
// Project: ${pkg.homepage}
|
||||||
|
|
||||||
class SvelteComponent {
|
export class CarbonSvelteComponent {
|
||||||
$$prop_def: {};
|
$$prop_def: {};
|
||||||
|
|
||||||
$$slot_def: {};
|
$$slot_def: {};
|
||||||
|
@ -35,6 +35,10 @@ export function generateTypes(components, pkg) {
|
||||||
$$prop_def += "* " + line + "\n";
|
$$prop_def += "* " + line + "\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (prop.kind === "const") {
|
||||||
|
$$prop_def += "* @constant\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (prop.value !== undefined) {
|
if (prop.value !== undefined) {
|
||||||
$$prop_def += "* @default " + prop.value + "\n";
|
$$prop_def += "* @default " + prop.value + "\n";
|
||||||
}
|
}
|
||||||
|
@ -67,7 +71,7 @@ export function generateTypes(components, pkg) {
|
||||||
});
|
});
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
export class ${moduleName} extends SvelteComponent {
|
export class ${moduleName} extends CarbonSvelteComponent {
|
||||||
${!!$$prop_def ? "$$prop_def: {" + $$prop_def + "}\n" : ""}
|
${!!$$prop_def ? "$$prop_def: {" + $$prop_def + "}\n" : ""}
|
||||||
|
|
||||||
${!!$$slot_def ? "$$slot_def: {" + $$slot_def + "}\n" : ""}
|
${!!$$slot_def ? "$$slot_def: {" + $$slot_def + "}\n" : ""}
|
||||||
|
|
|
@ -40,10 +40,16 @@ export function parseComponent(source, hooks) {
|
||||||
|
|
||||||
let value = undefined;
|
let value = undefined;
|
||||||
let type = undefined;
|
let type = undefined;
|
||||||
|
let kind = node.declaration.kind;
|
||||||
let description = null;
|
let description = null;
|
||||||
|
|
||||||
if (init != null) {
|
if (init != null) {
|
||||||
value = init.raw;
|
if (init.type === "ObjectExpression") {
|
||||||
|
value = source.slice(init.start, init.end).replace(/\n/g, " ");
|
||||||
|
type = value;
|
||||||
|
} else {
|
||||||
|
value = init.raw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const general_comments = commentParser(source);
|
const general_comments = commentParser(source);
|
||||||
|
@ -60,14 +66,15 @@ export function parseComponent(source, hooks) {
|
||||||
);
|
);
|
||||||
|
|
||||||
description = comment[0].description;
|
description = comment[0].description;
|
||||||
type = comment[0].tags[0].type;
|
|
||||||
|
type = comment[0].tags[comment[0].tags.length - 1].type;
|
||||||
} else {
|
} else {
|
||||||
throw Error(
|
throw Error(
|
||||||
`[${hooks.component}] property \`${id.name}\` should be annotated.`
|
`[${hooks.component}] property \`${id.name}\` should be annotated.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
exported_props.set(id.name, { value, type, description });
|
exported_props.set(id.name, { kind, value, type, description });
|
||||||
break;
|
break;
|
||||||
case "Slot":
|
case "Slot":
|
||||||
let slot_name = null;
|
let slot_name = null;
|
||||||
|
@ -82,10 +89,17 @@ export function parseComponent(source, hooks) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let default_value = "";
|
||||||
|
|
||||||
|
node.children.forEach((child) => {
|
||||||
|
default_value += `${source.slice(child.start, child.end)}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
slots.set(slot_name == null ? "default" : slot_name, {
|
slots.set(slot_name == null ? "default" : slot_name, {
|
||||||
attributes: node.attributes,
|
attributes: node.attributes,
|
||||||
children: node.children,
|
children: node.children,
|
||||||
default: slot_name == null,
|
default: slot_name == null,
|
||||||
|
default_value,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "EventHandler":
|
case "EventHandler":
|
||||||
|
@ -102,9 +116,11 @@ export function parseComponent(source, hooks) {
|
||||||
if (node.name === dispatcher_name) {
|
if (node.name === dispatcher_name) {
|
||||||
const [name, detail] = node.parent.arguments;
|
const [name, detail] = node.parent.arguments;
|
||||||
|
|
||||||
dispatched_events.set(name.raw, {
|
if (name.value !== undefined) {
|
||||||
detail: detail ? source.slice(detail.start, detail.end) : undefined,
|
dispatched_events.set(name.value, {
|
||||||
});
|
detail: detail ? source.slice(detail.start, detail.end) : undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pkg from "../../package.json";
|
||||||
import { format } from "prettier";
|
import { format } from "prettier";
|
||||||
import { parseComponent } from "./parse-component";
|
import { parseComponent } from "./parse-component";
|
||||||
import { generateTypes } from "./generate-types";
|
import { generateTypes } from "./generate-types";
|
||||||
|
import { generateIndex } from "./generate-index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollup plugin to generate library TypeScript definitions and documentation.
|
* Rollup plugin to generate library TypeScript definitions and documentation.
|
||||||
|
@ -59,9 +60,13 @@ function pluginGenerateDocs() {
|
||||||
},
|
},
|
||||||
writeBundle() {
|
writeBundle() {
|
||||||
const { code: types } = generateTypes(components, pkg);
|
const { code: types } = generateTypes(components, pkg);
|
||||||
const definitions = format(types, { parser: "typescript" });
|
fs.writeFileSync(pkg.types, format(types, { parser: "typescript" }));
|
||||||
|
|
||||||
fs.writeFileSync(pkg.types, definitions);
|
const { code: index } = generateIndex(components, groups, pkg);
|
||||||
|
fs.writeFileSync(
|
||||||
|
"./COMPONENT_INDEX.md",
|
||||||
|
format(index, { parser: "markdown" })
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* @typedef {{ id: string; text: string; }} ComboBoxItem
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the combobox items
|
* Set the combobox items
|
||||||
* @type {ComboBoxItem[]} [items=[]]
|
* @type {ComboBoxItem[]} [items=[]]
|
||||||
|
@ -111,6 +107,10 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{ id: string; text: string; }} ComboBoxItem
|
||||||
|
*/
|
||||||
|
|
||||||
import { createEventDispatcher, afterUpdate } from "svelte";
|
import { createEventDispatcher, afterUpdate } from "svelte";
|
||||||
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16";
|
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16";
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* @typedef {string} DropdownItemId
|
|
||||||
* @typedef {string} DropdownItemText
|
|
||||||
* @typedef {{ id: DropdownItemId; text: DropdownItemText; }} DropdownItem
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the dropdown items
|
* Set the dropdown items
|
||||||
* @type {DropdownItem[]} [items=[]]
|
* @type {DropdownItem[]} [items=[]]
|
||||||
|
@ -113,6 +107,12 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {string} DropdownItemId
|
||||||
|
* @typedef {string} DropdownItemText
|
||||||
|
* @typedef {{ id: DropdownItemId; text: DropdownItemText; }} DropdownItem
|
||||||
|
*/
|
||||||
|
|
||||||
import { setContext } from "svelte";
|
import { setContext } from "svelte";
|
||||||
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16";
|
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16";
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* @typedef {string[]} Files
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the accepted file types
|
* Specify the accepted file types
|
||||||
* @type {string[]} [accept=[]]
|
* @type {string[]} [accept=[]]
|
||||||
|
@ -64,6 +60,10 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {string[]} Files
|
||||||
|
*/
|
||||||
|
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
|
@ -30,12 +30,6 @@
|
||||||
*/
|
*/
|
||||||
export let aspectRatio = undefined;
|
export let aspectRatio = undefined;
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {boolean | number} ColumnSize
|
|
||||||
* @typedef {{span?: ColumnSize; offset: number;}} ColumnSizeDescriptor
|
|
||||||
* @typedef {ColumnSize | ColumnSizeDescriptor} ColumnBreakpoint
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the small breakpoint
|
* Set the small breakpoint
|
||||||
* @type {ColumnBreakpoint} [sm]
|
* @type {ColumnBreakpoint} [sm]
|
||||||
|
@ -66,6 +60,12 @@
|
||||||
*/
|
*/
|
||||||
export let max = undefined;
|
export let max = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {boolean | number} ColumnSize
|
||||||
|
* @typedef {{span?: ColumnSize; offset: number;}} ColumnSizeDescriptor
|
||||||
|
* @typedef {ColumnSize | ColumnSizeDescriptor} ColumnBreakpoint
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column breakpoints
|
* Column breakpoints
|
||||||
* @constant
|
* @constant
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
*/
|
*/
|
||||||
export let tabindex = "-1";
|
export let tabindex = "-1";
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {"close" | "open"} ListBoxFieldTranslationId
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default translation ids
|
* Default translation ids
|
||||||
* @constant
|
* @constant
|
||||||
|
@ -46,6 +42,10 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {"close" | "open"} ListBoxFieldTranslationId
|
||||||
|
*/
|
||||||
|
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
const defaultTranslations = {
|
const defaultTranslations = {
|
||||||
|
|
|
@ -12,16 +12,16 @@
|
||||||
*/
|
*/
|
||||||
export const translationIds = { close: "close", open: "open" };
|
export const translationIds = { close: "close", open: "open" };
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {"close" | "open"} ListBoxMenuIconTranslationId
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the default translation ids
|
* Override the default translation ids
|
||||||
* @type {(id: ListBoxMenuIconTranslationId) => string} [translateWithId = (id) => string]
|
* @type {(id: ListBoxMenuIconTranslationId) => string} [translateWithId = (id) => string]
|
||||||
*/
|
*/
|
||||||
export let translateWithId = (id) => defaultTranslations[id];
|
export let translateWithId = (id) => defaultTranslations[id];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {"close" | "open"} ListBoxMenuIconTranslationId
|
||||||
|
*/
|
||||||
|
|
||||||
import ChevronDown16 from "carbon-icons-svelte/lib/ChevronDown16";
|
import ChevronDown16 from "carbon-icons-svelte/lib/ChevronDown16";
|
||||||
|
|
||||||
const defaultTranslations = {
|
const defaultTranslations = {
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
*/
|
*/
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {"clearAll" | "clearSelection"} ListBoxSelectionTranslationId
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default translation ids
|
* Default translation ids
|
||||||
* @constant
|
* @constant
|
||||||
|
@ -37,6 +33,10 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {"clearAll" | "clearSelection"} ListBoxSelectionTranslationId
|
||||||
|
*/
|
||||||
|
|
||||||
import { createEventDispatcher, getContext } from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import Close16 from "carbon-icons-svelte/lib/Close16";
|
import Close16 from "carbon-icons-svelte/lib/Close16";
|
||||||
|
|
||||||
|
|
|
@ -95,10 +95,6 @@
|
||||||
*/
|
*/
|
||||||
export let hideLabel = false;
|
export let hideLabel = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {"increment" | "decrement"} NumberInputTranslationId
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the default translation ids
|
* Override the default translation ids
|
||||||
* @type {(id: NumberInputTranslationId) => string} [translateWithId = (id: NumberInputTranslationId) => string]
|
* @type {(id: NumberInputTranslationId) => string} [translateWithId = (id: NumberInputTranslationId) => string]
|
||||||
|
@ -133,6 +129,10 @@
|
||||||
*/
|
*/
|
||||||
export let ref = null;
|
export let ref = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {"increment" | "decrement"} NumberInputTranslationId
|
||||||
|
*/
|
||||||
|
|
||||||
import { createEventDispatcher, afterUpdate } from "svelte";
|
import { createEventDispatcher, afterUpdate } from "svelte";
|
||||||
import CaretDownGlyph from "carbon-icons-svelte/lib/CaretDownGlyph";
|
import CaretDownGlyph from "carbon-icons-svelte/lib/CaretDownGlyph";
|
||||||
import CaretUpGlyph from "carbon-icons-svelte/lib/CaretUpGlyph";
|
import CaretUpGlyph from "carbon-icons-svelte/lib/CaretUpGlyph";
|
||||||
|
|
331
types/index.d.ts
vendored
331
types/index.d.ts
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue