Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
sveld
generates TypeScript definitions for Svelte components by statically analyzing their props, events, slots and more. Prop types and signatures can be defined using JSDoc notation. This documentation generator can also emit component documentation in Markdown and JSON output formats.
The purpose of this project is to make third party Svelte component libraries compatible with the Svelte Language Server and TypeScript with minimal effort required by the author. For example, TypeScript definitions may be used during development via intelligent code completion in Integrated Development Environments (IDE) like VSCode.
Carbon Components Svelte uses this library to auto-generate component types and API metadata:
Please note that the generated TypeScript definitions require Svelte version 3.31 or greater.
Given a Svelte component, sveld
can infer basic prop types to generate TypeScript definitions compatible with the Svelte Language Server:
Button.svelte
<script>
export let type = "button";
export let primary = false;
</script>
<button {...$$restProps} {type} class:primary on:click>
<slot>Click me</slot>
</button>
The generated definition extends the official SvelteComponentTyped
interface exported from Svelte.
Button.svelte.d.ts
/// <reference types="svelte" />
import type { SvelteComponentTyped } from "svelte";
export interface ButtonProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap["button"]> {
/**
* @default "button"
*/
type?: string;
/**
* @default false
*/
primary?: boolean;
}
export default class Button extends SvelteComponentTyped<
ButtonProps,
{ click: WindowEventMap["click"] },
{ default: {} }
> {}
Sometimes, inferring prop types is insufficient.
Prop/event/slot types and signatures can be augmented using JSDoc notations.
/** @type {"button" | "submit" | "reset"} */
export let type = "button";
/**
* Set to `true` to use the primary variant
*/
export let primary = false;
The accompanying JSDoc annotations would generate the following:
/// <reference types="svelte" />
import { SvelteComponentTyped } from "svelte";
export interface ButtonProps extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap["button"]> {
/**
* @default "button"
*/
type?: "button" | "submit" | "reset";
/**
* Set to `true` to use the primary variant
* @default false
*/
primary?: boolean;
}
export default class Button extends SvelteComponentTyped<
ButtonProps,
{ click: WindowEventMap["click"] },
{ default: {} }
> {}
sveld
uses the Svelte compiler to statically analyze Svelte components exported from a library to generate documentation useful to the end user.
Extracted metadata include:
$$restProps
This library adopts a progressively enhanced approach. Any property type that cannot be inferred (e.g., "hello" is a string) falls back to "any" to minimize incorrectly typed properties or signatures. To mitigate this, the library author can add JSDoc annotations to specify types that cannot be reliably inferred. This represents a progressively enhanced approach because JSDocs are comments that can be ignored by the compiler.
The generated TypeScript definitions for a component extends the SvelteComponentTyped
interface available in svelte version 3.31.
Install sveld
as a development dependency.
yarn add -D sveld
# OR
npm i -D sveld
# OR
pnpm i -D sveld
Import and add sveld
as a plugin to your rollup.config.js
.
// rollup.config.js
import svelte from "rollup-plugin-svelte";
import resolve from "@rollup/plugin-node-resolve";
import sveld from "sveld";
export default {
input: "src/index.js",
output: {
format: "es",
file: "lib/index.mjs",
},
plugins: [svelte(), resolve(), sveld()],
};
When building the library, TypeScript definitions are emitted to the types
folder by default.
Customize the output folder using the typesOptions.outDir
option.
The following example emits the output to the dist
folder:
sveld({
+ typesOptions: {
+ outDir: 'dist'
+ }
})
The integration folder contains example set-ups:
export { default } ...
syntaxcarbon-components-svelte
exampleThe CLI wraps the Rollup plugin and uses the "svelte"
field defined in your package.json
as the entry point.
npx sveld
Append --json
or --markdown
flags to generate documentation in JSON/Markdown formats, respectively.
npx sveld --json --markdown
You can also use sveld
programmatically in Node.js.
If no input
is specified, sveld
will infer the entry point based on the package.json#svelte
field.
const { sveld } = require("sveld");
const pkg = require("./package.json");
sveld({
input: "./src/index.js",
glob: true,
markdown: true,
markdownOptions: {
onAppend: (type, document, components) => {
if (type === "h1")
document.append("quote", `${components.size} components exported from ${pkg.name}@${pkg.version}.`);
},
},
json: true,
jsonOptions: {
outFile: "docs/src/COMPONENT_API.json",
},
});
jsonOptions.outDir
If json
is true
, a COMPONENT_API.json
file will be generated at the root of your project. This file contains documentation for all components.
Use the jsonOptions.outDir
option to specify the folder for individual JSON files to be emitted.
sveld({
json: true,
jsonOptions: {
// an individual JSON file will be generated for each component API
// e.g. "docs/Button.api.json"
outDir: "docs",
},
});
TypeScript definitions are outputted to the types
folder by default. Don't forget to include the folder in your package.json
when publishing the package to NPM.
{
"svelte": "./src/index.js",
"main": "./lib/index.mjs",
+ "types": "./types/index.d.ts",
"files": [
"src",
"lib",
+ "types",
]
}
By default, only TypeScript definitions are generated.
To generate documentation in Markdown and JSON formats, set markdown
and json
to true
.
sveld({
+ markdown: true,
+ json: true,
})
@type
Without a @type
annotation, sveld
will infer the primitive type for a prop:
export let kind = "primary";
// inferred type: "string"
Use the @type
tag to explicitly document the type. In the following example, the kind
property has an enumerated (enum) type.
Signature:
/**
* Optional description
* @type {Type}
*/
Example:
/**
* Specify the kind of button
* @type {"primary" | "secondary" | "tertiary"}
*/
export let kind = "primary";
/**
* Specify the Carbon icon to render
* @type {typeof import("carbon-icons-svelte").CarbonIcon}
*/
export let renderIcon = Close20;
@typedef
The @typedef
tag can be used to define a common type that is used multiple times within a component. All typedefs defined in a component will be exported from the generated TypeScript definition file.
Signature:
/**
* @typedef {Type} TypeName
*/
Example:
/**
* @typedef {string} AuthorName
* @typedef {{ name?: AuthorName; dob?: string; }} Author
*/
/** @type {Author} */
export let author = {};
/** @type {Author[]} */
export let authors = [];
@slot
Use the @slot
tag for typing component slots. Note that @slot
is a non-standard JSDoc tag.
Signature:
/**
* @slot {Type} [slot name]
*/
Example:
<script>
/**
* @slot {{ prop: number; doubled: number; }}
* @slot {{ props: { class?: string; } }} description
*/
export let prop = 0;
</script>
<h1>
<slot {prop} doubled={prop * 2} />
</h1>
<p>
<slot name="description" props={{ class: $$props.class }} />
</p>
@event
Use the @event
tag for typing dispatched events. An event name must be specified.
Signature:
/**
* @event {EventDetail} eventname
*/
Example:
/**
* @event {{ key: string }} button:key
*/
export let key = "";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
$: dispatch("button:key", { key });
@restProps
sveld
can pick up inline HTML elements that $$restProps
is forwarded to. However, it cannot infer the underlying element for instantiated components.
You can use the @restProps
tag to specify the element tags that $$restProps
is forwarded to.
Signature:
/**
* Single element
* @restProps {tagname}
*
* Multiple elements
* @restProps {tagname-1 | tagname-2 | tagname-3}
*/
Example:
<script>
/** @restProps {h1 | button} */
export let edit = false;
import Button from "../";
</script>
{#if edit}
<Button {...$$restProps} />
{:else}
<h1 {...$$restProps}><slot /></h1>
{/if}
@extends
In some cases, a component may be based on another component. The @extends
tag can be used to extend generated component props.
Signature:
/**
* @extends {<relative path to component>} ComponentProps
*/
Example:
/** @extends {"./Button.svelte"} ButtonProps */
export const secondary = true;
import Button from "./Button.svelte";
@component
commentsThe Svelte Language Server supports component-level comments through the following syntax: <!-- @component [comment] -->
.
sveld
will copy these over to the exported default component in the TypeScript definition.
Example:
<!-- @component
@example
<Button>
Text
</Button>
-->
<button>
<slot />
</button>
Output:
/**
* @example
* <Button>
* Text
* </Button>
*/
export default class Button extends SvelteComponentTyped<ButtonProps, {}, { default: {} }> {}
Refer to the contributing guidelines.
0.17.1 - 2022-06-02
FAQs
Generate TypeScript definitions for your Svelte components.
The npm package sveld receives a total of 3,895 weekly downloads. As such, sveld popularity was classified as popular.
We found that sveld demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.