mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
refactor(types): separate script to generate types
This commit is contained in:
parent
010fe986e9
commit
c8b0b008c7
4 changed files with 1277 additions and 1248 deletions
78
scripts/rollup/generate-types.js
Normal file
78
scripts/rollup/generate-types.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* Use library component metadata to generate TypeScript definitions.
|
||||||
|
* @param {Map<string, { component: { exported_props: Map<string, any>; slots: Map<string, any>; } typedefs: {name: string; type: string;}[] }>} components
|
||||||
|
* @param {{name: string; version: string; homepage: string;}} pkg
|
||||||
|
*/
|
||||||
|
export function generateTypes(components, pkg) {
|
||||||
|
let code = `
|
||||||
|
// Type definitions for ${pkg.name} ${pkg.version}
|
||||||
|
// Project: ${pkg.homepage}
|
||||||
|
|
||||||
|
class SvelteComponent {
|
||||||
|
$$prop_def: {};
|
||||||
|
|
||||||
|
$$slot_def: {};
|
||||||
|
|
||||||
|
// stub all \`on:{eventname}\` directives
|
||||||
|
$on(eventname: string, handler: (e: Event) => any): () => void;
|
||||||
|
}\n\n`;
|
||||||
|
|
||||||
|
components.forEach((component, moduleName) => {
|
||||||
|
let $$prop_def = "";
|
||||||
|
let $$slot_def = "";
|
||||||
|
|
||||||
|
component.typedefs.forEach(({ name, type }) => {
|
||||||
|
const typedef = type.startsWith("{")
|
||||||
|
? `interface ${name} ${type}`
|
||||||
|
: `type ${name} = ${type};`;
|
||||||
|
code += typedef + "\n\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
component.component.exported_props.forEach((prop, name) => {
|
||||||
|
$$prop_def += "/**\n";
|
||||||
|
|
||||||
|
prop.description.split("\n").forEach((line) => {
|
||||||
|
$$prop_def += "* " + line + "\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prop.value !== undefined) {
|
||||||
|
$$prop_def += "* @default " + prop.value + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$$prop_def += "*/\n";
|
||||||
|
|
||||||
|
let value = "undefined";
|
||||||
|
|
||||||
|
if (prop.type) {
|
||||||
|
value = prop.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
$$prop_def += name + "?: " + value + ";" + "\n\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
component.component.slots.forEach((slot, slot_name) => {
|
||||||
|
let value = "";
|
||||||
|
|
||||||
|
slot.attributes.forEach((attribute) => {
|
||||||
|
if (attribute.name !== "name") {
|
||||||
|
value += attribute.name + ": any;";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (slot.default) {
|
||||||
|
$$slot_def += "default: {" + value + "};" + "\n";
|
||||||
|
} else {
|
||||||
|
$$slot_def += JSON.stringify(slot_name) + ": {" + value + "};" + "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
code += `
|
||||||
|
export class ${moduleName} extends SvelteComponent {
|
||||||
|
${!!$$prop_def ? "$$prop_def: {" + $$prop_def + "}\n" : ""}
|
||||||
|
|
||||||
|
${!!$$slot_def ? "$$slot_def: {" + $$slot_def + "}\n" : ""}
|
||||||
|
}\n\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { code };
|
||||||
|
}
|
|
@ -1,24 +1,14 @@
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import prettier from "prettier";
|
|
||||||
import pkg from "../../package.json";
|
import pkg from "../../package.json";
|
||||||
|
import { format } from "prettier";
|
||||||
import { parseComponent } from "./parse-component";
|
import { parseComponent } from "./parse-component";
|
||||||
|
import { generateTypes } from "./generate-types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollup plugin to generate library TypeScript definitions and documentation.
|
||||||
|
*/
|
||||||
function pluginGenerateDocs() {
|
function pluginGenerateDocs() {
|
||||||
let definitions = `
|
|
||||||
// Type definitions for ${pkg.name} ${pkg.version}
|
|
||||||
// Project: ${pkg.homepage}
|
|
||||||
|
|
||||||
class SvelteComponent {
|
|
||||||
$$prop_def: {};
|
|
||||||
|
|
||||||
$$slot_def: {};
|
|
||||||
|
|
||||||
// stub all 'on:{event}' directives
|
|
||||||
$on(eventname: string, handler: (e: Event) => any): () => void;
|
|
||||||
}\n\n`;
|
|
||||||
|
|
||||||
const shared_types = new Set();
|
|
||||||
const groups = new Map();
|
const groups = new Map();
|
||||||
const components = new Map();
|
const components = new Map();
|
||||||
|
|
||||||
|
@ -33,6 +23,8 @@ class SvelteComponent {
|
||||||
components.set(exportee, {});
|
components.set(exportee, {});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const shared_types = new Set();
|
||||||
|
|
||||||
Object.keys(chunkOrAsset.modules)
|
Object.keys(chunkOrAsset.modules)
|
||||||
.sort()
|
.sort()
|
||||||
.forEach(async (filename) => {
|
.forEach(async (filename) => {
|
||||||
|
@ -48,84 +40,28 @@ class SvelteComponent {
|
||||||
groups.set(group, [moduleName]);
|
groups.set(group, [moduleName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const typedefs = [];
|
||||||
const source = fs.readFileSync(filename, "utf-8");
|
const source = fs.readFileSync(filename, "utf-8");
|
||||||
const component = parseComponent(source, {
|
const component = parseComponent(source, {
|
||||||
component: moduleName,
|
component: moduleName,
|
||||||
onTypeDef: (tag) => {
|
onTypeDef: (tag) => {
|
||||||
if (shared_types.has(tag.name)) return;
|
if (shared_types.has(tag.name)) return;
|
||||||
|
|
||||||
shared_types.add(tag.name);
|
shared_types.add(tag.name);
|
||||||
|
typedefs.push(tag);
|
||||||
const ts_type = tag.type.startsWith("{")
|
|
||||||
? `interface ${tag.name} ${tag.type}`
|
|
||||||
: `type ${tag.name} = ${tag.type};`;
|
|
||||||
|
|
||||||
definitions += ts_type + "\n\n";
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let $$prop_def = "";
|
components.set(moduleName, { typedefs, component });
|
||||||
|
|
||||||
component.exported_props.forEach((prop, name) => {
|
|
||||||
$$prop_def += "/**\n";
|
|
||||||
|
|
||||||
prop.description.split("\n").forEach((line) => {
|
|
||||||
$$prop_def += "* " + line + "\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
if (prop.value !== undefined) {
|
|
||||||
$$prop_def += "* @default " + prop.value + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$$prop_def += "*/\n";
|
|
||||||
|
|
||||||
let value = "undefined";
|
|
||||||
|
|
||||||
if (prop.type) {
|
|
||||||
value = prop.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
$$prop_def += name + "?: " + value + ";" + "\n\n";
|
|
||||||
});
|
|
||||||
|
|
||||||
let $$slot_def = "";
|
|
||||||
|
|
||||||
component.slots.forEach((slot, slot_name) => {
|
|
||||||
let value = "";
|
|
||||||
|
|
||||||
slot.attributes.forEach((attribute) => {
|
|
||||||
if (attribute.name !== "name") {
|
|
||||||
value += attribute.name + ": any;";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (slot.default) {
|
|
||||||
$$slot_def += "default: {" + value + "};" + "\n";
|
|
||||||
} else {
|
|
||||||
$$slot_def +=
|
|
||||||
JSON.stringify(slot_name) + ": {" + value + "};" + "\n";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
definitions += `
|
|
||||||
export class ${moduleName} extends SvelteComponent {
|
|
||||||
${!!$$prop_def ? "$$prop_def: {" + $$prop_def + "}\n" : ""}
|
|
||||||
|
|
||||||
${!!$$slot_def ? "$$slot_def: {" + $$slot_def + "}\n" : ""}
|
|
||||||
}\n\n`;
|
|
||||||
|
|
||||||
components.set(moduleName, component);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
writeBundle() {
|
writeBundle() {
|
||||||
const formatted_definitions = prettier.format(definitions, {
|
const { code: types } = generateTypes(components, pkg);
|
||||||
parser: "typescript",
|
const definitions = format(types, { parser: "typescript" });
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(pkg.types, formatted_definitions);
|
fs.writeFileSync(pkg.types, definitions);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,19 +36,34 @@
|
||||||
* @typedef {ColumnSize | ColumnSizeDescriptor} ColumnBreakpoint
|
* @typedef {ColumnSize | ColumnSizeDescriptor} ColumnBreakpoint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {ColumnBreakpoint} [sm] */
|
/**
|
||||||
|
* Set the small breakpoint
|
||||||
|
* @type {ColumnBreakpoint} [sm]
|
||||||
|
*/
|
||||||
export let sm = undefined;
|
export let sm = undefined;
|
||||||
|
|
||||||
/** @type {ColumnBreakpoint} [md] */
|
/**
|
||||||
|
* Set the medium breakpoint
|
||||||
|
* @type {ColumnBreakpoint} [md]
|
||||||
|
*/
|
||||||
export let md = undefined;
|
export let md = undefined;
|
||||||
|
|
||||||
/** @type {ColumnBreakpoint} [lg] */
|
/**
|
||||||
|
* Set the large breakpoint
|
||||||
|
* @type {ColumnBreakpoint} [lg]
|
||||||
|
*/
|
||||||
export let lg = undefined;
|
export let lg = undefined;
|
||||||
|
|
||||||
/** @type {ColumnBreakpoint} [xlg] */
|
/**
|
||||||
|
* Set the extra large breakpoint
|
||||||
|
* @type {ColumnBreakpoint} [xlg]
|
||||||
|
*/
|
||||||
export let xlg = undefined;
|
export let xlg = undefined;
|
||||||
|
|
||||||
/** @type {ColumnBreakpoint} [max] */
|
/**
|
||||||
|
* Set the maximum breakpoint
|
||||||
|
* @type {ColumnBreakpoint} [max]
|
||||||
|
*/
|
||||||
export let max = undefined;
|
export let max = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
2332
types/index.d.ts
vendored
2332
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