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) => stringEscape html charshtmlEscape: (str: stringstr: string) => string
/**
* Unescape html chars
*/
declare const const htmlUnescape: (str: string) => stringUnescape html charshtmlUnescape: (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 TRecord<string, unknown>
}
interface MarkdownItHeader {
/**
* The slug of the header
*
* Typically the `id` attr of the header anchor
*/
MarkdownItHeader.id: stringThe slug of the header
Typically the `id` attr of the header anchorid: string
/**
* The level of the header
*
* `1` to `6` for `<h1>` to `<h6>`
*/
MarkdownItHeader.level: numberThe level of the header
`1` to `6` for `<h1>` to `<h6>`level: number
/**
* The title of the header
*/
MarkdownItHeader.title: stringThe title of the headertitle: string
/**
* Link of the header
*
* Typically using `#${slug}` as the anchor hash
*/
MarkdownItHeader.link: stringLink of the header
Typically using `#${slug}` as the anchor hashlink: string
/**
* The children of the header
*/
MarkdownItHeader.children: MarkdownItHeader[]The children of the headerchildren: 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
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: booleanShould 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: booleanShould 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) => stringResolve header title from markdown-it token
Typically using the next token of `heading_open` tokenresolveTitleFromToken: (
token: unknowntoken: unknown,
{ shouldAllowHtml: booleanShould 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: booleanShould 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 resolvedlevel: number[]
/**
* Should allow headers inside nested blocks or not
*
* If set to `true`, headers inside blockquote, list, etc. would also be resolved.
*/
ResolveHeadersOptions.shouldAllowNested: booleanShould 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) | undefinedA 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) | undefinedA function for formatting headingsformat?: (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 tokensresolveHeadersFromTokens: (
tokens: unknown[]tokens: unknown[],
{
level: number[] | undefinedHeading level that going to be resolvedlevel,
shouldAllowHtml: boolean | undefinedShould 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 | undefinedShould allow headers inside nested blocks or not
If set to `true`, headers inside blockquote, list, etc. would also be resolved.shouldAllowNested,
shouldEscapeText: boolean | undefinedShould 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) | undefinedA custom slugification function
Would be ignored if the `id` attr of the token is set.slugify,
format: ((str: string) => string | undefined) | undefinedA function for formatting headingsformat,
}?: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }Make all properties in T optionalPartial<ResolveHeadersOptions>,
) => MarkdownItHeader[]
/**
* Default slugification function
*/
declare const const slugify: (str: string) => stringDefault slugification functionslugify: (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 charshtmlEscape,
const htmlUnescape: (str: string) => string
export htmlUnescape
Unescape html charshtmlUnescape,
const resolveHeadersFromTokens: (tokens: unknown[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format, }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[]
export resolveHeadersFromTokens
Resolve headers from markdown-it tokensresolveHeadersFromTokens,
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` tokenresolveTitleFromToken,
const slugify: (str: string) => string
export slugify
Default slugification functionslugify,
}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!