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

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,6 @@
1
- import { MarkdownItHeader } from '@mdit-vue/types';
1
+ import { MarkdownItHeader } from "@mdit-vue/types";
2
2
 
3
+ //#region src/types/head.d.ts
3
4
  /**
4
5
  * Config for `<head>` tags
5
6
  */
@@ -9,11 +10,11 @@ type HeadConfig = [HeadTagEmpty, HeadAttrsConfig] | [HeadTagNonEmpty, HeadAttrsC
9
10
  *
10
11
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head
11
12
  */
12
- type HeadTag = HeadTagNonEmpty | HeadTagEmpty;
13
+ type HeadTag = HeadTagEmpty | HeadTagNonEmpty;
13
14
  /**
14
15
  * Non-empty tags in `<head>`
15
16
  */
16
- type HeadTagNonEmpty = 'title' | 'style' | 'script' | 'noscript' | 'template';
17
+ type HeadTagNonEmpty = 'noscript' | 'script' | 'style' | 'template' | 'title';
17
18
  /**
18
19
  * Empty tags in `<head>`
19
20
  */
@@ -21,8 +22,9 @@ type HeadTagEmpty = 'base' | 'link' | 'meta' | 'script';
21
22
  /**
22
23
  * Attributes to be set for tags in `<head>`
23
24
  */
24
- type HeadAttrsConfig = Record<string, string | boolean>;
25
-
25
+ type HeadAttrsConfig = Record<string, boolean | string>;
26
+ //#endregion
27
+ //#region src/types/locale.d.ts
26
28
  /**
27
29
  * Locales config, a key-value object
28
30
  *
@@ -36,97 +38,95 @@ type LocaleConfig<T extends LocaleData = LocaleData> = Record<string, Partial<T>
36
38
  * Locales data
37
39
  */
38
40
  type LocaleData = Record<never, never>;
39
-
41
+ //#endregion
42
+ //#region src/types/page.d.ts
40
43
  /**
41
44
  * Base type of vuepress page
42
45
  */
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[];
46
+ interface PageBase<ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> {
47
+ /**
48
+ * Route path of the page
49
+ *
50
+ * Firstly inferred from the file path
51
+ *
52
+ * Might be overridden by permalink
53
+ *
54
+ * @example '/guide/index.html'
55
+ * @example '/2020/02/02/hello-world.html'
56
+ */
57
+ path: string;
58
+ /**
59
+ * Title of the page
60
+ */
61
+ title: string;
62
+ /**
63
+ * Language of the page
64
+ */
65
+ lang: string;
66
+ /**
67
+ * Front matter of the page
68
+ */
69
+ frontmatter: PageFrontmatter<ExtraPageFrontmatter>;
71
70
  }
72
71
  /**
73
72
  * Vuepress page data
74
73
  */
75
- type PageData<ExtraPageData extends Record<any, any> = Record<never, never>, ExtraPageFrontmatter extends Record<any, any> = Record<string, unknown>> = PageBase<ExtraPageFrontmatter> & ExtraPageData;
74
+ type PageData<ExtraPageData extends Record<string, unknown> = Record<string, unknown>, ExtraPageFrontmatter extends Record<string, unknown> = Record<string, unknown>> = ExtraPageData & PageBase<ExtraPageFrontmatter>;
76
75
  /**
77
76
  * Vuepress page frontmatter
78
77
  *
79
78
  * Notice that frontmatter is parsed from yaml or other languages,
80
79
  * so we cannot guarantee the type safety
81
80
  */
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;
81
+ type PageFrontmatter<T extends Record<string, unknown> = Record<string, unknown>> = Partial<T> & {
82
+ date?: Date | string;
83
+ description?: string;
84
+ head?: HeadConfig[];
85
+ lang?: string;
86
+ layout?: string;
87
+ permalink?: string | null;
88
+ permalinkPattern?: string | null;
89
+ routeMeta?: Record<string, unknown>;
90
+ title?: string;
92
91
  };
93
92
  /**
94
93
  * Vuepress page header
95
94
  */
96
95
  type PageHeader = MarkdownItHeader;
97
-
96
+ //#endregion
97
+ //#region src/types/site.d.ts
98
98
  /**
99
99
  * Vuepress site data
100
100
  */
101
101
  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;
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;
130
130
  }
131
131
  /**
132
132
  * Locales data of vuepress site
@@ -138,76 +138,57 @@ interface SiteData extends SiteLocaleData {
138
138
  * used for specific locale
139
139
  */
140
140
  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[];
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
+ * Describe 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[];
170
170
  }
171
171
  /**
172
172
  * Site locale config
173
173
  */
174
174
  type SiteLocaleConfig = LocaleConfig<SiteLocaleData>;
175
-
175
+ //#endregion
176
+ //#region src/types/ssr.d.ts
176
177
  /**
177
178
  * Context for SSR
178
179
  */
179
180
  interface VuepressSSRContext {
180
- lang: string;
181
- head: HeadConfig[];
181
+ lang: string;
182
+ head: HeadConfig[];
182
183
  }
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
-
184
+ //#endregion
185
+ //#region src/utils/links/isLinkExternal.d.ts
206
186
  /**
207
187
  * Determine a link is external or not
208
188
  */
209
189
  declare const isLinkExternal: (link: string, base?: string) => boolean;
210
-
190
+ //#endregion
191
+ //#region src/utils/links/isLinkHttp.d.ts
211
192
  /**
212
193
  * Determine a link is http link or not
213
194
  *
@@ -216,56 +197,108 @@ declare const isLinkExternal: (link: string, base?: string) => boolean;
216
197
  * - //github.com
217
198
  */
218
199
  declare const isLinkHttp: (link: string) => boolean;
219
-
200
+ //#endregion
201
+ //#region src/utils/links/isLinkWithProtocol.d.ts
220
202
  /**
221
203
  * Determine a link has protocol or not
222
204
  */
223
205
  declare const isLinkWithProtocol: (link: string) => boolean;
224
-
206
+ //#endregion
207
+ //#region src/utils/routes/inferRoutePath.d.ts
225
208
  /**
226
- * Check if a value is plain object, with generic type support
209
+ * Infer route path of the given raw path
227
210
  */
228
- declare const isPlainObject: <T extends Record<any, any> = Record<any, any>>(val: unknown) => val is T;
229
-
211
+ declare const inferRoutePath: (rawPath: string) => string;
212
+ //#endregion
213
+ //#region src/utils/routes/normalizeRoutePath.d.ts
230
214
  /**
231
- * Normalize the given path to the final route path
215
+ * Normalize the given pathname path to the final route path
232
216
  */
233
- declare const normalizeRoutePath: (path: string) => string;
234
-
217
+ declare const normalizeRoutePath: (pathname: string, current?: string) => string;
218
+ //#endregion
219
+ //#region src/utils/routes/resolveLocalePath.d.ts
220
+ /**
221
+ * Resolve the matched locale path of route path
222
+ */
223
+ declare const resolveLocalePath: (locales: LocaleConfig, routePath: string) => string;
224
+ //#endregion
225
+ //#region src/utils/routes/resolveRoutePathFromUrl.d.ts
226
+ /**
227
+ * For a give URL, remove the origin and the site base to get the route path
228
+ */
229
+ declare const resolveRoutePathFromUrl: (url: string, base?: string) => string;
230
+ //#endregion
231
+ //#region src/utils/routes/splitPath.d.ts
232
+ /**
233
+ * Split a path into pathname and hashAndQueries
234
+ */
235
+ declare const splitPath: (path: string) => {
236
+ pathname: string;
237
+ hashAndQueries: string;
238
+ };
239
+ //#endregion
240
+ //#region src/utils/dedupeHead.d.ts
241
+ /**
242
+ * Dedupe head config with identifier
243
+ *
244
+ * Items that appear earlier have higher priority
245
+ */
246
+ declare const dedupeHead: (head: HeadConfig[]) => HeadConfig[];
247
+ //#endregion
248
+ //#region src/utils/ensureLeadingSlash.d.ts
249
+ /**
250
+ * Ensure a url string to have leading slash /
251
+ */
252
+ declare const ensureLeadingSlash: (str: string) => string;
253
+ //#endregion
254
+ //#region src/utils/ensureEndingSlash.d.ts
255
+ /**
256
+ * Ensure a url string to have ending slash /
257
+ */
258
+ declare const ensureEndingSlash: (str: string) => string;
259
+ //#endregion
260
+ //#region src/utils/formatDateString.d.ts
261
+ /**
262
+ * Format a date string to `yyyy-MM-dd`
263
+ */
264
+ declare const formatDateString: (str: string, defaultDateString?: string) => string;
265
+ //#endregion
266
+ //#region src/utils/omit.d.ts
235
267
  /**
236
268
  * Omit properties from an object
237
269
  */
238
270
  declare const omit: <T extends Record<string, unknown>, U extends string[]>(obj: T, ...keys: U) => Omit<T, U[number]>;
239
-
271
+ //#endregion
272
+ //#region src/utils/removeEndingSlash.d.ts
240
273
  /**
241
274
  * Remove ending slash / from a string
242
275
  */
243
276
  declare const removeEndingSlash: (str: string) => string;
244
-
277
+ //#endregion
278
+ //#region src/utils/removeLeadingSlash.d.ts
245
279
  /**
246
280
  * Remove leading slash / from a string
247
281
  */
248
282
  declare const removeLeadingSlash: (str: string) => string;
249
-
283
+ //#endregion
284
+ //#region src/utils/resolveHeadIdentifier.d.ts
250
285
  /**
251
286
  * Resolve identifier of a tag, to avoid duplicated tags in `<head>`
252
287
  */
253
288
  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
-
289
+ //#endregion
290
+ //#region src/utils/typeGuards.d.ts
262
291
  /**
263
292
  * Check if a value is a function
264
293
  */
265
294
  declare const isFunction: (val: unknown) => val is Function;
295
+ /**
296
+ * Check if a value is plain object, with generic type support
297
+ */
298
+ declare const isPlainObject: <T extends Record<any, any> = Record<any, any>>(val: unknown) => val is T;
266
299
  /**
267
300
  * Check if a value is a string
268
301
  */
269
302
  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 };
303
+ //#endregion
304
+ export { HeadAttrsConfig, HeadConfig, HeadTag, HeadTagEmpty, HeadTagNonEmpty, LocaleConfig, LocaleData, PageBase, PageData, PageFrontmatter, PageHeader, SiteData, SiteLocaleConfig, SiteLocaleData, 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.30",
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
  }