版博士V2.0程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

181 lines
8.0 KiB

  1. import { PipelineStage, Pipeline, RulesUse } from 'vite-plugin-md';
  2. export { Frontmatter, HeadProps, LinkProperty, MetaProperty, Pipeline, PipelineStage, RouteConfig } from 'vite-plugin-md';
  3. import { TaskEither } from 'fp-ts/lib/TaskEither';
  4. /**
  5. * Builder options are expected to be a key/value dictionary but must
  6. * be allowed to be an empty object
  7. */
  8. interface BuilderOptions {
  9. [key: string]: any;
  10. }
  11. /**
  12. * The Builder's event listener/handler
  13. *
  14. * **Note:** remember that handlers are meant to be async
  15. */
  16. type BuilderHandler<O extends BuilderOptions, S extends PipelineStage> = (payload: Pipeline<S>, options: O) => Promise<Pipeline<S>>;
  17. /**
  18. * **BuilderRegistration**
  19. *
  20. * Represents a Builder API's configured _options_ which includes
  21. * the stage in the lifecycle that this builder will be given it's
  22. * execution time.
  23. */
  24. interface BuilderRegistration<O extends BuilderOptions, S extends PipelineStage> {
  25. name: Readonly<string>;
  26. description?: Readonly<string>;
  27. /** The lifecycle event/hook which this builder will respond to */
  28. lifecycle: S;
  29. /**
  30. * The builder's handler function which receives the _payload_ for the
  31. * event lifecycle hook configured and then is allowed to mutate these
  32. * properties and pass back a similarly structured object to continue
  33. * on in that pipeline stage.
  34. */
  35. handler: BuilderHandler<O, S>;
  36. /**
  37. * The options _specific_ to the builder
  38. */
  39. options: Partial<O>;
  40. /**
  41. * This isn't strictly required, but it is nice to express which rules you have used
  42. * modified, or added from the MarkdownIt parser.
  43. *
  44. * Note: builders should try to avoid mutating core rules; if they need a modification
  45. * for their purposes consider _monkey patching_ the rule so that downstream rules
  46. * have a better understanding of current rule state.
  47. */
  48. parserRules?: RulesUse[];
  49. /**
  50. * If this plugin needs to modify the configuration in some way at initialization
  51. * it can add a function here to do that. In most cases, the builder can simply
  52. * wait for their event hook to be called (at which point they will get the configuration
  53. * passed to them).
  54. */
  55. initializer?: BuilderHandler<O, "initialize">;
  56. }
  57. type OptionsFor<T extends ConfiguredBuilder<string, {}, PipelineStage, string>> = T extends BuilderApi<string, infer O, any> ? O : never;
  58. /**
  59. * **BuilderDependency**
  60. *
  61. */
  62. type BuilderDependency<T extends Partial<{
  63. builders: readonly ConfiguredBuilder<string, {}, PipelineStage, string>[];
  64. }> = Partial<{
  65. builders: [];
  66. }>> = [builder: ConfiguredBuilder<string, BuilderOptions, PipelineStage, string>, options: T];
  67. type BuilderDependencyApi<B extends readonly ConfiguredBuilder<string, {}, PipelineStage, string>[], E extends string = never> = Omit<{
  68. /**
  69. * Allows you to state a preferred option configuration for the Builder
  70. * you are dependant on. This should be seen as a suggestion more than
  71. * a guarantee because if the end user is _also_ using this configuration,
  72. * their preferences will always be honored first.
  73. *
  74. * Secondarily, if _other_ Builders depend on the same Builder as you then
  75. * there will be
  76. */
  77. withConfig: <MB extends ConfiguredBuilder<string, {}, PipelineStage, string>>(options: MB) => BuilderDependencyApi<[...B, MB], E | "withConfig">;
  78. /**
  79. * Unlike simple configuration options for a builder dependency, those builders which
  80. * expose their own "hooks/callbacks" should be seen as a _promise_ by the builder that
  81. * your passed in function _will_ be run at the appropriate time.
  82. *
  83. * **Note:** it is possible that some Builder authors will have callback functionality
  84. * in their options hash but this is discouraged and unless designed carefully (aka, making
  85. * sure that the callback is setup as a queue which receives an unknown number of callers))
  86. * you may find unexpected outcomes where you're callback is overwritten by another
  87. * dependant Builder.
  88. */
  89. usingExposedCallback: (cb: any) => BuilderDependencyApi<B, E>;
  90. }, E>;
  91. /**
  92. * Users configure a `BuilderHandler` and we wrap this up functionality
  93. * with a higher-order `BuilderTask`.
  94. *
  95. * @returns TaskEither<string, Pipeline<S>>
  96. */
  97. type BuilderTask<S extends PipelineStage> = () => (payload: Pipeline<S>) => TaskEither<string, Pipeline<S>>;
  98. /**
  99. * Properties which can be defined during createBuilder utility
  100. */
  101. interface BuilderMeta<D extends string = "", R extends RulesUse[] = []> {
  102. description?: D;
  103. parserRules?: R;
  104. initializer?: BuilderHandler<BuilderOptions, "initialize">;
  105. }
  106. interface BuilderApiMeta<N extends string, S extends PipelineStage, D extends string> {
  107. kind: "builder";
  108. /** About the Builder API */
  109. about: {
  110. name: Readonly<N>;
  111. description: Readonly<D>;
  112. stage: Readonly<S>;
  113. };
  114. }
  115. type BuilderNeedsUserOptions<O extends {}, S extends PipelineStage> = (options?: Partial<O>) => BuilderRegistration<O, S>;
  116. type BuilderConfig = Record<PipelineStage, BuilderRegistration<BuilderOptions, PipelineStage>[] | []>;
  117. /**
  118. * **ConfiguredBuilder**
  119. *
  120. * A builder-api which has been configured with the user's options and is now ready
  121. * to be used as a handler.
  122. */
  123. type ConfiguredBuilder<TName extends string, TOptions extends {}, TStage extends PipelineStage, TDescription extends string> = (() => BuilderRegistration<TOptions, TStage>) & BuilderApiMeta<TName, TStage, TDescription>;
  124. type InlineBuilder = <N extends string, L extends PipelineStage>(name: N, lifecycle: L) => (payload: Pipeline<L>) => Pipeline<L>;
  125. /**
  126. * **BuilderApi**
  127. *
  128. * The `BuilderApi` is a function which receives a user's options (or none at all) and
  129. * then returns a `ConfiguredBuilder`.
  130. *
  131. * ```ts
  132. * // as function
  133. * const configured = api(options);
  134. * // for meta
  135. * const stage = api.about.lifecycle;
  136. * ```
  137. */
  138. type BuilderApi<TName extends string, TOptions extends BuilderOptions, TStage extends PipelineStage, TDescription extends string = "no description"> = ((options?: Partial<TOptions>) => ConfiguredBuilder<TName, TOptions, TStage, TDescription>) & BuilderApiMeta<TName, TStage, TDescription>;
  139. interface BuilderReadyForMeta<N extends string, O extends BuilderOptions, E extends PipelineStage> {
  140. /**
  141. * Step 5:
  142. * - provide additional details describing this builder
  143. */
  144. meta<D extends string = "no description", R extends RulesUse[] = []>(m?: BuilderMeta<D, R>): BuilderApi<N, O, E, D>;
  145. }
  146. interface BuilderReadyForHandler<N extends string, O extends BuilderOptions, E extends PipelineStage> {
  147. handler(h: BuilderHandler<O, E>): BuilderReadyForMeta<N, O, E>;
  148. }
  149. interface BuilderReadyForInitializer<N extends string, O extends BuilderOptions, E extends PipelineStage> {
  150. /**
  151. * Your builder may optionally provide an _initializer_ function who's utility is
  152. * establishing context and configuration settings at the top of the build pipeline.
  153. */
  154. initializer(i?: BuilderHandler<O, "initialize">): BuilderReadyForHandler<N, O, E>;
  155. }
  156. /**
  157. * **BuilderReadyForOptions**
  158. *
  159. * The **Builder API** is now "built" from a library standpoint but need to receive
  160. * the user's options.
  161. */
  162. interface BuilderReadyForOptions<N extends string, E extends PipelineStage> {
  163. /** add a _type_ for the options your builder will provide */
  164. options<O extends BuilderOptions = {}>(): BuilderReadyForInitializer<N, O, E>;
  165. }
  166. interface CreateBuilder {
  167. <N extends string, E extends PipelineStage>(name: N, lifecycle: E): BuilderReadyForOptions<N, E>;
  168. }
  169. /**
  170. * A utility function to help you build a type-safe "builder".
  171. *
  172. * Step 1:
  173. * - provide the **name** and **lifecycle hook** you'll plug into
  174. * - provide a generic `<O>` which expresses the options this builder will accept
  175. */
  176. declare const createBuilder: CreateBuilder;
  177. export { BuilderApi, BuilderApiMeta, BuilderConfig, BuilderDependency, BuilderDependencyApi, BuilderHandler, BuilderMeta, BuilderNeedsUserOptions, BuilderOptions, BuilderReadyForHandler, BuilderReadyForInitializer, BuilderReadyForMeta, BuilderReadyForOptions, BuilderRegistration, BuilderTask, ConfiguredBuilder, CreateBuilder, InlineBuilder, OptionsFor, createBuilder };