vuepress-plugin-md-power 1.0.0-rc.147 → 1.0.0-rc.149

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.
@@ -118,7 +118,7 @@ onMounted(() => {
118
118
  grid-column: span 2 / span 2;
119
119
  }
120
120
 
121
- .vp-code-tree .code-panel [class*="language-"] {
121
+ .vp-code-tree .code-panel div[class*="language-"] {
122
122
  flex: 1 2;
123
123
  margin: 16px 0 0;
124
124
  overflow: auto;
@@ -128,7 +128,7 @@ onMounted(() => {
128
128
 
129
129
  @media (min-width: 768px) {
130
130
  .vp-code-tree .code-tree-panel .vp-file-tree,
131
- .vp-code-tree .code-panel [class*="language-"] {
131
+ .vp-code-tree .code-panel div[class*="language-"] {
132
132
  overscroll-behavior: contain;
133
133
  }
134
134
  }
@@ -12,3 +12,12 @@ declare module '@internal/md-power/replEditorData' {
12
12
  const res: ReplEditorData
13
13
  export default res
14
14
  }
15
+
16
+ declare global {
17
+
18
+ const __MD_POWER_INJECT_OPTIONS__: MarkdownPowerPluginOptions
19
+ const __MD_POWER_DASHJS_INSTALLED__: boolean
20
+ const __MD_POWER_HLSJS_INSTALLED__: boolean
21
+ const __MD_POWER_MPEGTSJS_INSTALLED__: boolean
22
+
23
+ }
@@ -98,8 +98,16 @@ interface FileTreeOptions {
98
98
  }
99
99
 
100
100
  //#endregion
101
- //#region src/shared/icons.d.ts
102
- interface IconsOptions {
101
+ //#region src/shared/icon.d.ts
102
+ type IconOptions = IconifyProvider | IconFontProvider | FontAwesomeProvider;
103
+ interface IconProviderBase {
104
+ /**
105
+ * The provider of the icon
106
+ *
107
+ * 图标提供商
108
+ * @default 'iconify'
109
+ */
110
+ provider?: "iconify" | "iconfont" | "fontawesome";
103
111
  /**
104
112
  * The size of the icon
105
113
  * @default '1em'
@@ -111,6 +119,46 @@ interface IconsOptions {
111
119
  */
112
120
  color?: string;
113
121
  }
122
+ interface IconFontProvider extends IconProviderBase {
123
+ provider?: "iconfont";
124
+ /**
125
+ * The prefix of the iconfont
126
+ * @default 'iconfont icon-'
127
+ */
128
+ prefix?: string;
129
+ /**
130
+ * The assets of the iconfont
131
+ */
132
+ assets?: IconAssetLink | IconAssetLink[];
133
+ }
134
+ interface FontAwesomeProvider extends IconProviderBase {
135
+ provider?: "fontawesome";
136
+ /**
137
+ * The prefix of the fontawesome icon
138
+ * @default 'fas'
139
+ */
140
+ prefix?: LiteralUnion<FontAwesomePrefix>;
141
+ /**
142
+ * The assets of the fontawesome
143
+ * @default 'fontawesome'
144
+ */
145
+ assets?: FontAwesomeAssetBuiltIn | IconAssetLink | (IconAssetLink | FontAwesomeAssetBuiltIn)[];
146
+ }
147
+ interface IconifyProvider extends IconProviderBase {
148
+ provider?: "iconify";
149
+ /**
150
+ * The prefix of the icon
151
+ * @default ''
152
+ */
153
+ prefix?: LiteralUnion<IconifyPrefix>;
154
+ }
155
+ type FontAwesomeAssetBuiltIn = "fontawesome" | "fontawesome-with-brands";
156
+ type IconAssetLink = `//${string}` | `//${string}` | `https://${string}` | `http://${string}`;
157
+ type FontAwesomePrefix = "fas" | "s" | "far" | "r" | "fal" | "l" | "fat" | "t" | "fads" | "ds" | "fass" | "ss" | "fasr" | "sr" | "fasl" | "sl" | "fast" | "st" | "fasds" | "sds" | "fab" | "b";
158
+ type IconifyPrefix = "material-symbols" | "material-symbols-light" | "ic" | "mdi" | "mdi-light" | "line-md" | "solar" | "tabler" | "hugeicons" | "mingcute" | "ri" | "mynaui" | "iconamoon" | "iconoir" | "lucide" | "lucide-lab" | "uil" | "tdesign" | "si" | "bx" | "bxs" | "majesticons" | "gg" | "flowbite" | "basil" | "pixelarticons" | "pixel" | "akar-icons" | "ci" | "proicons" | "typcn" | "meteor-icons" | "prime" | "circum" | "fe" | "eos-icons" | "bitcoin-icons" | "humbleicons" | "uim" | "uit" | "uis" | "gridicons" | "mi" | "cuida" | "weui" | "duo-icons" | "svg-spinners" | "lets-icons" | "mage" | "stash" | "lineicons" | "icon-park-outline" | "icon-park-solid" | "icon-park-twotone" | "jam" | "guidance" | "carbon" | "ion" | "famicons" | "ant-design" | "lsicon" | "gravity-ui" | "cil" | "ep" | "charm" | "quill" | "bytesize" | "bi" | "rivet-icons" | "nimbus" | "formkit" | "fluent" | "ph" | "teenyicons" | "clarity" | "ix" | "octicon" | "memory" | "system-uicons" | "radix-icons" | "zondicons" | "uiw" | "maki" | "codex" | "ei" | "heroicons" | "pepicons-pop" | "pepicons-print" | "pepicons-pencil" | "f7" | "pajamas" | "garden" | "streamline" | "fa6-solid" | "fa6-regular" | "picon" | "ooui" | "oui" | "nrk" | "qlementine-icons" | "fluent-color" | "icon-park" | "marketeq" | "vscode-icons" | "codicon" | "material-icon-theme" | "file-icons" | "devicon" | "devicon-plain" | "catppuccin" | "skill-icons" | "unjs" | "simple-icons" | "logos" | "cib" | "fa6-brands" | "bxl" | "nonicons" | "arcticons" | "cbi" | "brandico" | "entypo-social" | "token" | "token-branded" | "cryptocurrency" | "cryptocurrency-color" | "openmoji" | "twemoji" | "noto" | "fluent-emoji" | "fluent-emoji-flat" | "fluent-emoji-high-contrast" | "noto-v1" | "emojione" | "emojione-monotone" | "emojione-v1" | "fxemoji" | "streamline-emojis" | "circle-flags" | "flag" | "flagpack" | "cif" | "gis" | "map" | "geo" | "game-icons" | "fad" | "academicons" | "wi" | "meteocons" | "healthicons" | "medical-icon" | "covid" | "la" | "eva" | "dashicons" | "flat-color-icons" | "entypo" | "foundation" | "raphael" | "icons8" | "iwwa" | "gala" | "heroicons-outline" | "heroicons-solid" | "fa-solid" | "fa-regular" | "fa-brands" | "fa" | "fluent-mdl2" | "fontisto" | "icomoon-free" | "subway" | "oi" | "wpf" | "simple-line-icons" | "et" | "el" | "vaadin" | "grommet-icons" | "whh" | "si-glyph" | "zmdi" | "ls" | "bpmn" | "flat-ui" | "vs" | "topcoat" | "il" | "websymbol" | "fontelico" | "ps" | "feather" | "mono-icons" | "pepicons";
159
+ type LiteralUnion<Union extends Base, Base = string> = Union | (Base & {
160
+ zz_IGNORE_ME?: never;
161
+ });
114
162
 
115
163
  //#endregion
116
164
  //#region src/shared/jsfiddle.d.ts
@@ -236,13 +284,23 @@ interface MarkdownPowerPluginOptions {
236
284
  */
237
285
  pdf?: boolean | PDFOptions;
238
286
  /**
287
+ * 是否启用 图标支持
288
+ * - iconify - `::collect:icon_name::` => `<VPIcon name="collect:icon_name" />`
289
+ * - iconfont - `::name::` => `<i class="iconfont icon-name"></i>`
290
+ * - fontawesome - `::fas:name::` => `<i class="fa-solid fa-name"></i>`
291
+ *
292
+ * @default false
293
+ */
294
+ icon?: IconOptions;
295
+ /**
239
296
  * 是否启用 iconify 图标嵌入语法
240
297
  *
241
298
  * `::collect:icon_name::`
242
299
  *
243
300
  * @default false
301
+ * @deprecated use `icon` instead 该配置已弃用,请使用 `icon` 代替
244
302
  */
245
- icons?: boolean | IconsOptions;
303
+ icons?: boolean | IconOptions;
246
304
  /**
247
305
  * 是否启用 隐秘文本 语法
248
306
  *
@@ -478,4 +536,4 @@ declare function resolveImageSize(app: App, url: string, remote?: boolean): Prom
478
536
  declare function markdownPowerPlugin(options?: MarkdownPowerPluginOptions): Plugin;
479
537
 
480
538
  //#endregion
481
- export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, IconsOptions, JSFiddleTokenMeta, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta, createCodeTabIconGetter, markdownPowerPlugin, resolveImageSize };
539
+ export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, FontAwesomeAssetBuiltIn, FontAwesomePrefix, FontAwesomeProvider, IconAssetLink, IconFontProvider, IconOptions, IconProviderBase, IconifyPrefix, IconifyProvider, JSFiddleTokenMeta, LiteralUnion, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta, createCodeTabIconGetter, markdownPowerPlugin, resolveImageSize };
package/lib/node/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { tab } from "@mdit/plugin-tab";
3
- import { addViteOptimizeDepsInclude, ensureEndingSlash, isArray, isLinkExternal, isLinkHttp, isPlainObject } from "@vuepress/helper";
3
+ import { addViteOptimizeDepsInclude, ensureEndingSlash, isArray, isLinkAbsolute, isLinkExternal, isLinkHttp, isPlainObject } from "@vuepress/helper";
4
4
  import { Buffer } from "node:buffer";
5
5
  import http from "node:https";
6
6
  import { URL, URLSearchParams } from "node:url";
7
- import { camelCase, isBoolean, isEmptyObject, isNull, isNumber, isString, isUndefined, kebabCase, withTimeout } from "@pengzhanbo/utils";
7
+ import { camelCase, isBoolean, isEmptyObject, isNull, isNumber, isPlainObject as isPlainObject$1, isString, isUndefined, kebabCase, notNullish, omit, toArray, uniqueBy, withTimeout } from "@pengzhanbo/utils";
8
8
  import imageSize from "image-size";
9
9
  import { colors, fs, getDirname, logger, path } from "vuepress/utils";
10
- import { isPackageExists, resolveModule } from "local-pkg";
11
10
  import path$1 from "node:path";
12
11
  import { globSync } from "tinyglobby";
13
- import { removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
12
+ import { isLinkHttp as isLinkHttp$1, removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
14
13
  import fs$1, { promises } from "node:fs";
15
14
  import process from "node:process";
16
15
  import container from "markdown-it-container";
16
+ import { isPackageExists, resolveModule } from "local-pkg";
17
17
  import { LRUCache } from "lru-cache";
18
18
  import { watch } from "chokidar";
19
19
  import { customAlphabet } from "nanoid";
@@ -917,7 +917,7 @@ const codeTabs = (md, options = {}) => {
917
917
  });
918
918
  const titlesContent = titles.map((title, index$1) => {
919
919
  const icon = getIcon(title);
920
- return `<template #title${index$1}="{ value, isActive }">${icon ? `<VPIcon name="${icon}"/>` : ""}<span>${title}</span></template>`;
920
+ return `<template #title${index$1}="{ value, isActive }">${icon ? `<VPIcon provider="iconify" name="${icon}"/>` : ""}<span>${title}</span></template>`;
921
921
  }).join("");
922
922
  return `<CodeTabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>${titlesContent}`;
923
923
  },
@@ -1379,7 +1379,7 @@ function codeTreePlugin(md, app, options = {}) {
1379
1379
  filepath: node.filepath
1380
1380
  };
1381
1381
  return `<FileTreeNode${stringifyAttrs(props)}>
1382
- <template #icon><VPIcon name="${getIcon(node.filename, props.type, mode)}" /></template>
1382
+ <template #icon><VPIcon provider="iconify" name="${getIcon(node.filename, props.type, mode)}" /></template>
1383
1383
  ${node.children?.length ? renderFileTree(node.children, mode) : ""}
1384
1384
  </FileTreeNode>`;
1385
1385
  }).join("\n");
@@ -1473,6 +1473,18 @@ const alignList = [
1473
1473
  ];
1474
1474
  function alignPlugin(md) {
1475
1475
  for (const name of alignList) createContainerPlugin(md, name, { before: () => `<div style="text-align:${name}">` });
1476
+ createContainerPlugin(md, "flex", { before: (info) => {
1477
+ const { attrs: attrs$1 } = resolveAttrs(info);
1478
+ const styles = ["margin:16px 0;display:flex"];
1479
+ const align = attrs$1.start ? "flex-start" : attrs$1.end ? "flex-end" : attrs$1.center ? "center" : "";
1480
+ const justify = attrs$1.between ? "space-between" : attrs$1.around ? "space-around" : attrs$1.center ? "center" : "";
1481
+ if (align) styles.push(`align-items:${align}`);
1482
+ if (justify) styles.push(`justify-content:${justify}`);
1483
+ if (attrs$1.column) styles.push("flex-direction:column");
1484
+ if (attrs$1.wrap) styles.push("flex-wrap:wrap");
1485
+ styles.push(`gap:${parseRect(attrs$1.gap || "16")}`);
1486
+ return `<div style="${styles.join(";")}">`;
1487
+ } });
1476
1488
  }
1477
1489
 
1478
1490
  //#endregion
@@ -1793,7 +1805,7 @@ function fileTreePlugin(md, options = {}) {
1793
1805
  });
1794
1806
  const nodeType = children.length > 0 ? "folder" : type;
1795
1807
  const renderedComment = comment ? `<template #comment>${md.renderInline(comment.replaceAll("#", "#"))}</template>` : "";
1796
- const renderedIcon = !isOmit ? `<template #icon><VPIcon name="${getIcon(filename, nodeType, meta.icon)}" /></template>` : "";
1808
+ const renderedIcon = !isOmit ? `<template #icon><VPIcon provider="iconify" name="${getIcon(filename, nodeType, meta.icon)}" /></template>` : "";
1797
1809
  const props = {
1798
1810
  expanded: nodeType === "folder" ? expanded : false,
1799
1811
  focus,
@@ -2313,7 +2325,7 @@ function timelinePlugin(md) {
2313
2325
  const attrs$1 = token.meta;
2314
2326
  attrs$1.card ??= void 0;
2315
2327
  const icon = attrs$1.icon;
2316
- return `<VPTimelineItem${stringifyAttrs(attrs$1, true)}>${icon ? `<template #icon><VPIcon name="${icon}"/></template>` : ""}`;
2328
+ return `<VPTimelineItem${stringifyAttrs(attrs$1, true)}>${icon ? `<template #icon><VPIcon provider="iconify" name="${icon}"/></template>` : ""}`;
2317
2329
  };
2318
2330
  md.renderer.rules.timeline_item_close = () => "</VPTimelineItem>";
2319
2331
  md.renderer.rules.timeline_item_title_open = () => "<template #title>";
@@ -3508,6 +3520,193 @@ function parseSource(source) {
3508
3520
  }
3509
3521
  }
3510
3522
 
3523
+ //#endregion
3524
+ //#region src/node/icon/createIconRule.ts
3525
+ function createIconRule([l1, l2, r1, r2], deprecated) {
3526
+ return (state, silent) => {
3527
+ let found = false;
3528
+ const max = state.posMax;
3529
+ const start = state.pos;
3530
+ if (state.src.charCodeAt(start) !== l1 || state.src.charCodeAt(start + 1) !== l2) return false;
3531
+ const next = state.src.charCodeAt(start + 2);
3532
+ if (next === 32 || next === 58) return false;
3533
+ /* istanbul ignore if -- @preserve */
3534
+ if (silent) return false;
3535
+ if (max - start < 5) return false;
3536
+ state.pos = start + 2;
3537
+ while (state.pos < max) {
3538
+ if (state.src.charCodeAt(state.pos) === r1 && state.src.charCodeAt(state.pos + 1) === r2) {
3539
+ found = true;
3540
+ break;
3541
+ }
3542
+ state.md.inline.skipToken(state);
3543
+ }
3544
+ if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
3545
+ state.pos = start;
3546
+ return false;
3547
+ }
3548
+ const info = state.src.slice(start + 2, state.pos);
3549
+ state.posMax = state.pos;
3550
+ state.pos = start + 2;
3551
+ const icon = state.push("icon", "i", 0);
3552
+ icon.markup = "::";
3553
+ icon.content = info;
3554
+ icon.meta = { deprecated };
3555
+ state.pos = state.posMax + 2;
3556
+ state.posMax = max;
3557
+ return true;
3558
+ };
3559
+ }
3560
+
3561
+ //#endregion
3562
+ //#region src/node/icon/resolveIcon.ts
3563
+ const RE_SIZE = /(?<=\s|^)=(.+?)(?:\s|$)/;
3564
+ const RE_COLOR = /(?<=\s|^)\/(.+?)(?:\s|$)/;
3565
+ const RE_PROVIDER = /^(iconify|iconfont|fontawesome)\s+/;
3566
+ const RE_EXTRA_KEY = /(?:^|-)\d-/g;
3567
+ function resolveIcon(content, options) {
3568
+ let size = options.size;
3569
+ let color = options.color;
3570
+ let provider = options.provider || "iconify";
3571
+ content = content.replace(RE_PROVIDER, (_, p) => {
3572
+ provider = p;
3573
+ return "";
3574
+ }).replace(RE_SIZE, (_, s) => {
3575
+ size = s;
3576
+ return "";
3577
+ }).replace(RE_COLOR, (_, c) => {
3578
+ color = c;
3579
+ return "";
3580
+ }).trim();
3581
+ const index = content.indexOf(" ");
3582
+ const name = index === -1 ? content : content.slice(0, index);
3583
+ const extra = index === -1 ? "" : content.slice(index + 1);
3584
+ const props = {
3585
+ provider,
3586
+ size,
3587
+ color,
3588
+ name
3589
+ };
3590
+ if (!extra) return props;
3591
+ const { attrs: attrs$1 } = resolveAttrs(extra);
3592
+ const info = [];
3593
+ const excludes = [];
3594
+ for (const key in attrs$1) if (attrs$1[key] === true) {
3595
+ excludes.push(key);
3596
+ info.push(kebabCase(key).replace(RE_EXTRA_KEY, (m) => `${m.slice(0, -1)}`));
3597
+ }
3598
+ return {
3599
+ ...props,
3600
+ extra: info.join(" "),
3601
+ ...omit(attrs$1, excludes)
3602
+ };
3603
+ }
3604
+
3605
+ //#endregion
3606
+ //#region src/node/icon/icon.ts
3607
+ function iconRender(content, options) {
3608
+ const icon = resolveIcon(content, options);
3609
+ return `<VPIcon${stringifyAttrs(icon)} />`;
3610
+ }
3611
+ const iconPlugin = (md, options = {}) => {
3612
+ /**
3613
+ * ::collect:icon_name =size /color::
3614
+ */
3615
+ md.inline.ruler.before(
3616
+ "link",
3617
+ "icon",
3618
+ // : : : :
3619
+ createIconRule([
3620
+ 58,
3621
+ 58,
3622
+ 58,
3623
+ 58
3624
+ ])
3625
+ );
3626
+ /**
3627
+ * :[collect:icon_name size/color]:
3628
+ * @deprecated
3629
+ */
3630
+ md.inline.ruler.before(
3631
+ "link",
3632
+ "icon_deprecated",
3633
+ // : [ ] :
3634
+ createIconRule([
3635
+ 58,
3636
+ 91,
3637
+ 93,
3638
+ 58
3639
+ ], true)
3640
+ );
3641
+ md.renderer.rules.icon = (tokens, idx, _, env) => {
3642
+ const { content, meta } = tokens[idx];
3643
+ let icon = content;
3644
+ /* istanbul ignore if -- @preserve */
3645
+ if (meta.deprecated) {
3646
+ const [name, opt = ""] = content.split(" ");
3647
+ const [size, color] = opt.trim().split("/");
3648
+ icon = `${name}${size ? ` =${size}` : ""}${color ? ` /${color}` : ""}`;
3649
+ console.warn(`The icon syntax of \`${colors.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors.green(`::${icon}::`)}\` instead. (${colors.gray(env.filePathRelative || env.filePath)})`);
3650
+ }
3651
+ return iconRender(icon, options);
3652
+ };
3653
+ };
3654
+
3655
+ //#endregion
3656
+ //#region src/node/icon/prepareIcon.ts
3657
+ function getFontAwesomeCDNLink(type) {
3658
+ return `https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/js/${type}.min.js`;
3659
+ }
3660
+ function prepareIcon(imports, options = {}) {
3661
+ const setupContent = [];
3662
+ const assets = [];
3663
+ if (options.provider === "iconfont") assets.push(...toArray(options.assets).map((asset) => normalizeAsset(asset)).filter(notNullish));
3664
+ else if (options.provider === "fontawesome") assets.push(...toArray(options.assets || "fontawesome").map((asset) => {
3665
+ if (asset === "fontawesome") return [
3666
+ "solid",
3667
+ "regular",
3668
+ "fontawesome"
3669
+ ].map(getFontAwesomeCDNLink).map((asset$1) => normalizeAsset(asset$1, "fontawesome"));
3670
+ if (asset === "fontawesome-with-brands") return normalizeAsset(getFontAwesomeCDNLink("brands"), "fontawesome");
3671
+ return null;
3672
+ }).flat().filter(notNullish));
3673
+ let hasStyle = false;
3674
+ let hasScript = false;
3675
+ for (const asset of uniqueBy(assets, (a, b) => a.link === b.link)) if (asset.type === "style") {
3676
+ hasStyle = true;
3677
+ setupContent.push(`useStyleTag('@import url("${asset.link}");')`);
3678
+ } else if (asset.type === "script") {
3679
+ hasScript = true;
3680
+ setupContent.push(asset.provide === "fontawesome" ? `useScriptTag("${asset.link}", () => {}, { attrs: { "data-auto-replace-svg": "nest" } })` : `useScriptTag("${asset.link}")`);
3681
+ }
3682
+ if (hasScript || hasStyle) {
3683
+ const exports = [];
3684
+ if (hasScript) exports.push("useScriptTag");
3685
+ if (hasStyle) exports.push("useStyleTag");
3686
+ imports.add(`import { ${exports.join(", ")} } from '@vueuse/core'`);
3687
+ }
3688
+ return setupContent.join("\n ");
3689
+ }
3690
+ function normalizeAsset(asset, provide) {
3691
+ const link = normalizeLink(asset);
3692
+ if (asset.endsWith(".js")) return {
3693
+ type: "script",
3694
+ link,
3695
+ provide
3696
+ };
3697
+ if (asset.endsWith(".css")) return {
3698
+ type: "style",
3699
+ link,
3700
+ provide
3701
+ };
3702
+ console.error(`[vuepress:icon] Can not recognize icon link: "${asset}"`);
3703
+ return null;
3704
+ }
3705
+ function normalizeLink(link) {
3706
+ if (isLinkHttp$1(link) || isLinkAbsolute(link)) return link;
3707
+ return `//${link}`;
3708
+ }
3709
+
3511
3710
  //#endregion
3512
3711
  //#region src/node/inline/abbr.ts
3513
3712
  const abbrPlugin = (md) => {
@@ -3665,107 +3864,6 @@ const annotationPlugin = (md) => {
3665
3864
  md.block.ruler.before("reference", "annotation", annotationDef, { alt: ["paragraph", "reference"] });
3666
3865
  };
3667
3866
 
3668
- //#endregion
3669
- //#region src/node/inline/icons.ts
3670
- function createIconRule([l1, l2, r1, r2], deprecated) {
3671
- return (state, silent) => {
3672
- let found = false;
3673
- const max = state.posMax;
3674
- const start = state.pos;
3675
- if (state.src.charCodeAt(start) !== l1 || state.src.charCodeAt(start + 1) !== l2) return false;
3676
- const next = state.src.charCodeAt(start + 2);
3677
- if (next === 32 || next === 58) return false;
3678
- /* istanbul ignore if -- @preserve */
3679
- if (silent) return false;
3680
- if (max - start < 5) return false;
3681
- state.pos = start + 2;
3682
- while (state.pos < max) {
3683
- if (state.src.charCodeAt(state.pos) === r1 && state.src.charCodeAt(state.pos + 1) === r2) {
3684
- found = true;
3685
- break;
3686
- }
3687
- state.md.inline.skipToken(state);
3688
- }
3689
- if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
3690
- state.pos = start;
3691
- return false;
3692
- }
3693
- const info = state.src.slice(start + 2, state.pos);
3694
- state.posMax = state.pos;
3695
- state.pos = start + 2;
3696
- const icon = state.push("icon", "i", 0);
3697
- icon.markup = "::";
3698
- icon.content = info;
3699
- icon.meta = { deprecated };
3700
- state.pos = state.posMax + 2;
3701
- state.posMax = max;
3702
- return true;
3703
- };
3704
- }
3705
- const RE_SIZE = /(?<=\s|^)=(.+?)(?:\s|$)/;
3706
- const RE_COLOR = /(?<=\s|^)\/(.+?)(?:\s|$)/;
3707
- function iconRender(content, options) {
3708
- let size = options.size;
3709
- let color = options.color;
3710
- content = content.replace(RE_SIZE, (_, s) => {
3711
- size = s;
3712
- return "";
3713
- }).replace(RE_COLOR, (_, c) => {
3714
- color = c;
3715
- return "";
3716
- }).trim();
3717
- const [name, ...extra] = content.split(/\s+/);
3718
- return `<VPIcon${stringifyAttrs({
3719
- name,
3720
- size,
3721
- color,
3722
- class: extra.length ? extra.join(" ") : void 0
3723
- })} />`;
3724
- }
3725
- const iconPlugin = (md, options = {}) => {
3726
- /**
3727
- * ::collect:icon_name =size /color::
3728
- */
3729
- md.inline.ruler.before(
3730
- "link",
3731
- "icon",
3732
- // : : : :
3733
- createIconRule([
3734
- 58,
3735
- 58,
3736
- 58,
3737
- 58
3738
- ])
3739
- );
3740
- /**
3741
- * :[collect:icon_name size/color]:
3742
- * @deprecated
3743
- */
3744
- md.inline.ruler.before(
3745
- "link",
3746
- "icon_deprecated",
3747
- // : [ ] :
3748
- createIconRule([
3749
- 58,
3750
- 91,
3751
- 93,
3752
- 58
3753
- ], true)
3754
- );
3755
- md.renderer.rules.icon = (tokens, idx, _, env) => {
3756
- const { content, meta } = tokens[idx];
3757
- let icon = content;
3758
- /* istanbul ignore if -- @preserve */
3759
- if (meta.deprecated) {
3760
- const [name, opt = ""] = content.split(" ");
3761
- const [size, color] = opt.trim().split("/");
3762
- icon = `${name}${size ? ` =${size}` : ""}${color ? ` /${color}` : ""}`;
3763
- console.warn(`The icon syntax of \`${colors.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors.green(`::${icon}::`)}\` instead. (${colors.gray(env.filePathRelative || env.filePath)})`);
3764
- }
3765
- return iconRender(icon, options);
3766
- };
3767
- };
3768
-
3769
3867
  //#endregion
3770
3868
  //#region src/node/inline/plot.ts
3771
3869
  const plotDef = (state, silent) => {
@@ -3831,7 +3929,6 @@ function inlineSyntaxPlugin(md, options) {
3831
3929
  * [HTML]: A HTML element description
3832
3930
  */
3833
3931
  md.use(abbrPlugin);
3834
- if (options.icons) md.use(iconPlugin, isPlainObject(options.icons) ? options.icons : {});
3835
3932
  if (options.plot === true || isPlainObject(options.plot) && options.plot.tag !== false) md.use(plotPlugin);
3836
3933
  }
3837
3934
 
@@ -3934,6 +4031,7 @@ async function prepareConfigFile(app, options) {
3934
4031
  imports.add(`import VPField from '${CLIENT_FOLDER}components/VPField.vue'`);
3935
4032
  enhances.add(`app.component('VPField', VPField)`);
3936
4033
  }
4034
+ const setupIcon = prepareIcon(imports, options.icon);
3937
4035
  return app.writeTemp("md-power/config.js", `\
3938
4036
  import { defineClientConfig } from 'vuepress/client'
3939
4037
  ${Array.from(imports.values()).join("\n")}
@@ -3943,23 +4041,39 @@ import '${CLIENT_FOLDER}styles/index.css'
3943
4041
  export default defineClientConfig({
3944
4042
  enhance({ router, app }) {
3945
4043
  ${Array.from(enhances.values()).map((item) => ` ${item}`).join("\n")}
4044
+ },
4045
+ setup() {
4046
+ ${setupIcon}
3946
4047
  }
3947
4048
  })
3948
4049
  `);
3949
4050
  }
3950
4051
 
4052
+ //#endregion
4053
+ //#region src/node/provideData.ts
4054
+ function provideData(options) {
4055
+ const mardownOptions = {
4056
+ plot: options.plot,
4057
+ pdf: options.pdf
4058
+ };
4059
+ const icon = options.icon ?? { provider: "iconify" };
4060
+ return {
4061
+ __MD_POWER_INJECT_OPTIONS__: mardownOptions,
4062
+ __MD_POWER_DASHJS_INSTALLED__: isPackageExists("dashjs"),
4063
+ __MD_POWER_HLSJS_INSTALLED__: isPackageExists("hls.js"),
4064
+ __MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists("mpegts.js"),
4065
+ __MD_POWER_ICON_PROVIDER__: icon.provider || "iconify",
4066
+ __MD_POWER_ICON_PREFIX__: icon.prefix || ""
4067
+ };
4068
+ }
4069
+
3951
4070
  //#endregion
3952
4071
  //#region src/node/plugin.ts
3953
4072
  function markdownPowerPlugin(options = {}) {
3954
4073
  return {
3955
4074
  name: "vuepress-plugin-md-power",
3956
4075
  clientConfigFile: (app) => prepareConfigFile(app, options),
3957
- define: {
3958
- __MD_POWER_INJECT_OPTIONS__: options,
3959
- __MD_POWER_DASHJS_INSTALLED__: isPackageExists("dashjs"),
3960
- __MD_POWER_HLSJS_INSTALLED__: isPackageExists("hls.js"),
3961
- __MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists("mpegts.js")
3962
- },
4076
+ define: provideData(options),
3963
4077
  extendsBundlerOptions(bundlerOptions, app) {
3964
4078
  if (options.repl) addViteOptimizeDepsInclude(bundlerOptions, app, [
3965
4079
  "shiki/core",
@@ -3977,6 +4091,7 @@ function markdownPowerPlugin(options = {}) {
3977
4091
  docsTitlePlugin(md);
3978
4092
  embedSyntaxPlugin(md, options);
3979
4093
  inlineSyntaxPlugin(md, options);
4094
+ iconPlugin(md, options.icon ?? (isPlainObject$1(options.icons) ? options.icons : {}));
3980
4095
  if (options.demo) demoPlugin(app, md);
3981
4096
  await containerPlugin(app, md, options);
3982
4097
  await imageSizePlugin(app, md, options.imageSize);
@@ -96,8 +96,16 @@ interface FileTreeOptions {
96
96
  }
97
97
 
98
98
  //#endregion
99
- //#region src/shared/icons.d.ts
100
- interface IconsOptions {
99
+ //#region src/shared/icon.d.ts
100
+ type IconOptions = IconifyProvider | IconFontProvider | FontAwesomeProvider;
101
+ interface IconProviderBase {
102
+ /**
103
+ * The provider of the icon
104
+ *
105
+ * 图标提供商
106
+ * @default 'iconify'
107
+ */
108
+ provider?: "iconify" | "iconfont" | "fontawesome";
101
109
  /**
102
110
  * The size of the icon
103
111
  * @default '1em'
@@ -109,6 +117,46 @@ interface IconsOptions {
109
117
  */
110
118
  color?: string;
111
119
  }
120
+ interface IconFontProvider extends IconProviderBase {
121
+ provider?: "iconfont";
122
+ /**
123
+ * The prefix of the iconfont
124
+ * @default 'iconfont icon-'
125
+ */
126
+ prefix?: string;
127
+ /**
128
+ * The assets of the iconfont
129
+ */
130
+ assets?: IconAssetLink | IconAssetLink[];
131
+ }
132
+ interface FontAwesomeProvider extends IconProviderBase {
133
+ provider?: "fontawesome";
134
+ /**
135
+ * The prefix of the fontawesome icon
136
+ * @default 'fas'
137
+ */
138
+ prefix?: LiteralUnion<FontAwesomePrefix>;
139
+ /**
140
+ * The assets of the fontawesome
141
+ * @default 'fontawesome'
142
+ */
143
+ assets?: FontAwesomeAssetBuiltIn | IconAssetLink | (IconAssetLink | FontAwesomeAssetBuiltIn)[];
144
+ }
145
+ interface IconifyProvider extends IconProviderBase {
146
+ provider?: "iconify";
147
+ /**
148
+ * The prefix of the icon
149
+ * @default ''
150
+ */
151
+ prefix?: LiteralUnion<IconifyPrefix>;
152
+ }
153
+ type FontAwesomeAssetBuiltIn = "fontawesome" | "fontawesome-with-brands";
154
+ type IconAssetLink = `//${string}` | `//${string}` | `https://${string}` | `http://${string}`;
155
+ type FontAwesomePrefix = "fas" | "s" | "far" | "r" | "fal" | "l" | "fat" | "t" | "fads" | "ds" | "fass" | "ss" | "fasr" | "sr" | "fasl" | "sl" | "fast" | "st" | "fasds" | "sds" | "fab" | "b";
156
+ type IconifyPrefix = "material-symbols" | "material-symbols-light" | "ic" | "mdi" | "mdi-light" | "line-md" | "solar" | "tabler" | "hugeicons" | "mingcute" | "ri" | "mynaui" | "iconamoon" | "iconoir" | "lucide" | "lucide-lab" | "uil" | "tdesign" | "si" | "bx" | "bxs" | "majesticons" | "gg" | "flowbite" | "basil" | "pixelarticons" | "pixel" | "akar-icons" | "ci" | "proicons" | "typcn" | "meteor-icons" | "prime" | "circum" | "fe" | "eos-icons" | "bitcoin-icons" | "humbleicons" | "uim" | "uit" | "uis" | "gridicons" | "mi" | "cuida" | "weui" | "duo-icons" | "svg-spinners" | "lets-icons" | "mage" | "stash" | "lineicons" | "icon-park-outline" | "icon-park-solid" | "icon-park-twotone" | "jam" | "guidance" | "carbon" | "ion" | "famicons" | "ant-design" | "lsicon" | "gravity-ui" | "cil" | "ep" | "charm" | "quill" | "bytesize" | "bi" | "rivet-icons" | "nimbus" | "formkit" | "fluent" | "ph" | "teenyicons" | "clarity" | "ix" | "octicon" | "memory" | "system-uicons" | "radix-icons" | "zondicons" | "uiw" | "maki" | "codex" | "ei" | "heroicons" | "pepicons-pop" | "pepicons-print" | "pepicons-pencil" | "f7" | "pajamas" | "garden" | "streamline" | "fa6-solid" | "fa6-regular" | "picon" | "ooui" | "oui" | "nrk" | "qlementine-icons" | "fluent-color" | "icon-park" | "marketeq" | "vscode-icons" | "codicon" | "material-icon-theme" | "file-icons" | "devicon" | "devicon-plain" | "catppuccin" | "skill-icons" | "unjs" | "simple-icons" | "logos" | "cib" | "fa6-brands" | "bxl" | "nonicons" | "arcticons" | "cbi" | "brandico" | "entypo-social" | "token" | "token-branded" | "cryptocurrency" | "cryptocurrency-color" | "openmoji" | "twemoji" | "noto" | "fluent-emoji" | "fluent-emoji-flat" | "fluent-emoji-high-contrast" | "noto-v1" | "emojione" | "emojione-monotone" | "emojione-v1" | "fxemoji" | "streamline-emojis" | "circle-flags" | "flag" | "flagpack" | "cif" | "gis" | "map" | "geo" | "game-icons" | "fad" | "academicons" | "wi" | "meteocons" | "healthicons" | "medical-icon" | "covid" | "la" | "eva" | "dashicons" | "flat-color-icons" | "entypo" | "foundation" | "raphael" | "icons8" | "iwwa" | "gala" | "heroicons-outline" | "heroicons-solid" | "fa-solid" | "fa-regular" | "fa-brands" | "fa" | "fluent-mdl2" | "fontisto" | "icomoon-free" | "subway" | "oi" | "wpf" | "simple-line-icons" | "et" | "el" | "vaadin" | "grommet-icons" | "whh" | "si-glyph" | "zmdi" | "ls" | "bpmn" | "flat-ui" | "vs" | "topcoat" | "il" | "websymbol" | "fontelico" | "ps" | "feather" | "mono-icons" | "pepicons";
157
+ type LiteralUnion<Union extends Base, Base = string> = Union | (Base & {
158
+ zz_IGNORE_ME?: never;
159
+ });
112
160
 
113
161
  //#endregion
114
162
  //#region src/shared/jsfiddle.d.ts
@@ -234,13 +282,23 @@ interface MarkdownPowerPluginOptions {
234
282
  */
235
283
  pdf?: boolean | PDFOptions;
236
284
  /**
285
+ * 是否启用 图标支持
286
+ * - iconify - `::collect:icon_name::` => `<VPIcon name="collect:icon_name" />`
287
+ * - iconfont - `::name::` => `<i class="iconfont icon-name"></i>`
288
+ * - fontawesome - `::fas:name::` => `<i class="fa-solid fa-name"></i>`
289
+ *
290
+ * @default false
291
+ */
292
+ icon?: IconOptions;
293
+ /**
237
294
  * 是否启用 iconify 图标嵌入语法
238
295
  *
239
296
  * `::collect:icon_name::`
240
297
  *
241
298
  * @default false
299
+ * @deprecated use `icon` instead 该配置已弃用,请使用 `icon` 代替
242
300
  */
243
- icons?: boolean | IconsOptions;
301
+ icons?: boolean | IconOptions;
244
302
  /**
245
303
  * 是否启用 隐秘文本 语法
246
304
  *
@@ -460,4 +518,4 @@ interface ArtPlayerTokenMeta extends SizeOptions {
460
518
  }
461
519
 
462
520
  //#endregion
463
- export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, IconsOptions, JSFiddleTokenMeta, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta };
521
+ export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, FontAwesomeAssetBuiltIn, FontAwesomePrefix, FontAwesomeProvider, IconAssetLink, IconFontProvider, IconOptions, IconProviderBase, IconifyPrefix, IconifyProvider, JSFiddleTokenMeta, LiteralUnion, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vuepress-plugin-md-power",
3
3
  "type": "module",
4
- "version": "1.0.0-rc.147",
4
+ "version": "1.0.0-rc.149",
5
5
  "description": "The Plugin for VuePress 2 - markdown power",
6
6
  "author": "pengzhanbo <volodymyr@foxmail.com>",
7
7
  "license": "MIT",
@@ -32,16 +32,16 @@
32
32
  ],
33
33
  "peerDependencies": {
34
34
  "artplayer": "^5.2.3",
35
- "dashjs": "^5.0.1",
35
+ "dashjs": "^5.0.2",
36
36
  "esbuild": "^0.25.4",
37
37
  "hls.js": "^1.6.2",
38
38
  "less": "^4.3.0",
39
39
  "markdown-it": "^14.1.0",
40
40
  "mpegts.js": "^1.7.3",
41
- "sass": "^1.88.0",
42
- "sass-embedded": "^1.88.0",
41
+ "sass": "^1.89.0",
42
+ "sass-embedded": "^1.89.0",
43
43
  "stylus": "^0.64.0",
44
- "vuepress": "2.0.0-rc.22"
44
+ "vuepress": "2.0.0-rc.23"
45
45
  },
46
46
  "peerDependenciesMeta": {
47
47
  "artplayer": {
@@ -69,24 +69,24 @@
69
69
  "@mdit/plugin-tab": "^0.18.0",
70
70
  "@mdit/plugin-tasklist": "^0.18.0",
71
71
  "@pengzhanbo/utils": "^2.1.0",
72
- "@vuepress/helper": "2.0.0-rc.99",
73
- "@vueuse/core": "^13.1.0",
72
+ "@vuepress/helper": "2.0.0-rc.105",
73
+ "@vueuse/core": "^13.2.0",
74
74
  "chokidar": "3.6.0",
75
75
  "image-size": "^2.0.2",
76
76
  "local-pkg": "^1.1.1",
77
77
  "lru-cache": "^11.1.0",
78
78
  "markdown-it-container": "^4.0.0",
79
79
  "nanoid": "^5.1.5",
80
- "shiki": "^3.4.0",
80
+ "shiki": "^3.4.2",
81
81
  "tinyglobby": "0.2.13",
82
- "tm-grammars": "^1.23.18",
82
+ "tm-grammars": "^1.23.21",
83
83
  "tm-themes": "^1.10.6",
84
- "vue": "^3.5.13"
84
+ "vue": "^3.5.14"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@types/markdown-it": "^14.1.2",
88
88
  "artplayer": "^5.2.3",
89
- "dashjs": "^5.0.1",
89
+ "dashjs": "^5.0.2",
90
90
  "hls.js": "^1.6.2",
91
91
  "mpegts.js": "1.7.3"
92
92
  },