@md-plugins/shared 0.1.0-rc.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,24 @@
1
1
  # @md-plugins/shared
2
2
 
3
- The `@md-plugins/shared` package provides common utilities, types, and helpers used across various Markdown-It plugins in the `@md-plugins` ecosystem. It serves as a foundational package to ensure consistency and reduce code duplication across the plugins.
3
+ [![npm version](https://img.shields.io/npm/v/@md-plugins/shared?label=%40md-plugins%2Fshared)](https://www.npmjs.com/package/@md-plugins/shared)
4
+ [![npm downloads](https://img.shields.io/npm/dt/@md-plugins/shared)](https://www.npmjs.com/package/@md-plugins/shared)
5
+ [![npm monthly downloads](https://img.shields.io/npm/dm/@md-plugins/shared)](https://www.npmjs.com/package/@md-plugins/shared)
6
+ [![license](https://img.shields.io/npm/l/@md-plugins/shared)](https://www.npmjs.com/package/@md-plugins/shared)
4
7
 
5
- QPress applications and regular `@md-plugins/vite-md-plugin` users do not need to install this package directly. Use it only when building a custom Markdown-It plugin or contributing to the MD-Plugins packages.
8
+ <span class="badge-github-sponsors"><a href="https://github.com/sponsors/hawkeye64" title="Sponsor this project on GitHub"><img src="https://img.shields.io/badge/github-sponsors-ea4aaa.svg?logo=githubsponsors&logoColor=white" alt="GitHub Sponsors button" /></a></span>
9
+ <span class="badge-paypal"><a href="https://paypal.me/hawkeye64" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span>
10
+
11
+ [![Discord](https://img.shields.io/badge/discord-join%20server-738ADB?style=for-the-badge&logo=discord&logoColor=738ADB)](https://chat.quasar.dev)
12
+ [![X](https://img.shields.io/badge/follow-@jgalbraith64-1DA1F2?style=for-the-badge&logo=x&logoColor=1DA1F2)](https://twitter.com/jgalbraith64)
13
+
14
+ The `@md-plugins/shared` package provides common utilities, types, and helpers used across the Markdown-it plugins in the md-plugins ecosystem. It keeps Q-Press and direct plugin usage on the same environment shape for frontmatter, table of contents, extracted titles, and page-level imports.
15
+
16
+ Q-Press applications and regular `@md-plugins/vite-md-plugin` users do not need to install this package directly. Use it only when building a custom Markdown-it plugin or contributing to the md-plugins packages.
6
17
 
7
18
  ## Features
8
19
 
9
20
  - Shared TypeScript types for plugin environments.
10
- - Common utility functions for Markdown-It processing.
21
+ - Common utility functions for Markdown-it processing.
11
22
  - Centralized definitions for easier maintenance and reusability.
12
23
  - Lightweight and dependency-free.
13
24
 
package/dist/index.d.mts CHANGED
@@ -1,65 +1,59 @@
1
- import Token from 'markdown-it/lib/token.mjs';
2
-
1
+ import Token from "markdown-it/lib/token.mjs";
3
2
  /**
4
3
  * Escapes HTML-sensitive characters so text can be safely injected into markup.
5
4
  */
6
5
  declare const htmlEscape: (str: string) => string;
7
-
8
6
  /**
9
7
  * Decodes the HTML entities emitted by {@link htmlEscape} and common numeric variants.
10
8
  */
11
9
  declare const htmlUnescape: (str: string) => string;
12
-
13
10
  interface MarkdownItEnv {
14
- plugins?: Record<string, unknown>;
11
+ plugins?: Record<string, unknown>;
15
12
  }
16
13
  interface MarkdownItHeader {
17
- /**
18
- * The slug of the header
19
- *
20
- * Typically the `id` attr of the header anchor
21
- */
22
- id: string;
23
- /**
24
- * The level of the header
25
- *
26
- * `1` to `6` for `<h1>` to `<h6>`
27
- */
28
- level: number;
29
- /**
30
- * The title of the header
31
- */
32
- title: string;
33
- /**
34
- * Link of the header
35
- *
36
- * Typically using `#${slug}` as the anchor hash
37
- */
38
- link: string;
39
- /**
40
- * The children of the header
41
- */
42
- children: MarkdownItHeader[];
14
+ /**
15
+ * The slug of the header
16
+ *
17
+ * Typically the `id` attr of the header anchor
18
+ */
19
+ id: string;
20
+ /**
21
+ * The level of the header
22
+ *
23
+ * `1` to `6` for `<h1>` to `<h6>`
24
+ */
25
+ level: number;
26
+ /**
27
+ * The title of the header
28
+ */
29
+ title: string;
30
+ /**
31
+ * Link of the header
32
+ *
33
+ * Typically using `#${slug}` as the anchor hash
34
+ */
35
+ link: string;
36
+ /**
37
+ * The children of the header
38
+ */
39
+ children: MarkdownItHeader[];
43
40
  }
44
- type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | {
45
- [P in K]?: T;
46
- } | undefined, key: K, defaults: T) => T;
47
-
41
+ type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T) => T;
48
42
  interface ResolveTitleOptions {
49
- /**
50
- * Should allow inline HTML tags or not.
51
- *
52
- * If the result is going to be used as Vue template, it should allow inline
53
- * HTML tags so that Vue custom components would be kept.
54
- */
55
- shouldAllowHtml: boolean;
56
- /**
57
- * Should escape the text content or not.
58
- *
59
- * If the result is going to be used in HTML directly, it should be escaped
60
- * so that the text content won't be wrongly treated as HTML tags.
61
- */
62
- shouldEscapeText: boolean;
43
+ /**
44
+ * Should allow inline HTML tags or not.
45
+ *
46
+ * If the result is going to be used as Vue template, it should allow inline
47
+ * HTML tags so that Vue custom components would be kept.
48
+ */
49
+ shouldAllowHtml: boolean;
50
+ /**
51
+ * Should escape the text content or not.
52
+ *
53
+ * If the result is going to be used in HTML directly, it should be escaped
54
+ * so that the text content won't be wrongly treated as HTML tags.
55
+ */
56
+ shouldEscapeText: boolean;
63
57
  }
64
58
  /**
65
59
  * Extracts plain heading text from a markdown-it inline token.
@@ -69,28 +63,27 @@ interface ResolveTitleOptions {
69
63
  * are ignored so the title remains human-readable.
70
64
  */
71
65
  declare const resolveTitleFromToken: (token: Token, { shouldAllowHtml, shouldEscapeText }: ResolveTitleOptions) => string;
72
-
73
66
  interface ResolveHeadersOptions extends ResolveTitleOptions {
74
- /**
75
- * Heading level that going to be resolved
76
- */
77
- level: number[];
78
- /**
79
- * Should allow headers inside nested blocks or not
80
- *
81
- * If set to `true`, headers inside blockquote, list, etc. would also be resolved.
82
- */
83
- shouldAllowNested: boolean;
84
- /**
85
- * A custom slugification function
86
- *
87
- * Would be ignored if the `id` attr of the token is set.
88
- */
89
- slugify?: (str: string) => string;
90
- /**
91
- * A function for formatting headings
92
- */
93
- format?: (str: string) => string | undefined;
67
+ /**
68
+ * Heading level that going to be resolved
69
+ */
70
+ level: number[];
71
+ /**
72
+ * Should allow headers inside nested blocks or not
73
+ *
74
+ * If set to `true`, headers inside blockquote, list, etc. would also be resolved.
75
+ */
76
+ shouldAllowNested: boolean;
77
+ /**
78
+ * A custom slugification function
79
+ *
80
+ * Would be ignored if the `id` attr of the token is set.
81
+ */
82
+ slugify?: (str: string) => string;
83
+ /**
84
+ * A function for formatting headings
85
+ */
86
+ format?: (str: string) => string | undefined;
94
87
  }
95
88
  /**
96
89
  * Builds a nested heading tree from markdown-it heading tokens.
@@ -98,16 +91,14 @@ interface ResolveHeadersOptions extends ResolveTitleOptions {
98
91
  * Existing heading `id` attributes are preserved. When a heading has no `id`,
99
92
  * the configured `slugify` function creates one from the resolved heading text.
100
93
  */
101
- declare const resolveHeadersFromTokens: (tokens: Token[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format, }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[];
102
-
94
+ declare const resolveHeadersFromTokens: (tokens: Token[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[];
103
95
  /**
104
96
  * Converts arbitrary heading text into a stable URL-friendly slug.
105
97
  *
106
98
  * The result is lowercase, accent-free, hyphen-separated, and safe to use as a
107
99
  * generated Markdown heading id.
108
100
  */
109
- declare const slugify: (str: string) => string;
110
-
101
+ declare const slugify$1: (str: string) => string;
111
102
  /**
112
103
  * Resolves plugin options from either a direct options object or a nested
113
104
  * package-level options bag.
@@ -116,9 +107,5 @@ declare const slugify: (str: string) => string;
116
107
  * or through a shared md-plugins config object keyed by plugin name. This helper
117
108
  * supports both shapes while applying default values.
118
109
  */
119
- declare function resolvePluginOptions<T extends object, K extends keyof any>(options: T | {
120
- [key in K]?: T;
121
- } | undefined, key: K, defaults: T): T;
122
-
123
- export { htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify };
124
- export type { MarkdownItEnv, MarkdownItHeader, ResolveHeadersOptions, ResolvePluginOptionsFn, ResolveTitleOptions };
110
+ declare function resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): T;
111
+ export { type MarkdownItEnv, type MarkdownItHeader, ResolveHeadersOptions, type ResolvePluginOptionsFn, ResolveTitleOptions, htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify$1 as slugify };
package/dist/index.d.ts CHANGED
@@ -1,65 +1,59 @@
1
- import Token from 'markdown-it/lib/token.mjs';
2
-
1
+ import Token from "markdown-it/lib/token.mjs";
3
2
  /**
4
3
  * Escapes HTML-sensitive characters so text can be safely injected into markup.
5
4
  */
6
5
  declare const htmlEscape: (str: string) => string;
7
-
8
6
  /**
9
7
  * Decodes the HTML entities emitted by {@link htmlEscape} and common numeric variants.
10
8
  */
11
9
  declare const htmlUnescape: (str: string) => string;
12
-
13
10
  interface MarkdownItEnv {
14
- plugins?: Record<string, unknown>;
11
+ plugins?: Record<string, unknown>;
15
12
  }
16
13
  interface MarkdownItHeader {
17
- /**
18
- * The slug of the header
19
- *
20
- * Typically the `id` attr of the header anchor
21
- */
22
- id: string;
23
- /**
24
- * The level of the header
25
- *
26
- * `1` to `6` for `<h1>` to `<h6>`
27
- */
28
- level: number;
29
- /**
30
- * The title of the header
31
- */
32
- title: string;
33
- /**
34
- * Link of the header
35
- *
36
- * Typically using `#${slug}` as the anchor hash
37
- */
38
- link: string;
39
- /**
40
- * The children of the header
41
- */
42
- children: MarkdownItHeader[];
14
+ /**
15
+ * The slug of the header
16
+ *
17
+ * Typically the `id` attr of the header anchor
18
+ */
19
+ id: string;
20
+ /**
21
+ * The level of the header
22
+ *
23
+ * `1` to `6` for `<h1>` to `<h6>`
24
+ */
25
+ level: number;
26
+ /**
27
+ * The title of the header
28
+ */
29
+ title: string;
30
+ /**
31
+ * Link of the header
32
+ *
33
+ * Typically using `#${slug}` as the anchor hash
34
+ */
35
+ link: string;
36
+ /**
37
+ * The children of the header
38
+ */
39
+ children: MarkdownItHeader[];
43
40
  }
44
- type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | {
45
- [P in K]?: T;
46
- } | undefined, key: K, defaults: T) => T;
47
-
41
+ type ResolvePluginOptionsFn = <T extends object, K extends keyof any>(options: T | { [P in K]?: T; } | undefined, key: K, defaults: T) => T;
48
42
  interface ResolveTitleOptions {
49
- /**
50
- * Should allow inline HTML tags or not.
51
- *
52
- * If the result is going to be used as Vue template, it should allow inline
53
- * HTML tags so that Vue custom components would be kept.
54
- */
55
- shouldAllowHtml: boolean;
56
- /**
57
- * Should escape the text content or not.
58
- *
59
- * If the result is going to be used in HTML directly, it should be escaped
60
- * so that the text content won't be wrongly treated as HTML tags.
61
- */
62
- shouldEscapeText: boolean;
43
+ /**
44
+ * Should allow inline HTML tags or not.
45
+ *
46
+ * If the result is going to be used as Vue template, it should allow inline
47
+ * HTML tags so that Vue custom components would be kept.
48
+ */
49
+ shouldAllowHtml: boolean;
50
+ /**
51
+ * Should escape the text content or not.
52
+ *
53
+ * If the result is going to be used in HTML directly, it should be escaped
54
+ * so that the text content won't be wrongly treated as HTML tags.
55
+ */
56
+ shouldEscapeText: boolean;
63
57
  }
64
58
  /**
65
59
  * Extracts plain heading text from a markdown-it inline token.
@@ -69,28 +63,27 @@ interface ResolveTitleOptions {
69
63
  * are ignored so the title remains human-readable.
70
64
  */
71
65
  declare const resolveTitleFromToken: (token: Token, { shouldAllowHtml, shouldEscapeText }: ResolveTitleOptions) => string;
72
-
73
66
  interface ResolveHeadersOptions extends ResolveTitleOptions {
74
- /**
75
- * Heading level that going to be resolved
76
- */
77
- level: number[];
78
- /**
79
- * Should allow headers inside nested blocks or not
80
- *
81
- * If set to `true`, headers inside blockquote, list, etc. would also be resolved.
82
- */
83
- shouldAllowNested: boolean;
84
- /**
85
- * A custom slugification function
86
- *
87
- * Would be ignored if the `id` attr of the token is set.
88
- */
89
- slugify?: (str: string) => string;
90
- /**
91
- * A function for formatting headings
92
- */
93
- format?: (str: string) => string | undefined;
67
+ /**
68
+ * Heading level that going to be resolved
69
+ */
70
+ level: number[];
71
+ /**
72
+ * Should allow headers inside nested blocks or not
73
+ *
74
+ * If set to `true`, headers inside blockquote, list, etc. would also be resolved.
75
+ */
76
+ shouldAllowNested: boolean;
77
+ /**
78
+ * A custom slugification function
79
+ *
80
+ * Would be ignored if the `id` attr of the token is set.
81
+ */
82
+ slugify?: (str: string) => string;
83
+ /**
84
+ * A function for formatting headings
85
+ */
86
+ format?: (str: string) => string | undefined;
94
87
  }
95
88
  /**
96
89
  * Builds a nested heading tree from markdown-it heading tokens.
@@ -98,16 +91,14 @@ interface ResolveHeadersOptions extends ResolveTitleOptions {
98
91
  * Existing heading `id` attributes are preserved. When a heading has no `id`,
99
92
  * the configured `slugify` function creates one from the resolved heading text.
100
93
  */
101
- declare const resolveHeadersFromTokens: (tokens: Token[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format, }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[];
102
-
94
+ declare const resolveHeadersFromTokens: (tokens: Token[], { level, shouldAllowHtml, shouldAllowNested, shouldEscapeText, slugify, format }?: Partial<ResolveHeadersOptions>) => MarkdownItHeader[];
103
95
  /**
104
96
  * Converts arbitrary heading text into a stable URL-friendly slug.
105
97
  *
106
98
  * The result is lowercase, accent-free, hyphen-separated, and safe to use as a
107
99
  * generated Markdown heading id.
108
100
  */
109
- declare const slugify: (str: string) => string;
110
-
101
+ declare const slugify$1: (str: string) => string;
111
102
  /**
112
103
  * Resolves plugin options from either a direct options object or a nested
113
104
  * package-level options bag.
@@ -116,9 +107,5 @@ declare const slugify: (str: string) => string;
116
107
  * or through a shared md-plugins config object keyed by plugin name. This helper
117
108
  * supports both shapes while applying default values.
118
109
  */
119
- declare function resolvePluginOptions<T extends object, K extends keyof any>(options: T | {
120
- [key in K]?: T;
121
- } | undefined, key: K, defaults: T): T;
122
-
123
- export { htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify };
124
- export type { MarkdownItEnv, MarkdownItHeader, ResolveHeadersOptions, ResolvePluginOptionsFn, ResolveTitleOptions };
110
+ declare function resolvePluginOptions<T extends object, K extends keyof any>(options: T | { [key in K]?: T; } | undefined, key: K, defaults: T): T;
111
+ export { type MarkdownItEnv, type MarkdownItHeader, ResolveHeadersOptions, type ResolvePluginOptionsFn, ResolveTitleOptions, htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify$1 as slugify };
package/dist/index.mjs CHANGED
@@ -1,103 +1,102 @@
1
1
  const htmlEscapeMap = {
2
- "&": "&amp;",
3
- "<": "&lt;",
4
- ">": "&gt;",
5
- "'": "&#39;",
6
- '"': "&quot;"
2
+ "&": "&amp;",
3
+ "<": "&lt;",
4
+ ">": "&gt;",
5
+ "'": "&#39;",
6
+ "\"": "&quot;"
7
7
  };
8
8
  const htmlEscapeRegexp = /[&<>'"]/g;
9
+
9
10
  const htmlEscape = (str) => str.replace(htmlEscapeRegexp, (char) => htmlEscapeMap[char]);
10
11
 
11
12
  const htmlUnescapeMap = {
12
- "&amp;": "&",
13
- "&#38;": "&",
14
- "&lt;": "<",
15
- "&#60;": "<",
16
- "&gt;": ">",
17
- "&#62;": ">",
18
- "&apos;": "'",
19
- "&#39;": "'",
20
- "&quot;": '"',
21
- "&#34;": '"'
13
+ "&amp;": "&",
14
+ "&#38;": "&",
15
+ "&lt;": "<",
16
+ "&#60;": "<",
17
+ "&gt;": ">",
18
+ "&#62;": ">",
19
+ "&apos;": "'",
20
+ "&#39;": "'",
21
+ "&quot;": "\"",
22
+ "&#34;": "\""
22
23
  };
23
24
  const htmlUnescapeRegexp = /&(amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g;
25
+
24
26
  const htmlUnescape = (str) => str.replace(htmlUnescapeRegexp, (char) => htmlUnescapeMap[char]);
25
27
 
28
+
26
29
  const resolveTitleFromToken = (token, { shouldAllowHtml, shouldEscapeText }) => {
27
- const children = token.children ?? [];
28
- const titleTokenTypes = ["text", "emoji", "code_inline"];
29
- if (shouldAllowHtml) {
30
- titleTokenTypes.push("html_inline");
31
- }
32
- const titleTokens = children.filter(
33
- (item) => titleTokenTypes.includes(item.type) && // filter permalink symbol that generated by markdown-it-anchor
34
- !item.meta?.isPermalinkSymbol
35
- );
36
- return titleTokens.reduce((result, item) => {
37
- if (shouldEscapeText) {
38
- if (item.type === "code_inline" || item.type === "text") {
39
- return `${result}${htmlEscape(item.content)}`;
40
- }
41
- }
42
- return `${result}${item.content}`;
43
- }, "").trim();
30
+ const children = token.children ?? [];
31
+ const titleTokenTypes = [
32
+ "text",
33
+ "emoji",
34
+ "code_inline"
35
+ ];
36
+ if (shouldAllowHtml) titleTokenTypes.push("html_inline");
37
+ return children.filter((item) => titleTokenTypes.includes(item.type) && !item.meta?.isPermalinkSymbol).reduce((result, item) => {
38
+ if (shouldEscapeText) {
39
+ if (item.type === "code_inline" || item.type === "text") return `${result}${htmlEscape(item.content)}`;
40
+ }
41
+ return `${result}${item.content}`;
42
+ }, "").trim();
44
43
  };
45
44
 
46
45
  const andRE = /&/g;
47
46
  const rCombining = /[\u0300-\u036F]/g;
48
47
  const rControl = /[\u0000-\u001f]/g;
49
48
  const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g;
49
+
50
50
  const slugify = (str) => str.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase().normalize("NFKD").replace(rCombining, "").replace(andRE, "-and-").replace(rControl, "-").replace(rSpecial, "-").replace(/[^a-z0-9-]+/g, "").replace(/([a-z])(\d)/g, "$1-$2").replace(/(\d)([a-z])/g, "$1-$2").replace(/-{2,}/g, "-").replace(/(^-|-$)/g, "").replace(/^(\d)/, "_$1");
51
51
 
52
- const resolveHeadersFromTokens = (tokens, {
53
- level = [1, 2, 3],
54
- shouldAllowHtml = false,
55
- shouldAllowNested = false,
56
- shouldEscapeText = false,
57
- slugify: slugify$1 = slugify,
58
- format = (str) => str
59
- } = {}) => {
60
- const headers = [];
61
- const stack = [];
62
- const pushHeader = (header) => {
63
- while (stack.length > 0 && header.level <= stack[0].level) {
64
- stack.shift();
65
- }
66
- if (stack.length === 0) {
67
- headers.push(header);
68
- } else {
69
- stack[0].children.push(header);
70
- }
71
- stack.unshift(header);
72
- };
73
- tokens.forEach((token, i) => {
74
- if (token.type !== "heading_open") return;
75
- if (token.level !== 0 && !shouldAllowNested) return;
76
- const headerLevel = Number.parseInt(token.tag.slice(1), 10);
77
- if (!level.includes(headerLevel)) return;
78
- const nextToken = tokens[i + 1];
79
- if (!nextToken) return;
80
- const title = resolveTitleFromToken(nextToken, {
81
- shouldAllowHtml,
82
- shouldEscapeText
83
- });
84
- const slug = token.attrGet("id") ?? slugify$1(title);
85
- pushHeader({
86
- level: headerLevel,
87
- title: format(title) ?? title,
88
- id: slug,
89
- link: `#${slug}`,
90
- children: []
91
- });
92
- });
93
- return headers;
52
+
53
+ const resolveHeadersFromTokens = (tokens, { level = [
54
+ 1,
55
+ 2,
56
+ 3
57
+ ], shouldAllowHtml = false, shouldAllowNested = false, shouldEscapeText = false, slugify: slugify$1 = slugify, format = (str) => str } = {}) => {
58
+ const headers = [];
59
+ const stack = [];
60
+
61
+ const pushHeader = (header) => {
62
+ while (stack.length > 0 && header.level <= stack[0].level) stack.shift();
63
+ if (stack.length === 0) headers.push(header);
64
+ else stack[0].children.push(header);
65
+ stack.unshift(header);
66
+ };
67
+ tokens.forEach((token, i) => {
68
+ if (token.type !== "heading_open") return;
69
+ if (token.level !== 0 && !shouldAllowNested) return;
70
+ const headerLevel = Number.parseInt(token.tag.slice(1), 10);
71
+ if (!level.includes(headerLevel)) return;
72
+ const nextToken = tokens[i + 1];
73
+ if (!nextToken) return;
74
+ const title = resolveTitleFromToken(nextToken, {
75
+ shouldAllowHtml,
76
+ shouldEscapeText
77
+ });
78
+ const slug = token.attrGet("id") ?? slugify$1(title);
79
+ pushHeader({
80
+ level: headerLevel,
81
+ title: format(title) ?? title,
82
+ id: slug,
83
+ link: `#${slug}`,
84
+ children: []
85
+ });
86
+ });
87
+ return headers;
94
88
  };
95
89
 
90
+
96
91
  function resolvePluginOptions(options, key, defaults) {
97
- if (options && typeof options === "object" && key in options) {
98
- return { ...defaults, ...options[key] };
99
- }
100
- return { ...defaults, ...options };
92
+ if (options && typeof options === "object" && key in options) return {
93
+ ...defaults,
94
+ ...options[key]
95
+ };
96
+ return {
97
+ ...defaults,
98
+ ...options
99
+ };
101
100
  }
102
101
 
103
- export { htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify };
102
+ export { htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolvePluginOptions, resolveTitleFromToken, slugify };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@md-plugins/shared",
3
- "version": "0.1.0-rc.9",
3
+ "version": "1.1.0",
4
4
  "description": "Shared functions and utilities for md-plugins.",
5
5
  "keywords": [
6
6
  "markdown-it",
@@ -37,13 +37,13 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/markdown-it": "^14.1.2",
40
- "markdown-it": "^14.2.0"
40
+ "markdown-it": "^14.3.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "markdown-it": "^14.2.0"
44
44
  },
45
45
  "scripts": {
46
- "build": "unbuild",
46
+ "build": "obuild && node ../../scripts/ensure-obuild-types.mjs",
47
47
  "clean": "rm -rf dist/ node_modules/",
48
48
  "test": "vitest"
49
49
  }