Shared Package Overview

The @md-plugins/shared package provides utilities and types used internally by the MD-Plugins packages. It serves as a common foundation, ensuring consistency and reducing duplication across the different plugins.

TIP

QPress applications do not need to install or import @md-plugins/shared directly. Install it only when you are building a custom Markdown-It plugin or contributing to the MD-Plugins packages themselves.

Key Features

  • Common Utilities: Provides utility functions that are commonly used across multiple plugins.
  • Type Definitions: Includes TypeScript type definitions to ensure type safety and consistency.
  • Helper Functions: Offers helper functions to simplify common tasks and operations.
  • Reusable Helpers: Contains shared helpers that can be leveraged by other MD-Plugins packages.

Utilities

The shared package includes a variety of utility functions that can be used to perform common tasks. Some of the key utilities include:

  • String Manipulation: Functions for manipulating and formatting strings.
  • Array Operations: Functions for performing common array operations.
  • Object Handling: Functions for handling and manipulating objects.
  • Validation: Functions for validating data and inputs.

Type Definitions

The shared package provides TypeScript type definitions that are used across the MD-Plugins project. These type definitions help ensure type safety and consistency. Some of the key type definitions include:

  • MarkdownItEnv: Defines the structure of the environment object used by MD-Plugins plugins.
  • PluginOptions: Defines the structure of the options object passed to plugins.
/**
 * Escape html chars
 */
declare const const htmlEscape: (str: string) => string
Escape html chars
htmlEscape
: (str: stringstr: string) => string
/** * Unescape html chars */ declare const const htmlUnescape: (str: string) => string
Unescape html chars
htmlUnescape
: (str: stringstr: string) => string
interface MarkdownItEnv { MarkdownItEnv.plugins?: Record<string, unknown> | undefinedplugins?: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record
<string, unknown>
} interface MarkdownItHeader { /** * The slug of the header * * Typically the `id` attr of the header anchor */ MarkdownItHeader.id: string
The slug of the header Typically the `id` attr of the header anchor
id
: string
/** * The level of the header * * `1` to `6` for `<h1>` to `<h6>` */ MarkdownItHeader.level: number
The level of the header `1` to `6` for `<h1>` to `<h6>`
level
: number
/** * The title of the header */ MarkdownItHeader.title: string
The title of the header
title
: string
/** * Link of the header * * Typically using `#${slug}` as the anchor hash */ MarkdownItHeader.link: string
Link of the header Typically using `#${slug}` as the anchor hash
link
: string
/** * The children of the header */ MarkdownItHeader.children: MarkdownItHeader[]
The children of the header
children
: MarkdownItHeader[]
} type type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T) => TResolvePluginOptionsFn = <function (type parameter) T in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TT extends object, function (type parameter) K in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TK extends keyof any>( options: T | { [P in K]?: T | undefined; } | undefinedoptions: | function (type parameter) T in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TT | { [function (type parameter) PP in function (type parameter) K in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TK]?: function (type parameter) T in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TT } | undefined, key: K extends keyof anykey: function (type parameter) K in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TK, defaults: T extends objectdefaults: function (type parameter) T in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TT, ) => function (type parameter) T in <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T): TT interface LinkPluginOptions { LinkPluginOptions.externalTarget?: "_blank" | "_self" | undefinedexternalTarget?: '_blank' | '_self' LinkPluginOptions.externalRel?: string | undefinedexternalRel?: string } const
const linkOptions: {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
}
linkOptions
=
function resolvePluginOptions<{
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
}, "link">(options: {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
} | {
    link?: {
        externalTarget: string;
        externalRel?: undefined;
    } | {
        externalTarget: "_self";
        externalRel: string;
    } | undefined;
} | undefined, key: "link", defaults: {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
}): {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
}
resolvePluginOptions
({
link?: {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
} | undefined
link
: { externalTarget: stringexternalTarget: '_blank' } }, 'link', {
LinkPluginOptions.externalTarget?: "_blank" | "_self" | undefinedexternalTarget: '_self', LinkPluginOptions.externalRel?: string | undefinedexternalRel: 'noopener', } satisfies LinkPluginOptions) const linkTarget =
const linkOptions: {
    externalTarget: string;
    externalRel?: undefined;
} | {
    externalTarget: "_self";
    externalRel: string;
}
linkOptions
.externalTarget: stringexternalTarget
const linkTarget: string
interface ResolveTitleOptions { /** * Should allow inline HTML tags or not. * * If the result is going to be used as Vue template, it should allow inline * HTML tags so that Vue custom components would be kept. */ ResolveTitleOptions.shouldAllowHtml: boolean
Should allow inline HTML tags or not. If the result is going to be used as Vue template, it should allow inline HTML tags so that Vue custom components would be kept.
shouldAllowHtml
: boolean
/** * Should escape the text content or not. * * If the result is going to be used in HTML directly, it should be escaped * so that the text content won't be wrongly treated as HTML tags. */ ResolveTitleOptions.shouldEscapeText: boolean
Should escape the text content or not. If the result is going to be used in HTML directly, it should be escaped so that the text content won't be wrongly treated as HTML tags.
shouldEscapeText
: boolean
} /** * Resolve header title from markdown-it token * * Typically using the next token of `heading_open` token */ declare const const resolveTitleFromToken: (token: unknown, { shouldAllowHtml, shouldEscapeText }: ResolveTitleOptions) => string
Resolve header title from markdown-it token Typically using the next token of `heading_open` token
resolveTitleFromToken
: (
token: unknowntoken: unknown, { shouldAllowHtml: boolean
Should allow inline HTML tags or not. If the result is going to be used as Vue template, it should allow inline HTML tags so that Vue custom components would be kept.
shouldAllowHtml
, shouldEscapeText: boolean
Should escape the text content or not. If the result is going to be used in HTML directly, it should be escaped so that the text content won't be wrongly treated as HTML tags.
shouldEscapeText
}: ResolveTitleOptions,
) => string interface ResolveHeadersOptions extends ResolveTitleOptions { /** * Heading level that going to be resolved */ ResolveHeadersOptions.level: number[]
Heading level that going to be resolved
level
: number[]
/** * Should allow headers inside nested blocks or not * * If set to `true`, headers inside blockquote, list, etc. would also be resolved. */ ResolveHeadersOptions.shouldAllowNested: boolean
Should allow headers inside nested blocks or not If set to `true`, headers inside blockquote, list, etc. would also be resolved.
shouldAllowNested
: boolean
/** * A custom slugification function * * Would be ignored if the `id` attr of the token is set. */ ResolveHeadersOptions.slugify?: ((str: string) => string) | undefined
A custom slugification function Would be ignored if the `id` attr of the token is set.
slugify
?: (str: stringstr: string) => string
/** * A function for formatting headings */ ResolveHeadersOptions.format?: ((str: string) => string | undefined) | undefined
A function for formatting headings
format
?: (str: stringstr: string) => string | undefined
} /** * Resolve headers from markdown-it tokens */ declare const const resolveHeadersFromTokens: (tokens: unknown[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format, }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[]
Resolve headers from markdown-it tokens
resolveHeadersFromTokens
: (
tokens: unknown[]tokens: unknown[], { level: number[] | undefined
Heading level that going to be resolved
level
,
shouldAllowHtml: boolean | undefined
Should allow inline HTML tags or not. If the result is going to be used as Vue template, it should allow inline HTML tags so that Vue custom components would be kept.
shouldAllowHtml
,
shouldAllowNested: boolean | undefined
Should allow headers inside nested blocks or not If set to `true`, headers inside blockquote, list, etc. would also be resolved.
shouldAllowNested
,
shouldEscapeText: boolean | undefined
Should escape the text content or not. If the result is going to be used in HTML directly, it should be escaped so that the text content won't be wrongly treated as HTML tags.
shouldEscapeText
,
slugify: ((str: string) => string) | undefined
A custom slugification function Would be ignored if the `id` attr of the token is set.
slugify
,
format: ((str: string) => string | undefined) | undefined
A function for formatting headings
format
,
}?: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<ResolveHeadersOptions>,
) => MarkdownItHeader[] /** * Default slugification function */ declare const const slugify: (str: string) => string
Default slugification function
slugify
: (str: stringstr: string) => string
declare function function resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TresolvePluginOptions<function (type parameter) T in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TT extends object, function (type parameter) K in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TK extends keyof any>( options: T | { [key in K]?: T | undefined; } | undefinedoptions: | function (type parameter) T in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TT | { [function (type parameter) keykey in function (type parameter) K in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TK]?: function (type parameter) T in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TT } | undefined, key: K extends keyof anykey: function (type parameter) K in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TK, defaults: T extends objectdefaults: function (type parameter) T in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TT, ): function (type parameter) T in resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): TT export { type export MarkdownItEnvMarkdownItEnv, type export MarkdownItHeaderMarkdownItHeader, type export ResolveHeadersOptionsResolveHeadersOptions, type
type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T) => T
export ResolvePluginOptionsFn
ResolvePluginOptionsFn
,
type export ResolveTitleOptionsResolveTitleOptions,
const htmlEscape: (str: string) => string
export htmlEscape
Escape html chars
htmlEscape
,
const htmlUnescape: (str: string) => string
export htmlUnescape
Unescape html chars
htmlUnescape
,
const resolveHeadersFromTokens: (tokens: unknown[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format, }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[]
export resolveHeadersFromTokens
Resolve headers from markdown-it tokens
resolveHeadersFromTokens
,
function resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): T
export resolvePluginOptions
resolvePluginOptions
,
const resolveTitleFromToken: (token: unknown, { shouldAllowHtml, shouldEscapeText }: ResolveTitleOptions) => string
export resolveTitleFromToken
Resolve header title from markdown-it token Typically using the next token of `heading_open` token
resolveTitleFromToken
,
const slugify: (str: string) => string
export slugify
Default slugification function
slugify
,
}

Helper Functions

The shared package includes a variety of helper functions that simplify common tasks and operations. Some of the key helper functions include:

  • resolveTitleFromToken: Extracts the title from a Markdown token.
  • parseFrontmatter: Parses frontmatter content from a Markdown file.
  • generateSlug: Generates a slug from a given string.
  • htmlEscape: Escapes HTML characters in a string.
  • htmlUnescape: Unescapes HTML characters in a string.
  • slugify: Slugifies a string using a custom function.

Conclusion

The shared package is an essential internal part of the MD-Plugins project, providing common utilities, type definitions, and helper functions. If you are building custom plugins, you can use it to stay aligned with the same types and helpers used by the official MD-Plugins packages.

Happy coding!