UNPKG

@wc-toolkit/cem-inheritance

Version:

A tool for mapping inherited content (including class members, attributes, CSS parts, CSS variables, slots, and events) from parent web component classes in the Custom Elements Manifest

350 lines (311 loc) 9.55 kB
import { AnalyzePhaseParams, PackageLinkPhaseParams } from '@custom-elements-manifest/analyzer'; /** * A reference to an export of a module. * * All references are required to be publically accessible, so the canonical * representation of a reference is the export it's available from. * * `package` should generally refer to an npm package name. If `package` is * undefined then the reference is local to this package. If `module` is * undefined the reference is local to the containing module. * * References to global symbols like `Array`, `HTMLElement`, or `Event` should * use a `package` name of `"global:"`. */ interface Reference { name: string; package?: string; module?: string; } /** * A reference to the source of a declaration or member. */ interface SourceReference { /** * An absolute URL to the source (ie. a GitHub URL). */ href: string; } interface Type { /** * The full string representation of the type, in whatever type syntax is * used, such as JSDoc, Closure, or TypeScript. */ text: string; /** * An array of references to the types in the type string. * * These references have optional indices into the type string so that tools * can understand the references in the type string independently of the type * system and syntax. For example, a documentation viewer could display the * type `Array<FooElement | BarElement>` with cross-references to `FooElement` * and `BarElement` without understanding arrays, generics, or union types. */ references?: TypeReference[]; source?: SourceReference; } /** * A reference that is associated with a type string and optionally a range * within the string. * * Start and end must both be present or not present. If they're present, they * are indices into the associated type string. If they are missing, the entire * type string is the symbol referenced and the name should match the type * string. */ interface TypeReference extends Reference { start?: number; end?: number; } /** * The common interface of classes and mixins. */ interface ClassLike { name: string; /** * A markdown summary suitable for display in a listing. */ summary?: string; /** * A markdown description of the class. */ description?: string; /** * The superclass of this class. * * If this class is defined with mixin applications, the prototype chain * includes the mixin applications and the true superclass is computed * from them. */ superclass?: Reference; /** * Any class mixins applied in the extends clause of this class. * * If mixins are applied in the class definition, then the true superclass * of this class is the result of applying mixins in order to the superclass. * * Mixins must be listed in order of their application to the superclass or * previous mixin application. This means that the innermost mixin is listed * first. This may read backwards from the common order in JavaScript, but * matches the order of language used to describe mixin application, like * "S with A, B". * * @example * * ```javascript * class T extends B(A(S)) {} * ``` * * is described by: * ```json * { * "kind": "class", * "superclass": { * "name": "S" * }, * "mixins": [ * { * "name": "A" * }, * { * "name": "B" * }, * ] * } * ``` */ mixins?: Array<Reference>; members?: Array<ClassMember>; source?: SourceReference; /** * Whether the class or mixin is deprecated. * If the value is a string, it's the reason for the deprecation. */ deprecated?: boolean | string; } type ClassMember = ClassField | ClassMethod; /** * The common interface of variables, class fields, and function * parameters. */ interface PropertyLike { name: string; /** * A markdown summary suitable for display in a listing. */ summary?: string; /** * A markdown description of the field. */ description?: string; type?: Type; default?: string; /** * Whether the property is deprecated. * If the value is a string, it's the reason for the deprecation. */ deprecated?: boolean | string; /** * Whether the property is read-only. */ readonly?: boolean; } interface ClassField extends PropertyLike { kind: 'field'; static?: boolean; privacy?: Privacy; inheritedFrom?: Reference; source?: SourceReference; } interface ClassMethod extends FunctionLike { kind: 'method'; static?: boolean; privacy?: Privacy; inheritedFrom?: Reference; source?: SourceReference; } /** * A description of a class mixin. * * Mixins are functions which generate a new subclass of a given superclass. * This interfaces describes the class and custom element features that * are added by the mixin. As such, it extends the CustomElement interface and * ClassLike interface. * * Since mixins are functions, it also extends the FunctionLike interface. This * means a mixin is callable, and has parameters and a return type. * * The return type is often hard or impossible to accurately describe in type * systems like TypeScript. It requires generics and an `extends` operator * that TypeScript lacks. Therefore it's recommended that the return type is * left empty. The most common form of a mixin function takes a single * argument, so consumers of this interface should assume that the return type * is the single argument subclassed by this declaration. * * A mixin should not have a superclass. If a mixins composes other mixins, * they should be listed in the `mixins` field. * * See [this article]{@link https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/} * for more information on the classmixin pattern in JavaScript. * * @example * * This JavaScript mixin declaration: * ```javascript * const MyMixin = (base) => class extends base { * foo() { ... } * } * ``` * * Is described by this JSON: * ```json * { * "kind": "mixin", * "name": "MyMixin", * "parameters": [ * { * "name": "base", * } * ], * "members": [ * { * "kind": "method", * "name": "foo", * } * ] * } * ``` */ interface MixinDeclaration extends ClassLike, FunctionLike { kind: 'mixin'; } interface Parameter extends PropertyLike { /** * Whether the parameter is optional. Undefined implies non-optional. */ optional?: boolean; /** * Whether the parameter is a rest parameter. Only the last parameter may be a rest parameter. * Undefined implies single parameter. */ rest?: boolean; } interface FunctionLike { name: string; /** * A markdown summary suitable for display in a listing. */ summary?: string; /** * A markdown description. */ description?: string; /** * Whether the function is deprecated. * If the value is a string, it's the reason for the deprecation. */ deprecated?: boolean | string; parameters?: Parameter[]; return?: { type?: Type; /** * A markdown summary suitable for display in a listing. */ summary?: string; /** * A markdown description. */ description?: string; }; } type Privacy = 'public' | 'private' | 'protected'; type CemInheritanceOptions = { /** Name of the updated CEM file - default is "custom-elements.json" */ fileName?: string; /** Path to output directory */ outdir?: string; /** Class names of any components you would like to exclude from inheritance */ exclude?: string[]; /** Omit items from inheritance based on a custom CEM property */ omitByProperty?: OmittedProperties; /** Omit items from inheritance based on CEM Analyzer plugin config */ omitByConfig?: ConfigOmit; /** Skip inheritance for an aspect of your components */ ignore?: string[]; /** External CEMs that your components extend */ externalManifests?: unknown[]; /** Include external manifest declarations in your manifest */ includeExternalManifests?: boolean; /** Shows process logs */ debug?: boolean; /** Prevents plugin from executing */ skip?: boolean; /** @internal Used to indicate if this is used as a CEM a plugin */ usedByPlugin?: boolean; }; /** @deprecated This has been replaced with `CemInheritanceOptions` */ type Options = CemInheritanceOptions; type ConfigOmit = { [key: string]: OmittedApis; }; type OmittedProperties = { attributes?: string; cssParts?: string; cssProperties?: string; cssStates?: string; events?: string; methods?: string; properties?: string; slots?: string; }; type OmittedApis = Record<keyof OmittedProperties, string[]>; /** A generic extension of the CEM `MixinDeclaration` type to allow for strongly typing your custom data */ type Mixin<T = Record<string, unknown>> = MixinDeclaration & T; declare function cemInheritancePlugin(options?: CemInheritanceOptions): { name: string; analyzePhase(params: AnalyzePhaseParams): void; packageLinkPhase({ customElementsManifest }: PackageLinkPhaseParams): void; }; declare function updateCemInheritance(cem: unknown, options?: CemInheritanceOptions): void; declare function generateUpdatedCem(cem: unknown, options?: CemInheritanceOptions): unknown; export { type CemInheritanceOptions, type ConfigOmit, type Mixin, type OmittedApis, type OmittedProperties, type Options, cemInheritancePlugin, generateUpdatedCem, updateCemInheritance };