@vuepress/shared 2.0.0-rc.3 → 2.0.0-rc.31

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
@@ -5,7 +5,7 @@
5
5
 
6
6
  ## Documentation
7
7
 
8
- https://v2.vuepress.vuejs.org
8
+ https://vuepress.vuejs.org
9
9
 
10
10
  ## License
11
11
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { MarkdownItHeader } from '@mdit-vue/types';
2
-
1
+ import { MarkdownItHeader } from "@mdit-vue/types";
2
+ //#region src/types/head.d.ts
3
3
  /**
4
4
  * Config for `<head>` tags
5
5
  */
@@ -9,11 +9,11 @@ type HeadConfig = [HeadTagEmpty, HeadAttrsConfig] | [HeadTagNonEmpty, HeadAttrsC
9
9
  *
10
10
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head
11
11
  */
12
- type HeadTag = HeadTagNonEmpty | HeadTagEmpty;
12
+ type HeadTag = HeadTagEmpty | HeadTagNonEmpty;
13
13
  /**
14
14
  * Non-empty tags in `<head>`
15
15
  */
16
- type HeadTagNonEmpty = 'title' | 'style' | 'script' | 'noscript' | 'template';
16
+ type HeadTagNonEmpty = 'noscript' | 'script' | 'style' | 'template' | 'title';
17
17
  /**
18
18
  * Empty tags in `<head>`
19
19
  */
@@ -21,8 +21,9 @@ type HeadTagEmpty = 'base' | 'link' | 'meta' | 'script';
21
21
  /**
22
22
  * Attributes to be set for tags in `<head>`
23
23
  */
24
- type HeadAttrsConfig = Record<string, string | boolean>;
25
-
24
+ type HeadAttrsConfig = Record<string, boolean | string>;
25
+ //#endregion
26
+ //#region src/types/locale.d.ts
26
27
  /**
27
28
  * Locales config, a key-value object
28
29
  *
@@ -36,97 +37,95 @@ type LocaleConfig<T extends LocaleData = LocaleData> = Record<string, Partial<T>
36
37
  * Locales data
37
38
  */
38
39
  type LocaleData = Record<never, never>;
39
-
40
+ //#endregion
41
+ //#region src/types/page.d.ts
40
42
  /**
41
43
  * Base type of vuepress page
42
44
  */
43
- interface PageBase<ExtraPageFrontmatter extends Record<any, any> = Record<string, unknown>> {
44
- /**
45
- * Route path of the page
46
- *
47
- * Firstly inferred from the file path
48
- *
49
- * Might be overridden by permalink
50
- *
51
- * @example '/guide/index.html'
52
- * @example '/2020/02/02/hello-world.html'
53
- */
54
- path: string;
55
- /**
56
- * Title of the page
57
- */
58
- title: string;
59
- /**
60
- * Language of the page
61
- */
62
- lang: string;
63
- /**
64
- * Front matter of the page
65
- */
66
- frontmatter: PageFrontmatter<ExtraPageFrontmatter>;
67
- /**
68
- * Headers of the page
69
- */
70
- headers: PageHeader[];
45
+ interface PageBase<ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> {
46
+ /**
47
+ * Route path of the page
48
+ *
49
+ * Firstly inferred from the file path
50
+ *
51
+ * Might be overridden by permalink
52
+ *
53
+ * @example '/guide/index.html'
54
+ * @example '/2020/02/02/hello-world.html'
55
+ */
56
+ path: string;
57
+ /**
58
+ * Title of the page
59
+ */
60
+ title: string;
61
+ /**
62
+ * Language of the page
63
+ */
64
+ lang: string;
65
+ /**
66
+ * Front matter of the page
67
+ */
68
+ frontmatter: PageFrontmatter<ExtraPageFrontmatter>;
71
69
  }
72
70
  /**
73
71
  * Vuepress page data
74
72
  */
75
- type PageData<ExtraPageData extends Record<any, any> = Record<never, never>, ExtraPageFrontmatter extends Record<any, any> = Record<string, unknown>> = PageBase<ExtraPageFrontmatter> & ExtraPageData;
73
+ type PageData<ExtraPageData extends Record<string, unknown> = Record<string, unknown>, ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> = ExtraPageData & PageBase<ExtraPageFrontmatter>;
76
74
  /**
77
75
  * Vuepress page frontmatter
78
76
  *
79
77
  * Notice that frontmatter is parsed from yaml or other languages,
80
78
  * so we cannot guarantee the type safety
81
79
  */
82
- type PageFrontmatter<T extends Record<any, any> = Record<string, unknown>> = Partial<T> & {
83
- date?: string | Date;
84
- description?: string;
85
- head?: HeadConfig[];
86
- lang?: string;
87
- layout?: string;
88
- permalink?: string;
89
- permalinkPattern?: string | null;
90
- routeMeta?: Record<string, unknown>;
91
- title?: string;
80
+ type PageFrontmatter<T extends Record<string, unknown> = Record<string, unknown>> = Partial<T> & {
81
+ date?: Date | string;
82
+ description?: string;
83
+ head?: HeadConfig[];
84
+ lang?: string;
85
+ layout?: string;
86
+ permalink?: string | null;
87
+ permalinkPattern?: string | null;
88
+ routeMeta?: Record<string, unknown>;
89
+ title?: string;
92
90
  };
93
91
  /**
94
92
  * Vuepress page header
95
93
  */
96
94
  type PageHeader = MarkdownItHeader;
97
-
95
+ //#endregion
96
+ //#region src/types/site.d.ts
98
97
  /**
99
98
  * Vuepress site data
100
99
  */
101
100
  interface SiteData extends SiteLocaleData {
102
- /**
103
- * The base URL the site will be deployed at
104
- *
105
- * It should always start and end with a slash
106
- *
107
- * @default '/'
108
- */
109
- base: '/' | `/${string}/`;
110
- /**
111
- * Specify locales for i18n support
112
- *
113
- * It will override the root-level site data in different subpath
114
- *
115
- * @example
116
- * {
117
- * '/en/': {
118
- * lang: 'en-US',
119
- * title: 'Hello',
120
- * description: 'This will take effect under /en/ subpath',
121
- * },
122
- * '/zh/': {
123
- * lang: 'zh-CN',
124
- * title: '你好',
125
- * description: '它将会在 /zh/ 子路径下生效',
126
- * }
127
- * }
128
- */
129
- locales: SiteLocaleConfig;
101
+ /**
102
+ * The base URL the site will be deployed at
103
+ *
104
+ * It should always start and end with a slash
105
+ *
106
+ * @default '/'
107
+ */
108
+ base: '/' | `/${string}/`;
109
+ /**
110
+ * Specify locales for i18n support
111
+ *
112
+ * It will override the root-level site data in different subpath
113
+ *
114
+ * @example
115
+ * {
116
+ * '/en/': {
117
+ * lang: 'en-US',
118
+ * title: 'Hello',
119
+ * description: 'This will take effect under /en/ subpath',
120
+ * },
121
+ * '/zh/': {
122
+ * lang: 'zh-CN',
123
+ * title: '你好',
124
+ * description: '它将会在 /zh/ 子路径下生效',
125
+ * }
126
+ * }
127
+ */
128
+ locales: SiteLocaleConfig;
130
129
  }
131
130
  /**
132
131
  * Locales data of vuepress site
@@ -138,76 +137,57 @@ interface SiteData extends SiteLocaleData {
138
137
  * used for specific locale
139
138
  */
140
139
  interface SiteLocaleData {
141
- /**
142
- * Language for the site
143
- *
144
- * @default 'en-US'
145
- */
146
- lang: string;
147
- /**
148
- * Title for the site
149
- *
150
- * @default ''
151
- */
152
- title: string;
153
- /**
154
- * Description for the site
155
- *
156
- * @default ''
157
- */
158
- description: string;
159
- /**
160
- * Head config
161
- *
162
- * Descibe the tags to be appended into the `<head>` tag
163
- *
164
- * @default []
165
- *
166
- * @example ['link', { rel: 'icon', href: '/logo.png' }]
167
- * @example ['style', { type: 'text/css' }, 'p { color: red; }']
168
- */
169
- head: HeadConfig[];
140
+ /**
141
+ * Language for the site
142
+ *
143
+ * @default 'en-US'
144
+ */
145
+ lang: string;
146
+ /**
147
+ * Title for the site
148
+ *
149
+ * @default ''
150
+ */
151
+ title: string;
152
+ /**
153
+ * Description for the site
154
+ *
155
+ * @default ''
156
+ */
157
+ description: string;
158
+ /**
159
+ * Head config
160
+ *
161
+ * Describe the tags to be appended into the `<head>` tag
162
+ *
163
+ * @default []
164
+ *
165
+ * @example ['link', { rel: 'icon', href: '/logo.png' }]
166
+ * @example ['style', { type: 'text/css' }, 'p { color: red; }']
167
+ */
168
+ head: HeadConfig[];
170
169
  }
171
170
  /**
172
171
  * Site locale config
173
172
  */
174
173
  type SiteLocaleConfig = LocaleConfig<SiteLocaleData>;
175
-
174
+ //#endregion
175
+ //#region src/types/ssr.d.ts
176
176
  /**
177
177
  * Context for SSR
178
178
  */
179
179
  interface VuepressSSRContext {
180
- lang: string;
181
- head: HeadConfig[];
180
+ lang: string;
181
+ head: HeadConfig[];
182
182
  }
183
-
184
- /**
185
- * Dedupe head config with identifier
186
- *
187
- * Items that appear earlier have higher priority
188
- */
189
- declare const dedupeHead: (head: HeadConfig[]) => HeadConfig[];
190
-
191
- /**
192
- * Ensure a url string to have leading slash /
193
- */
194
- declare const ensureLeadingSlash: (str: string) => string;
195
-
196
- /**
197
- * Ensure a url string to have ending slash /
198
- */
199
- declare const ensureEndingSlash: (str: string) => string;
200
-
201
- /**
202
- * Format a date string to `yyyy-MM-dd`
203
- */
204
- declare const formatDateString: (str: string, defaultDateString?: string) => string;
205
-
183
+ //#endregion
184
+ //#region src/utils/links/isLinkExternal.d.ts
206
185
  /**
207
186
  * Determine a link is external or not
208
187
  */
209
188
  declare const isLinkExternal: (link: string, base?: string) => boolean;
210
-
189
+ //#endregion
190
+ //#region src/utils/links/isLinkHttp.d.ts
211
191
  /**
212
192
  * Determine a link is http link or not
213
193
  *
@@ -216,56 +196,108 @@ declare const isLinkExternal: (link: string, base?: string) => boolean;
216
196
  * - //github.com
217
197
  */
218
198
  declare const isLinkHttp: (link: string) => boolean;
219
-
199
+ //#endregion
200
+ //#region src/utils/links/isLinkWithProtocol.d.ts
220
201
  /**
221
202
  * Determine a link has protocol or not
222
203
  */
223
204
  declare const isLinkWithProtocol: (link: string) => boolean;
224
-
205
+ //#endregion
206
+ //#region src/utils/routes/inferRoutePath.d.ts
225
207
  /**
226
- * Check if a value is plain object, with generic type support
208
+ * Infer route path of the given raw path
227
209
  */
228
- declare const isPlainObject: <T extends Record<any, any> = Record<any, any>>(val: unknown) => val is T;
229
-
210
+ declare const inferRoutePath: (rawPath: string) => string;
211
+ //#endregion
212
+ //#region src/utils/routes/normalizeRoutePath.d.ts
213
+ /**
214
+ * Normalize the given pathname path to the final route path
215
+ */
216
+ declare const normalizeRoutePath: (pathname: string, current?: string) => string;
217
+ //#endregion
218
+ //#region src/utils/routes/resolveLocalePath.d.ts
230
219
  /**
231
- * Normalize the given path to the final route path
220
+ * Resolve the matched locale path of route path
232
221
  */
233
- declare const normalizeRoutePath: (path: string) => string;
234
-
222
+ declare const resolveLocalePath: (locales: LocaleConfig, routePath: string) => string;
223
+ //#endregion
224
+ //#region src/utils/routes/resolveRoutePathFromUrl.d.ts
225
+ /**
226
+ * For a give URL, remove the origin and the site base to get the route path
227
+ */
228
+ declare const resolveRoutePathFromUrl: (url: string, base?: string) => string;
229
+ //#endregion
230
+ //#region src/utils/routes/splitPath.d.ts
231
+ /**
232
+ * Split a path into pathname and hashAndQueries
233
+ */
234
+ declare const splitPath: (path: string) => {
235
+ pathname: string;
236
+ hashAndQueries: string;
237
+ };
238
+ //#endregion
239
+ //#region src/utils/dedupeHead.d.ts
240
+ /**
241
+ * Dedupe head config with identifier
242
+ *
243
+ * Items that appear earlier have higher priority
244
+ */
245
+ declare const dedupeHead: (head: HeadConfig[]) => HeadConfig[];
246
+ //#endregion
247
+ //#region src/utils/ensureLeadingSlash.d.ts
248
+ /**
249
+ * Ensure a url string to have leading slash /
250
+ */
251
+ declare const ensureLeadingSlash: (str: string) => string;
252
+ //#endregion
253
+ //#region src/utils/ensureEndingSlash.d.ts
254
+ /**
255
+ * Ensure a url string to have ending slash /
256
+ */
257
+ declare const ensureEndingSlash: (str: string) => string;
258
+ //#endregion
259
+ //#region src/utils/formatDateString.d.ts
260
+ /**
261
+ * Format a date string to `yyyy-MM-dd`
262
+ */
263
+ declare const formatDateString: (str: string, defaultDateString?: string) => string;
264
+ //#endregion
265
+ //#region src/utils/omit.d.ts
235
266
  /**
236
267
  * Omit properties from an object
237
268
  */
238
269
  declare const omit: <T extends Record<string, unknown>, U extends string[]>(obj: T, ...keys: U) => Omit<T, U[number]>;
239
-
270
+ //#endregion
271
+ //#region src/utils/removeEndingSlash.d.ts
240
272
  /**
241
273
  * Remove ending slash / from a string
242
274
  */
243
275
  declare const removeEndingSlash: (str: string) => string;
244
-
276
+ //#endregion
277
+ //#region src/utils/removeLeadingSlash.d.ts
245
278
  /**
246
279
  * Remove leading slash / from a string
247
280
  */
248
281
  declare const removeLeadingSlash: (str: string) => string;
249
-
282
+ //#endregion
283
+ //#region src/utils/resolveHeadIdentifier.d.ts
250
284
  /**
251
285
  * Resolve identifier of a tag, to avoid duplicated tags in `<head>`
252
286
  */
253
287
  declare const resolveHeadIdentifier: ([tag, attrs, content]: HeadConfig) => string | null;
254
-
255
- /**
256
- * Resolve the matched locale path of route path
257
- */
258
- declare const resolveLocalePath: (locales: LocaleConfig, routePath: string) => string;
259
-
260
- declare const resolveRoutePathFromUrl: (url: string, base?: string) => string;
261
-
288
+ //#endregion
289
+ //#region src/utils/typeGuards.d.ts
262
290
  /**
263
291
  * Check if a value is a function
264
292
  */
265
293
  declare const isFunction: (val: unknown) => val is Function;
294
+ /**
295
+ * Check if a value is plain object, with generic type support
296
+ */
297
+ declare const isPlainObject: <T extends Record<any, any> = Record<any, any>>(val: unknown) => val is T;
266
298
  /**
267
299
  * Check if a value is a string
268
300
  */
269
301
  declare const isString: (val: unknown) => val is string;
270
-
271
- export { type HeadAttrsConfig, type HeadConfig, type HeadTag, type HeadTagEmpty, type HeadTagNonEmpty, type LocaleConfig, type LocaleData, type PageBase, type PageData, type PageFrontmatter, type PageHeader, type SiteData, type SiteLocaleConfig, type SiteLocaleData, type VuepressSSRContext, dedupeHead, ensureEndingSlash, ensureLeadingSlash, formatDateString, isFunction, isLinkExternal, isLinkHttp, isLinkWithProtocol, isPlainObject, isString, normalizeRoutePath, omit, removeEndingSlash, removeLeadingSlash, resolveHeadIdentifier, resolveLocalePath, resolveRoutePathFromUrl };
302
+ //#endregion
303
+ export { type HeadAttrsConfig, type HeadConfig, type HeadTag, type HeadTagEmpty, type HeadTagNonEmpty, type LocaleConfig, type LocaleData, type PageBase, type PageData, type PageFrontmatter, type PageHeader, type SiteData, type SiteLocaleConfig, type SiteLocaleData, type VuepressSSRContext, dedupeHead, ensureEndingSlash, ensureLeadingSlash, formatDateString, inferRoutePath, isFunction, isLinkExternal, isLinkHttp, isLinkWithProtocol, isPlainObject, isString, normalizeRoutePath, omit, removeEndingSlash, removeLeadingSlash, resolveHeadIdentifier, resolveLocalePath, resolveRoutePathFromUrl, splitPath };
package/dist/index.js CHANGED
@@ -1,145 +1,196 @@
1
- // src/utils/resolveHeadIdentifier.ts
2
- var TAGS_ALLOWED = ["link", "meta", "script", "style", "noscript", "template"];
3
- var TAGS_UNIQUE = ["title", "base"];
4
- var resolveHeadIdentifier = ([tag, attrs, content]) => {
5
- if (TAGS_UNIQUE.includes(tag)) {
6
- return tag;
7
- }
8
- if (!TAGS_ALLOWED.includes(tag)) {
9
- return null;
10
- }
11
- if (tag === "meta" && attrs.name) {
12
- return `${tag}.${attrs.name}`;
13
- }
14
- if (tag === "template" && attrs.id) {
15
- return `${tag}.${attrs.id}`;
16
- }
17
- return JSON.stringify([
18
- tag,
19
- Object.entries(attrs).map(([key, value]) => {
20
- if (typeof value === "boolean") {
21
- return value ? [key, ""] : null;
22
- }
23
- return [key, value];
24
- }).filter((item) => item != null).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)),
25
- content
26
- ]);
1
+ //#region src/utils/links/isLinkWithProtocol.ts
2
+ /**
3
+ * Determine a link has protocol or not
4
+ */
5
+ const isLinkWithProtocol = (link) => /^[a-z][a-z0-9+.-]*:/.test(link) || link.startsWith("//");
6
+ //#endregion
7
+ //#region src/utils/links/isLinkExternal.ts
8
+ const markdownLinkRegexp = /.md((\?|#).*)?$/;
9
+ /**
10
+ * Determine a link is external or not
11
+ */
12
+ const isLinkExternal = (link, base = "/") => isLinkWithProtocol(link) || link.startsWith("/") && !link.startsWith(base) && !markdownLinkRegexp.test(link);
13
+ //#endregion
14
+ //#region src/utils/links/isLinkHttp.ts
15
+ /**
16
+ * Determine a link is http link or not
17
+ *
18
+ * - http://github.com
19
+ * - https://github.com
20
+ * - //github.com
21
+ */
22
+ const isLinkHttp = (link) => /^(https?:)?\/\//.test(link);
23
+ //#endregion
24
+ //#region src/utils/routes/inferRoutePath.ts
25
+ /**
26
+ * Infer route path of the given raw path
27
+ */
28
+ const inferRoutePath = (rawPath) => {
29
+ if (!rawPath || rawPath.endsWith("/")) return rawPath;
30
+ let routePath = rawPath.replace(/(^|\/)README.md$/i, "$1index.html");
31
+ if (routePath.endsWith(".md")) routePath = `${routePath.substring(0, routePath.length - 3)}.html`;
32
+ else if (!routePath.endsWith(".html")) routePath = `${routePath}.html`;
33
+ if (routePath.endsWith("/index.html")) routePath = routePath.substring(0, routePath.length - 10);
34
+ return routePath;
27
35
  };
28
-
29
- // src/utils/dedupeHead.ts
30
- var dedupeHead = (head) => {
31
- const identifierSet = /* @__PURE__ */ new Set();
32
- const result = [];
33
- head.forEach((item) => {
34
- const identifier = resolveHeadIdentifier(item);
35
- if (identifier && !identifierSet.has(identifier)) {
36
- identifierSet.add(identifier);
37
- result.push(item);
38
- }
39
- });
40
- return result;
36
+ //#endregion
37
+ //#region src/utils/routes/normalizeRoutePath.ts
38
+ const FAKE_HOST = "http://.";
39
+ /**
40
+ * Normalize the given pathname path to the final route path
41
+ */
42
+ const normalizeRoutePath = (pathname, current) => {
43
+ if (!pathname.startsWith("/") && current) {
44
+ const loc = current.slice(0, current.lastIndexOf("/"));
45
+ return inferRoutePath(new URL(`${loc}/${pathname}`, FAKE_HOST).pathname);
46
+ }
47
+ return inferRoutePath(pathname);
41
48
  };
42
-
43
- // src/utils/ensureLeadingSlash.ts
44
- var ensureLeadingSlash = (str) => str[0] === "/" ? str : `/${str}`;
45
-
46
- // src/utils/ensureEndingSlash.ts
47
- var ensureEndingSlash = (str) => str[str.length - 1] === "/" || str.endsWith(".html") ? str : `${str}/`;
48
-
49
- // src/utils/formatDateString.ts
50
- var formatDateString = (str, defaultDateString = "") => {
51
- const dateMatch = str.match(/\b(\d{4})-(\d{1,2})-(\d{1,2})\b/);
52
- if (dateMatch === null) {
53
- return defaultDateString;
54
- }
55
- const [, yearStr, monthStr, dayStr] = dateMatch;
56
- return [yearStr, monthStr.padStart(2, "0"), dayStr.padStart(2, "0")].join("-");
49
+ //#endregion
50
+ //#region src/utils/routes/resolveLocalePath.ts
51
+ /**
52
+ * Resolve the matched locale path of route path
53
+ */
54
+ const resolveLocalePath = (locales, routePath) => {
55
+ const localePaths = Object.keys(locales).sort((a, b) => {
56
+ const levelDelta = b.split("/").length - a.split("/").length;
57
+ if (levelDelta !== 0) return levelDelta;
58
+ return b.length - a.length;
59
+ });
60
+ for (const localePath of localePaths) if (routePath.startsWith(localePath)) return localePath;
61
+ return "/";
57
62
  };
58
-
59
- // src/utils/isLinkHttp.ts
60
- var isLinkHttp = (link) => /^(https?:)?\/\//.test(link);
61
-
62
- // src/utils/isLinkExternal.ts
63
- var markdownLinkRegexp = /.md((\?|#).*)?$/;
64
- var isLinkExternal = (link, base = "/") => {
65
- if (isLinkHttp(link)) {
66
- return true;
67
- }
68
- if (link.startsWith("/") && !link.startsWith(base) && !markdownLinkRegexp.test(link)) {
69
- return true;
70
- }
71
- return false;
63
+ //#endregion
64
+ //#region src/utils/routes/resolveRoutePathFromUrl.ts
65
+ /**
66
+ * For a give URL, remove the origin and the site base to get the route path
67
+ */
68
+ const resolveRoutePathFromUrl = (url, base = "/") => {
69
+ const pathname = url.replace(/^(?:https?:)?\/\/[^/]*/, "");
70
+ return pathname.startsWith(base) ? `/${pathname.slice(base.length)}` : pathname;
72
71
  };
73
-
74
- // src/utils/isLinkWithProtocol.ts
75
- var isLinkWithProtocol = (link) => /^[a-z][a-z0-9+.-]*:/.test(link);
76
-
77
- // src/utils/isPlainObject.ts
78
- var isPlainObject = (val) => Object.prototype.toString.call(val) === "[object Object]";
79
-
80
- // src/utils/normalizeRoutePath.ts
81
- var normalizeRoutePath = (path) => {
82
- const convertedMdPath = path.endsWith("README.md") ? path.substring(0, path.length - 9) : path.endsWith(".md") ? path.substring(0, path.length - 3) + ".html" : path;
83
- return convertedMdPath.endsWith("/index.html") ? convertedMdPath.substring(0, convertedMdPath.length - 10) : convertedMdPath.endsWith(".html") || convertedMdPath.endsWith("/") ? convertedMdPath : convertedMdPath + ".html";
72
+ //#endregion
73
+ //#region src/utils/routes/splitPath.ts
74
+ const SPLIT_CHAR_REGEXP = /(#|\?)/;
75
+ /**
76
+ * Split a path into pathname and hashAndQueries
77
+ */
78
+ const splitPath = (path) => {
79
+ const [pathname, ...hashAndQueries] = path.split(SPLIT_CHAR_REGEXP);
80
+ return {
81
+ pathname,
82
+ hashAndQueries: hashAndQueries.join("")
83
+ };
84
84
  };
85
-
86
- // src/utils/omit.ts
87
- var omit = (obj, ...keys) => {
88
- const result = { ...obj };
89
- for (const key of keys) {
90
- delete result[key];
91
- }
92
- return result;
85
+ //#endregion
86
+ //#region src/utils/resolveHeadIdentifier.ts
87
+ const TAGS_ALLOWED = [
88
+ "link",
89
+ "meta",
90
+ "script",
91
+ "style",
92
+ "noscript",
93
+ "template"
94
+ ];
95
+ const TAGS_UNIQUE = ["title", "base"];
96
+ /**
97
+ * Resolve identifier of a tag, to avoid duplicated tags in `<head>`
98
+ */
99
+ const resolveHeadIdentifier = ([tag, attrs, content]) => {
100
+ if (TAGS_UNIQUE.includes(tag)) return tag;
101
+ if (!TAGS_ALLOWED.includes(tag)) return null;
102
+ if (tag === "meta" && attrs.name) return `${tag}.${attrs.name}`;
103
+ if (tag === "template" && attrs.id) return `${tag}.${attrs.id}`;
104
+ return JSON.stringify([
105
+ tag,
106
+ Object.entries(attrs).map(([key, value]) => {
107
+ if (typeof value === "boolean") return value ? [key, ""] : null;
108
+ return [key, value];
109
+ }).filter((item) => item != null).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)),
110
+ content
111
+ ]);
93
112
  };
94
-
95
- // src/utils/removeEndingSlash.ts
96
- var removeEndingSlash = (str) => str[str.length - 1] === "/" ? str.slice(0, -1) : str;
97
-
98
- // src/utils/removeLeadingSlash.ts
99
- var removeLeadingSlash = (str) => str[0] === "/" ? str.slice(1) : str;
100
-
101
- // src/utils/resolveLocalePath.ts
102
- var resolveLocalePath = (locales, routePath) => {
103
- const localePaths = Object.keys(locales).sort((a, b) => {
104
- const levelDelta = b.split("/").length - a.split("/").length;
105
- if (levelDelta !== 0) {
106
- return levelDelta;
107
- }
108
- return b.length - a.length;
109
- });
110
- for (const localePath of localePaths) {
111
- if (routePath.startsWith(localePath)) {
112
- return localePath;
113
- }
114
- }
115
- return "/";
113
+ //#endregion
114
+ //#region src/utils/dedupeHead.ts
115
+ /**
116
+ * Dedupe head config with identifier
117
+ *
118
+ * Items that appear earlier have higher priority
119
+ */
120
+ const dedupeHead = (head) => {
121
+ const identifierSet = /* @__PURE__ */ new Set();
122
+ const result = [];
123
+ head.forEach((item) => {
124
+ const identifier = resolveHeadIdentifier(item);
125
+ if (identifier && !identifierSet.has(identifier)) {
126
+ identifierSet.add(identifier);
127
+ result.push(item);
128
+ }
129
+ });
130
+ return result;
116
131
  };
117
-
118
- // src/utils/resolveRoutePathFromUrl.ts
119
- var resolveRoutePathFromUrl = (url, base = "/") => {
120
- const pathname = url.replace(/^(https?:)?\/\/[^/]*/, "");
121
- return pathname.startsWith(base) ? `/${pathname.slice(base.length)}` : pathname;
132
+ //#endregion
133
+ //#region src/utils/ensureLeadingSlash.ts
134
+ /**
135
+ * Ensure a url string to have leading slash /
136
+ */
137
+ const ensureLeadingSlash = (str) => str.startsWith("/") ? str : `/${str}`;
138
+ //#endregion
139
+ //#region src/utils/ensureEndingSlash.ts
140
+ /**
141
+ * Ensure a url string to have ending slash /
142
+ */
143
+ const ensureEndingSlash = (str) => str.endsWith("/") || str.endsWith(".html") ? str : `${str}/`;
144
+ //#endregion
145
+ //#region src/utils/formatDateString.ts
146
+ /**
147
+ * Format a date string to `yyyy-MM-dd`
148
+ */
149
+ const formatDateString = (str, defaultDateString = "") => {
150
+ const dateMatch = str.match(/\b(\d{4})-(\d{1,2})-(\d{1,2})\b/);
151
+ if (dateMatch === null) return defaultDateString;
152
+ const [, yearStr, monthStr, dayStr] = dateMatch;
153
+ return [
154
+ yearStr,
155
+ monthStr.padStart(2, "0"),
156
+ dayStr.padStart(2, "0")
157
+ ].join("-");
122
158
  };
123
-
124
- // src/utils/typeGuards.ts
125
- var isFunction = (val) => typeof val === "function";
126
- var isString = (val) => typeof val === "string";
127
- export {
128
- dedupeHead,
129
- ensureEndingSlash,
130
- ensureLeadingSlash,
131
- formatDateString,
132
- isFunction,
133
- isLinkExternal,
134
- isLinkHttp,
135
- isLinkWithProtocol,
136
- isPlainObject,
137
- isString,
138
- normalizeRoutePath,
139
- omit,
140
- removeEndingSlash,
141
- removeLeadingSlash,
142
- resolveHeadIdentifier,
143
- resolveLocalePath,
144
- resolveRoutePathFromUrl
159
+ //#endregion
160
+ //#region src/utils/omit.ts
161
+ /**
162
+ * Omit properties from an object
163
+ */
164
+ const omit = (obj, ...keys) => {
165
+ const result = { ...obj };
166
+ for (const key of keys) delete result[key];
167
+ return result;
145
168
  };
169
+ //#endregion
170
+ //#region src/utils/removeEndingSlash.ts
171
+ /**
172
+ * Remove ending slash / from a string
173
+ */
174
+ const removeEndingSlash = (str) => str.endsWith("/") ? str.slice(0, -1) : str;
175
+ //#endregion
176
+ //#region src/utils/removeLeadingSlash.ts
177
+ /**
178
+ * Remove leading slash / from a string
179
+ */
180
+ const removeLeadingSlash = (str) => str.startsWith("/") ? str.slice(1) : str;
181
+ //#endregion
182
+ //#region src/utils/typeGuards.ts
183
+ /**
184
+ * Check if a value is a function
185
+ */
186
+ const isFunction = (val) => typeof val === "function";
187
+ /**
188
+ * Check if a value is plain object, with generic type support
189
+ */
190
+ const isPlainObject = (val) => Object.prototype.toString.call(val) === "[object Object]";
191
+ /**
192
+ * Check if a value is a string
193
+ */
194
+ const isString = (val) => typeof val === "string";
195
+ //#endregion
196
+ export { dedupeHead, ensureEndingSlash, ensureLeadingSlash, formatDateString, inferRoutePath, isFunction, isLinkExternal, isLinkHttp, isLinkWithProtocol, isPlainObject, isString, normalizeRoutePath, omit, removeEndingSlash, removeLeadingSlash, resolveHeadIdentifier, resolveLocalePath, resolveRoutePathFromUrl, splitPath };
package/package.json CHANGED
@@ -1,55 +1,49 @@
1
1
  {
2
2
  "name": "@vuepress/shared",
3
- "version": "2.0.0-rc.3",
3
+ "version": "2.0.0-rc.31",
4
4
  "description": "Utils that shared between VuePress node and client",
5
5
  "keywords": [
6
- "vuepress",
7
6
  "shared",
8
- "utils"
7
+ "utils",
8
+ "vuepress"
9
9
  ],
10
10
  "homepage": "https://github.com/vuepress",
11
11
  "bugs": {
12
12
  "url": "https://github.com/vuepress/core/issues"
13
13
  },
14
+ "license": "MIT",
15
+ "author": "meteorlxy",
14
16
  "repository": {
15
17
  "type": "git",
16
18
  "url": "git+https://github.com/vuepress/core.git"
17
19
  },
18
- "license": "MIT",
19
- "author": "meteorlxy",
20
+ "files": [
21
+ "dist"
22
+ ],
20
23
  "type": "module",
21
- "exports": {
22
- ".": "./dist/index.js",
23
- "./package.json": "./package.json"
24
- },
25
24
  "main": "./dist/index.js",
26
25
  "module": "./dist/index.js",
27
26
  "types": "./dist/index.d.ts",
28
- "files": [
29
- "dist"
30
- ],
31
- "dependencies": {
32
- "@mdit-vue/types": "^2.0.0"
27
+ "exports": {
28
+ ".": "./dist/index.js",
29
+ "./package.json": "./package.json"
33
30
  },
34
31
  "publishConfig": {
35
32
  "access": "public"
36
33
  },
37
- "tsup": {
38
- "clean": true,
39
- "dts": "./src/index.ts",
40
- "entry": [
41
- "./src/index.ts"
42
- ],
43
- "format": [
44
- "esm"
45
- ],
46
- "outDir": "./dist",
47
- "sourcemap": false,
48
- "target": "es2022",
34
+ "dependencies": {
35
+ "@mdit-vue/types": "^3.0.2"
36
+ },
37
+ "tsdown": {
38
+ "dts": true,
39
+ "entry": "./src/index.ts",
40
+ "fixedExtension": false,
41
+ "format": "esm",
42
+ "target": "es2023",
49
43
  "tsconfig": "../../tsconfig.dts.json"
50
44
  },
51
45
  "scripts": {
52
- "build": "tsup",
46
+ "build": "tsdown",
53
47
  "clean": "rimraf dist"
54
48
  }
55
49
  }