vuepress-plugin-md-power 1.0.0-rc.143 → 1.0.0-rc.145
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 +10 -10
- package/lib/client/components/CanIUse.vue +4 -4
- package/lib/client/components/FileTreeNode.vue +229 -0
- package/lib/client/components/VPField.vue +94 -0
- package/lib/client/composables/demo.js +3 -3
- package/lib/node/index.d.ts +7 -1
- package/lib/node/index.js +460 -440
- package/lib/shared/index.d.ts +7 -1
- package/package.json +18 -18
- package/lib/client/components/FileTreeItem.vue +0 -183
package/lib/node/index.js
CHANGED
|
@@ -816,14 +816,14 @@ var definitions = {
|
|
|
816
816
|
};
|
|
817
817
|
|
|
818
818
|
// src/node/fileIcons/findIcon.ts
|
|
819
|
-
function getFileIcon(fileName,
|
|
820
|
-
const name = getFileIconName(fileName,
|
|
819
|
+
function getFileIcon(fileName, type) {
|
|
820
|
+
const name = getFileIconName(fileName, type);
|
|
821
821
|
if (!name)
|
|
822
|
-
return
|
|
822
|
+
return type !== "folder" ? defaultFile : defaultFolder;
|
|
823
823
|
return name;
|
|
824
824
|
}
|
|
825
|
-
function getFileIconName(fileName,
|
|
826
|
-
if (
|
|
825
|
+
function getFileIconName(fileName, type = "file") {
|
|
826
|
+
if (type === "folder") {
|
|
827
827
|
const icon2 = definitions.folders[fileName];
|
|
828
828
|
if (icon2)
|
|
829
829
|
return icon2;
|
|
@@ -921,10 +921,10 @@ var codeTabs = (md, options = {}) => {
|
|
|
921
921
|
tabOpenRenderer: ({ index }, tokens, tokenIndex) => {
|
|
922
922
|
let foundFence = false;
|
|
923
923
|
for (let i = tokenIndex; i < tokens.length; i++) {
|
|
924
|
-
const { type
|
|
925
|
-
if (
|
|
924
|
+
const { type } = tokens[i];
|
|
925
|
+
if (type === "code-tabs_tab_close")
|
|
926
926
|
break;
|
|
927
|
-
if ((
|
|
927
|
+
if ((type === "fence" || type === "import_code") && !foundFence) {
|
|
928
928
|
foundFence = true;
|
|
929
929
|
continue;
|
|
930
930
|
}
|
|
@@ -946,6 +946,7 @@ import imageSize from "image-size";
|
|
|
946
946
|
import { fs, logger, path } from "vuepress/utils";
|
|
947
947
|
|
|
948
948
|
// src/node/utils/resolveAttrs.ts
|
|
949
|
+
import { camelCase } from "@pengzhanbo/utils";
|
|
949
950
|
var RE_ATTR_VALUE = /(?:^|\s+)(?<attr>[\w-]+)(?:=\s*(?<quote>['"])(?<value>.+?)\k<quote>)?(?:\s+|$)/;
|
|
950
951
|
function resolveAttrs(info) {
|
|
951
952
|
info = info.trim();
|
|
@@ -955,23 +956,15 @@ function resolveAttrs(info) {
|
|
|
955
956
|
const rawAttrs = info;
|
|
956
957
|
let matched;
|
|
957
958
|
while (matched = info.match(RE_ATTR_VALUE)) {
|
|
958
|
-
const { attr, value } = matched.groups;
|
|
959
|
-
|
|
959
|
+
const { attr, value = true } = matched.groups;
|
|
960
|
+
let v = typeof value === "string" ? value.trim() : value;
|
|
961
|
+
if (v === "true")
|
|
962
|
+
v = true;
|
|
963
|
+
else if (v === "false")
|
|
964
|
+
v = false;
|
|
965
|
+
attrs2[camelCase(attr)] = v;
|
|
960
966
|
info = info.slice(matched[0].length);
|
|
961
967
|
}
|
|
962
|
-
Object.keys(attrs2).forEach((key) => {
|
|
963
|
-
let value = attrs2[key];
|
|
964
|
-
value = typeof value === "string" ? value.trim() : value;
|
|
965
|
-
if (value === "true")
|
|
966
|
-
value = true;
|
|
967
|
-
else if (value === "false")
|
|
968
|
-
value = false;
|
|
969
|
-
attrs2[key] = value;
|
|
970
|
-
if (key.includes("-")) {
|
|
971
|
-
const _key = key.replace(/-(\w)/g, (_, c) => c.toUpperCase());
|
|
972
|
-
attrs2[_key] = value;
|
|
973
|
-
}
|
|
974
|
-
});
|
|
975
968
|
return { attrs: attrs2, rawAttrs };
|
|
976
969
|
}
|
|
977
970
|
|
|
@@ -987,10 +980,10 @@ var BADGE_LIST = [
|
|
|
987
980
|
"https://vercel.com/button"
|
|
988
981
|
];
|
|
989
982
|
var cache = /* @__PURE__ */ new Map();
|
|
990
|
-
async function imageSizePlugin(app, md,
|
|
991
|
-
if (!app.env.isBuild || !
|
|
983
|
+
async function imageSizePlugin(app, md, type = false) {
|
|
984
|
+
if (!app.env.isBuild || !type)
|
|
992
985
|
return;
|
|
993
|
-
if (
|
|
986
|
+
if (type === "all") {
|
|
994
987
|
const start = performance.now();
|
|
995
988
|
try {
|
|
996
989
|
await scanRemoteImageSize(app);
|
|
@@ -1158,17 +1151,63 @@ import { isPlainObject as isPlainObject2 } from "@vuepress/helper";
|
|
|
1158
1151
|
|
|
1159
1152
|
// src/node/container/createContainer.ts
|
|
1160
1153
|
import container from "markdown-it-container";
|
|
1161
|
-
function createContainerPlugin(md,
|
|
1154
|
+
function createContainerPlugin(md, type, { before, after } = {}) {
|
|
1162
1155
|
const render = (tokens, index, options, env) => {
|
|
1163
1156
|
const token = tokens[index];
|
|
1164
|
-
const info = token.info.trim().slice(
|
|
1157
|
+
const info = token.info.trim().slice(type.length).trim() || "";
|
|
1165
1158
|
if (token.nesting === 1) {
|
|
1166
|
-
return before?.(info, tokens, index, options, env)
|
|
1159
|
+
return before?.(info, tokens, index, options, env) ?? `<div class="custom-container ${type}">`;
|
|
1167
1160
|
} else {
|
|
1168
|
-
return after?.(info, tokens, index, options, env)
|
|
1161
|
+
return after?.(info, tokens, index, options, env) ?? "</div>";
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
md.use(container, type, { render });
|
|
1165
|
+
}
|
|
1166
|
+
function createContainerSyntaxPlugin(md, type, render) {
|
|
1167
|
+
const maker = ":";
|
|
1168
|
+
const markerMinLen = 3;
|
|
1169
|
+
function defineContainer(state, startLine, endLine, silent) {
|
|
1170
|
+
const start = state.bMarks[startLine] + state.tShift[startLine];
|
|
1171
|
+
const max = state.eMarks[startLine];
|
|
1172
|
+
let pos = start;
|
|
1173
|
+
if (state.src[pos] !== maker)
|
|
1174
|
+
return false;
|
|
1175
|
+
pos += markerMinLen;
|
|
1176
|
+
for (pos = start + 1; pos <= max; pos++) {
|
|
1177
|
+
if (state.src[pos] !== maker)
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
if (pos - start < markerMinLen)
|
|
1181
|
+
return false;
|
|
1182
|
+
const markup = state.src.slice(start, pos);
|
|
1183
|
+
const info = state.src.slice(pos, max).trim();
|
|
1184
|
+
if (!info.startsWith(type))
|
|
1185
|
+
return false;
|
|
1186
|
+
if (silent)
|
|
1187
|
+
return true;
|
|
1188
|
+
let line = startLine;
|
|
1189
|
+
let content = "";
|
|
1190
|
+
while (++line < endLine) {
|
|
1191
|
+
if (state.src.slice(state.bMarks[line], state.eMarks[line]).trim() === markup) {
|
|
1192
|
+
break;
|
|
1193
|
+
}
|
|
1194
|
+
content += `${state.src.slice(state.bMarks[line], state.eMarks[line])}
|
|
1195
|
+
`;
|
|
1169
1196
|
}
|
|
1197
|
+
const token = state.push(`${type}_container`, "", 0);
|
|
1198
|
+
token.meta = resolveAttrs(info.slice(type.length)).attrs;
|
|
1199
|
+
token.content = content;
|
|
1200
|
+
token.markup = `${markup} ${type}`;
|
|
1201
|
+
token.map = [startLine, line + 1];
|
|
1202
|
+
state.line = line + 1;
|
|
1203
|
+
return true;
|
|
1204
|
+
}
|
|
1205
|
+
const defaultRender = (tokens, index) => {
|
|
1206
|
+
const { content } = tokens[index];
|
|
1207
|
+
return `<div class="custom-container ${type}">${content}</div>`;
|
|
1170
1208
|
};
|
|
1171
|
-
md.
|
|
1209
|
+
md.block.ruler.before("fence", `${type}_definition`, defineContainer);
|
|
1210
|
+
md.renderer.rules[`${type}_container`] = render ?? defaultRender;
|
|
1172
1211
|
}
|
|
1173
1212
|
|
|
1174
1213
|
// src/node/container/align.ts
|
|
@@ -1181,13 +1220,37 @@ function alignPlugin(md) {
|
|
|
1181
1220
|
}
|
|
1182
1221
|
}
|
|
1183
1222
|
|
|
1223
|
+
// src/node/utils/stringifyAttrs.ts
|
|
1224
|
+
import { isBoolean, isNull, isNumber, isString, isUndefined, kebabCase } from "@pengzhanbo/utils";
|
|
1225
|
+
function stringifyAttrs(attrs2, withUndefined = false) {
|
|
1226
|
+
const result = Object.entries(attrs2).map(([key, value]) => {
|
|
1227
|
+
const k = kebabCase(key);
|
|
1228
|
+
if (isUndefined(value) || value === "undefined")
|
|
1229
|
+
return withUndefined ? `:${k}="undefined"` : "";
|
|
1230
|
+
if (isNull(value) || value === "null")
|
|
1231
|
+
return withUndefined ? `:${k}="null"` : "";
|
|
1232
|
+
if (value === "true")
|
|
1233
|
+
value = true;
|
|
1234
|
+
if (value === "false")
|
|
1235
|
+
value = false;
|
|
1236
|
+
if (isBoolean(value))
|
|
1237
|
+
return value ? `${k}` : "";
|
|
1238
|
+
if (isNumber(value))
|
|
1239
|
+
return `:${k}="${value}"`;
|
|
1240
|
+
if (isString(value) && (value[0] === "{" || value[0] === "["))
|
|
1241
|
+
return `:${k}="${value.replaceAll('"', "'")}"`;
|
|
1242
|
+
const hasDynamic = key[0] === ":";
|
|
1243
|
+
return `${hasDynamic ? ":" : ""}${k}="${String(value)}"`;
|
|
1244
|
+
}).filter(Boolean).join(" ");
|
|
1245
|
+
return result ? ` ${result}` : "";
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1184
1248
|
// src/node/container/card.ts
|
|
1185
1249
|
function cardPlugin(md) {
|
|
1186
1250
|
createContainerPlugin(md, "card", {
|
|
1187
1251
|
before(info) {
|
|
1188
1252
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1189
|
-
|
|
1190
|
-
return `<VPCard${title ? ` title="${title}"` : ""}${icon ? ` icon="${icon}"` : ""}>`;
|
|
1253
|
+
return `<VPCard${stringifyAttrs(attrs2)}>`;
|
|
1191
1254
|
},
|
|
1192
1255
|
after: () => "</VPCard>"
|
|
1193
1256
|
});
|
|
@@ -1198,63 +1261,17 @@ function cardPlugin(md) {
|
|
|
1198
1261
|
createContainerPlugin(md, "card-masonry", {
|
|
1199
1262
|
before: (info) => {
|
|
1200
1263
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
return `<VPCardMasonry${cols ? ` :cols="${cols}"` : ""}${gap >= 0 ? ` :gap="${gap}"` : ""}>`;
|
|
1264
|
+
if (attrs2.cols)
|
|
1265
|
+
attrs2.cols = attrs2.cols[0] === "{" ? attrs2.cols : Number.parseInt(`${attrs2.cols}`);
|
|
1266
|
+
if (attrs2.gap)
|
|
1267
|
+
attrs2.gap = Number(attrs2.gap);
|
|
1268
|
+
return `<VPCardMasonry${stringifyAttrs(attrs2)}>`;
|
|
1207
1269
|
},
|
|
1208
1270
|
after: () => "</VPCardMasonry>"
|
|
1209
1271
|
});
|
|
1210
1272
|
}
|
|
1211
1273
|
|
|
1212
1274
|
// src/node/container/chat.ts
|
|
1213
|
-
var chatPlugin = (md) => {
|
|
1214
|
-
md.block.ruler.before("fence", "chat_def", chatDef);
|
|
1215
|
-
md.renderer.rules.chat_container = (tokens, idx, _, env) => {
|
|
1216
|
-
const { meta, content } = tokens[idx];
|
|
1217
|
-
const { title } = meta;
|
|
1218
|
-
const messages = parseChatContent(content);
|
|
1219
|
-
return `<div class="vp-chat">
|
|
1220
|
-
<div class="vp-chat-header">
|
|
1221
|
-
<p class="vp-chat-title">${title || "Chat"}</p>
|
|
1222
|
-
</div>
|
|
1223
|
-
<div class="vp-chat-content">
|
|
1224
|
-
${chatMessagesRender(md, env, messages)}
|
|
1225
|
-
</div>
|
|
1226
|
-
</div>`;
|
|
1227
|
-
};
|
|
1228
|
-
};
|
|
1229
|
-
function chatDef(state, startLine, endLine, silent) {
|
|
1230
|
-
const start = state.bMarks[startLine] + state.tShift[startLine];
|
|
1231
|
-
const max = state.eMarks[startLine];
|
|
1232
|
-
let pos = start;
|
|
1233
|
-
if (state.src.slice(pos, pos + 3) !== ":::")
|
|
1234
|
-
return false;
|
|
1235
|
-
pos += 3;
|
|
1236
|
-
const info = state.src.slice(start + 3, max).trim();
|
|
1237
|
-
if (!info.startsWith("chat"))
|
|
1238
|
-
return false;
|
|
1239
|
-
if (silent)
|
|
1240
|
-
return true;
|
|
1241
|
-
let line = startLine;
|
|
1242
|
-
let content = "";
|
|
1243
|
-
while (++line < endLine) {
|
|
1244
|
-
if (state.src.slice(state.bMarks[line], state.eMarks[line]).trim() === ":::") {
|
|
1245
|
-
break;
|
|
1246
|
-
}
|
|
1247
|
-
content += `${state.src.slice(state.bMarks[line], state.eMarks[line])}
|
|
1248
|
-
`;
|
|
1249
|
-
}
|
|
1250
|
-
const token = state.push("chat_container", "", 0);
|
|
1251
|
-
token.meta = resolveAttrs(info).attrs;
|
|
1252
|
-
token.content = content;
|
|
1253
|
-
token.markup = "::: chat";
|
|
1254
|
-
token.map = [startLine, line + 1];
|
|
1255
|
-
state.line = line + 1;
|
|
1256
|
-
return true;
|
|
1257
|
-
}
|
|
1258
1275
|
function chatMessagesRender(md, env, messages) {
|
|
1259
1276
|
let currentDate = "";
|
|
1260
1277
|
return messages.map(({ sender, username, date, content }) => {
|
|
@@ -1303,6 +1320,18 @@ function parseChatContent(content) {
|
|
|
1303
1320
|
}
|
|
1304
1321
|
return messages;
|
|
1305
1322
|
}
|
|
1323
|
+
var chatPlugin = (md) => createContainerSyntaxPlugin(
|
|
1324
|
+
md,
|
|
1325
|
+
"chat",
|
|
1326
|
+
(tokens, idx, _, env) => `<div class="vp-chat">
|
|
1327
|
+
<div class="vp-chat-header">
|
|
1328
|
+
<p class="vp-chat-title">${tokens[idx].meta?.title || "Chat"}</p>
|
|
1329
|
+
</div>
|
|
1330
|
+
<div class="vp-chat-content">
|
|
1331
|
+
${chatMessagesRender(md, env, parseChatContent(tokens[idx].content))}
|
|
1332
|
+
</div>
|
|
1333
|
+
</div>`
|
|
1334
|
+
);
|
|
1306
1335
|
|
|
1307
1336
|
// src/node/container/collapse.ts
|
|
1308
1337
|
function collapsePlugin(md) {
|
|
@@ -1311,14 +1340,14 @@ function collapsePlugin(md) {
|
|
|
1311
1340
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1312
1341
|
const idx = parseCollapse(tokens, index, attrs2);
|
|
1313
1342
|
const { accordion } = attrs2;
|
|
1314
|
-
return `<VPCollapse${
|
|
1343
|
+
return `<VPCollapse${stringifyAttrs({ accordion, index: idx })}>`;
|
|
1315
1344
|
},
|
|
1316
1345
|
after: () => `</VPCollapse>`
|
|
1317
1346
|
});
|
|
1318
1347
|
md.renderer.rules.collapse_item_open = (tokens, idx) => {
|
|
1319
1348
|
const token = tokens[idx];
|
|
1320
1349
|
const { expand, index } = token.meta;
|
|
1321
|
-
return `<VPCollapseItem${
|
|
1350
|
+
return `<VPCollapseItem${stringifyAttrs({ expand, index })}>`;
|
|
1322
1351
|
};
|
|
1323
1352
|
md.renderer.rules.collapse_item_close = () => "</VPCollapseItem>";
|
|
1324
1353
|
md.renderer.rules.collapse_item_title_open = () => "<template #title>";
|
|
@@ -1419,181 +1448,144 @@ function demoWrapperPlugin(md) {
|
|
|
1419
1448
|
});
|
|
1420
1449
|
}
|
|
1421
1450
|
|
|
1451
|
+
// src/node/container/field.ts
|
|
1452
|
+
import { isUndefined as isUndefined2 } from "@pengzhanbo/utils";
|
|
1453
|
+
function fieldPlugin(md) {
|
|
1454
|
+
createContainerPlugin(md, "field", {
|
|
1455
|
+
before: (info) => {
|
|
1456
|
+
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1457
|
+
const { name, type, required, optional, default: defaultValue } = attrs2;
|
|
1458
|
+
const props = stringifyAttrs({ name, required, optional });
|
|
1459
|
+
return `<VPField${props}${!isUndefined2(type) ? ` type="${type}"` : ""}${!isUndefined2(defaultValue) ? ` default-value="${defaultValue}"` : ""}>`;
|
|
1460
|
+
},
|
|
1461
|
+
after: () => "</VPField>"
|
|
1462
|
+
});
|
|
1463
|
+
createContainerPlugin(md, "field-group", {
|
|
1464
|
+
before: () => '<div class="vp-field-group">'
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1422
1468
|
// src/node/container/fileTree.ts
|
|
1423
|
-
import
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1469
|
+
import { removeEndingSlash } from "vuepress/shared";
|
|
1470
|
+
function parseFileTreeRawContent(content) {
|
|
1471
|
+
const root = { info: "", level: -1, children: [] };
|
|
1472
|
+
const stack = [root];
|
|
1473
|
+
const lines = content.trim().split("\n");
|
|
1474
|
+
for (const line of lines) {
|
|
1475
|
+
const match = line.match(/^(\s*)-(.*)$/);
|
|
1476
|
+
if (!match)
|
|
1477
|
+
continue;
|
|
1478
|
+
const level = Math.floor(match[1].length / 2);
|
|
1479
|
+
const info = match[2].trim();
|
|
1480
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= level) {
|
|
1481
|
+
stack.pop();
|
|
1482
|
+
}
|
|
1483
|
+
const parent = stack[stack.length - 1];
|
|
1484
|
+
const node = { info, level, children: [] };
|
|
1485
|
+
parent.children.push(node);
|
|
1486
|
+
stack.push(node);
|
|
1487
|
+
}
|
|
1488
|
+
return root.children;
|
|
1489
|
+
}
|
|
1490
|
+
var RE_FOCUS = /^\*\*(.*)\*\*(?:$|\s+)/;
|
|
1491
|
+
function parseFileTreeNodeInfo(info) {
|
|
1492
|
+
let filename = "";
|
|
1493
|
+
let comment = "";
|
|
1494
|
+
let focus = false;
|
|
1495
|
+
let expanded = true;
|
|
1496
|
+
let type = "file";
|
|
1497
|
+
let diff;
|
|
1498
|
+
if (info.startsWith("++")) {
|
|
1499
|
+
info = info.slice(2).trim();
|
|
1500
|
+
diff = "add";
|
|
1501
|
+
} else if (info.startsWith("--")) {
|
|
1502
|
+
info = info.slice(2).trim();
|
|
1503
|
+
diff = "remove";
|
|
1504
|
+
}
|
|
1505
|
+
info = info.replace(RE_FOCUS, (_, matched) => {
|
|
1506
|
+
filename = matched;
|
|
1507
|
+
focus = true;
|
|
1508
|
+
return "";
|
|
1509
|
+
});
|
|
1510
|
+
if (filename === "" && !focus) {
|
|
1511
|
+
const spaceIndex = info.indexOf(" ");
|
|
1512
|
+
filename = info.slice(0, spaceIndex === -1 ? info.length : spaceIndex);
|
|
1513
|
+
info = spaceIndex === -1 ? "" : info.slice(spaceIndex);
|
|
1514
|
+
}
|
|
1515
|
+
comment = info.trim();
|
|
1516
|
+
if (filename.endsWith("/")) {
|
|
1517
|
+
type = "folder";
|
|
1518
|
+
expanded = false;
|
|
1519
|
+
filename = removeEndingSlash(filename);
|
|
1520
|
+
}
|
|
1521
|
+
return { filename, comment, focus, expanded, type, diff };
|
|
1522
|
+
}
|
|
1431
1523
|
function fileTreePlugin(md, options = {}) {
|
|
1432
|
-
const getIcon = (filename,
|
|
1524
|
+
const getIcon = (filename, type, mode) => {
|
|
1433
1525
|
mode ||= options.icon || "colored";
|
|
1434
1526
|
if (mode === "simple")
|
|
1435
|
-
return
|
|
1436
|
-
return getFileIcon(filename,
|
|
1527
|
+
return type === "folder" ? defaultFolder : defaultFile;
|
|
1528
|
+
return getFileIcon(filename, type);
|
|
1437
1529
|
};
|
|
1438
|
-
const
|
|
1439
|
-
const {
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
} else {
|
|
1470
|
-
return "</div>";
|
|
1471
|
-
}
|
|
1472
|
-
};
|
|
1473
|
-
md.use(container2, type, { render });
|
|
1474
|
-
}
|
|
1475
|
-
function resolveTreeNodeInfo(tokens, current, idx) {
|
|
1476
|
-
let hasInline = false;
|
|
1477
|
-
let hasChildren = false;
|
|
1478
|
-
let inline;
|
|
1479
|
-
for (let i = idx + 1; !(tokens[i].level === current.level && tokens[i].type === "list_item_close"); ++i) {
|
|
1480
|
-
if (tokens[i].type === "inline" && !hasInline) {
|
|
1481
|
-
inline = tokens[i];
|
|
1482
|
-
hasInline = true;
|
|
1483
|
-
} else if (tokens[i].tag === "ul") {
|
|
1484
|
-
hasChildren = true;
|
|
1485
|
-
}
|
|
1486
|
-
if (hasInline && hasChildren)
|
|
1487
|
-
break;
|
|
1488
|
-
}
|
|
1489
|
-
if (!hasInline)
|
|
1490
|
-
return void 0;
|
|
1491
|
-
const children = inline.children.filter((token) => token.type === "text" && token.content || token.tag === "strong");
|
|
1492
|
-
const filename = children.filter((token) => token.type === "text").map((token) => token.content).join(" ").split(/\s+/)[0];
|
|
1493
|
-
const focus = children[0]?.tag === "strong";
|
|
1494
|
-
const type2 = hasChildren || filename.endsWith("/") ? "folder" : "file";
|
|
1495
|
-
const info = {
|
|
1496
|
-
filename: removeLeadingSlash(removeEndingSlash(filename)),
|
|
1497
|
-
type: type2,
|
|
1498
|
-
focus,
|
|
1499
|
-
empty: !hasChildren,
|
|
1500
|
-
expanded: type2 === "folder" && !filename.endsWith("/")
|
|
1501
|
-
};
|
|
1502
|
-
return [info, inline];
|
|
1503
|
-
}
|
|
1504
|
-
function updateInlineToken(inline, info, icon) {
|
|
1505
|
-
const children = inline.children;
|
|
1506
|
-
const tokens = [];
|
|
1507
|
-
const wrapperOpen = new Token("span_open", "span", 1);
|
|
1508
|
-
const wrapperClose = new Token("span_close", "span", -1);
|
|
1509
|
-
wrapperOpen.attrSet("class", `tree-node ${info.type}`);
|
|
1510
|
-
tokens.push(wrapperOpen);
|
|
1511
|
-
if (info.filename !== "..." && info.filename !== "\u2026") {
|
|
1512
|
-
const iconOpen = new Token("vp_iconify_open", "VPIcon", 1);
|
|
1513
|
-
iconOpen.attrSet("name", icon);
|
|
1514
|
-
const iconClose = new Token("vp_iconify_close", "VPIcon", -1);
|
|
1515
|
-
tokens.push(iconOpen, iconClose);
|
|
1516
|
-
}
|
|
1517
|
-
const fileOpen = new Token("span_open", "span", 1);
|
|
1518
|
-
fileOpen.attrSet("class", `name${info.focus ? " focus" : ""}`);
|
|
1519
|
-
tokens.push(fileOpen);
|
|
1520
|
-
let isStrongTag = false;
|
|
1521
|
-
while (children.length) {
|
|
1522
|
-
const token = children.shift();
|
|
1523
|
-
if (token.type === "text" && token.content) {
|
|
1524
|
-
if (token.content.includes(" ")) {
|
|
1525
|
-
const [first, ...other] = token.content.split(" ");
|
|
1526
|
-
const text = new Token("text", "", 0);
|
|
1527
|
-
text.content = removeEndingSlash(first);
|
|
1528
|
-
tokens.push(text);
|
|
1529
|
-
const comment = new Token("text", "", 0);
|
|
1530
|
-
comment.content = other.join(" ");
|
|
1531
|
-
children.unshift(comment);
|
|
1532
|
-
} else {
|
|
1533
|
-
token.content = removeEndingSlash(token.content);
|
|
1534
|
-
tokens.push(token);
|
|
1535
|
-
}
|
|
1536
|
-
if (!isStrongTag)
|
|
1537
|
-
break;
|
|
1538
|
-
} else if (token.tag === "strong") {
|
|
1539
|
-
token.content = removeEndingSlash(token.content);
|
|
1540
|
-
tokens.push(token);
|
|
1541
|
-
if (token.nesting === 1) {
|
|
1542
|
-
isStrongTag = true;
|
|
1543
|
-
} else {
|
|
1544
|
-
break;
|
|
1545
|
-
}
|
|
1546
|
-
} else {
|
|
1547
|
-
tokens.push(token);
|
|
1530
|
+
const renderFileTree = (nodes, meta) => nodes.map((node) => {
|
|
1531
|
+
const { info, level, children } = node;
|
|
1532
|
+
const { filename, comment, focus, expanded, type, diff } = parseFileTreeNodeInfo(info);
|
|
1533
|
+
const isOmit = filename === "\u2026" || filename === "...";
|
|
1534
|
+
if (children.length === 0 && type === "folder") {
|
|
1535
|
+
children.push({ info: "\u2026", level: level + 1, children: [] });
|
|
1536
|
+
}
|
|
1537
|
+
const nodeType = children.length > 0 ? "folder" : type;
|
|
1538
|
+
const renderedComment = comment ? `<template #comment>${md.renderInline(comment.replaceAll("#", "#"))}</template>` : "";
|
|
1539
|
+
const renderedIcon = !isOmit ? `<template #icon><VPIcon name="${getIcon(filename, nodeType, meta.icon)}" /></template>` : "";
|
|
1540
|
+
const props = {
|
|
1541
|
+
expanded: nodeType === "folder" ? expanded : false,
|
|
1542
|
+
focus,
|
|
1543
|
+
type: nodeType,
|
|
1544
|
+
diff,
|
|
1545
|
+
filename,
|
|
1546
|
+
level
|
|
1547
|
+
};
|
|
1548
|
+
return `<FileTreeNode${stringifyAttrs(props)}>
|
|
1549
|
+
${renderedIcon}${renderedComment}${children.length > 0 ? renderFileTree(children, meta) : ""}
|
|
1550
|
+
</FileTreeNode>`;
|
|
1551
|
+
}).join("\n");
|
|
1552
|
+
return createContainerSyntaxPlugin(
|
|
1553
|
+
md,
|
|
1554
|
+
"file-tree",
|
|
1555
|
+
(tokens, index) => {
|
|
1556
|
+
const token = tokens[index];
|
|
1557
|
+
const nodes = parseFileTreeRawContent(token.content);
|
|
1558
|
+
const meta = token.meta;
|
|
1559
|
+
return `<div class="vp-file-tree">${meta.title ? `<p class="vp-file-tree-title">${meta.title}</p>` : ""}${renderFileTree(nodes, meta)}</div>
|
|
1560
|
+
`;
|
|
1548
1561
|
}
|
|
1549
|
-
|
|
1550
|
-
const fileClose = new Token("span_close", "span", -1);
|
|
1551
|
-
tokens.push(fileClose);
|
|
1552
|
-
if (children.filter((token) => token.type === "text" && token.content.trim()).length) {
|
|
1553
|
-
const commentOpen = new Token("span_open", "span", 1);
|
|
1554
|
-
commentOpen.attrSet("class", "comment");
|
|
1555
|
-
const commentClose = new Token("span_close", "span", -1);
|
|
1556
|
-
tokens.push(commentOpen, ...children, commentClose);
|
|
1557
|
-
}
|
|
1558
|
-
tokens.push(wrapperClose);
|
|
1559
|
-
inline.children = tokens;
|
|
1562
|
+
);
|
|
1560
1563
|
}
|
|
1561
1564
|
|
|
1562
1565
|
// src/node/container/langRepl.ts
|
|
1563
1566
|
import { promises as fs2 } from "node:fs";
|
|
1564
1567
|
import { resolveModule } from "local-pkg";
|
|
1565
|
-
import container3 from "markdown-it-container";
|
|
1566
1568
|
import { colors, logger as logger2, path as path2 } from "vuepress/utils";
|
|
1567
|
-
var RE_INFO = /^(#editable)?(.*)$/;
|
|
1568
|
-
function createReplContainer(md, lang) {
|
|
1569
|
-
const type2 = `${lang}-repl`;
|
|
1570
|
-
const validate = (info) => info.trim().startsWith(type2);
|
|
1571
|
-
const render = (tokens, index) => {
|
|
1572
|
-
const token = tokens[index];
|
|
1573
|
-
const info = token.info.trim().slice(type2.length).trim() || "";
|
|
1574
|
-
const [, editable, title] = info.match(RE_INFO);
|
|
1575
|
-
if (token.nesting === 1)
|
|
1576
|
-
return `<CodeRepl ${editable ? "editable" : ""} title="${title || `${lang} playground`}">`;
|
|
1577
|
-
else
|
|
1578
|
-
return "</CodeRepl>";
|
|
1579
|
-
};
|
|
1580
|
-
md.use(container3, type2, { validate, render });
|
|
1581
|
-
}
|
|
1582
1569
|
async function langReplPlugin(app, md, {
|
|
1583
1570
|
theme,
|
|
1584
1571
|
go = false,
|
|
1585
1572
|
kotlin = false,
|
|
1586
1573
|
rust = false
|
|
1587
1574
|
}) {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1575
|
+
const container3 = (lang) => createContainerPlugin(md, `${lang}-repl`, {
|
|
1576
|
+
before(info) {
|
|
1577
|
+
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1578
|
+
const { editable, title } = attrs2;
|
|
1579
|
+
return `<CodeRepl${stringifyAttrs({ editable, title: title || `${lang} playground` })}>`;
|
|
1580
|
+
},
|
|
1581
|
+
after: () => "</CodeRepl>"
|
|
1582
|
+
});
|
|
1583
|
+
if (kotlin)
|
|
1584
|
+
container3("kotlin");
|
|
1585
|
+
if (go)
|
|
1586
|
+
container3("go");
|
|
1587
|
+
if (rust)
|
|
1588
|
+
container3("rust");
|
|
1597
1589
|
theme ??= { light: "github-light", dark: "github-dark" };
|
|
1598
1590
|
const data = { grammars: {} };
|
|
1599
1591
|
try {
|
|
@@ -1634,7 +1626,9 @@ async function read(file) {
|
|
|
1634
1626
|
|
|
1635
1627
|
// src/node/container/npmTo.ts
|
|
1636
1628
|
import { isArray } from "@vuepress/helper";
|
|
1637
|
-
import
|
|
1629
|
+
import { colors as colors2 } from "vuepress/utils";
|
|
1630
|
+
|
|
1631
|
+
// src/node/container/npmToPreset.ts
|
|
1638
1632
|
var ALLOW_LIST = ["npm", "pnpm", "yarn", "bun", "deno"];
|
|
1639
1633
|
var BOOL_FLAGS = ["--no-save", "-B", "--save-bundle", "--save-dev", "-D", "--save-prod", "-P", "--save-peer", "-O", "--save-optional", "-E", "--save-exact", "-y", "--yes", "-g", "--global"];
|
|
1640
1634
|
var DEFAULT_TABS = ["npm", "pnpm", "yarn"];
|
|
@@ -1818,28 +1812,32 @@ var MANAGERS_CONFIG = {
|
|
|
1818
1812
|
deno: { cli: "deno install --frozen" }
|
|
1819
1813
|
}
|
|
1820
1814
|
};
|
|
1815
|
+
|
|
1816
|
+
// src/node/container/npmTo.ts
|
|
1821
1817
|
function npmToPlugins(md, options = {}) {
|
|
1822
|
-
const type2 = "npm-to";
|
|
1823
1818
|
const opt = isArray(options) ? { tabs: options } : options;
|
|
1824
1819
|
const defaultTabs = opt.tabs?.length ? opt.tabs : DEFAULT_TABS;
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1820
|
+
createContainerPlugin(md, "npm-to", {
|
|
1821
|
+
before: (info, tokens, idx, _opt, env) => {
|
|
1822
|
+
const { attrs: attrs2 } = resolveAttrs(info);
|
|
1823
|
+
const tabs2 = attrs2.tabs ? attrs2.tabs.split(/,\s*/) : defaultTabs;
|
|
1829
1824
|
const token = tokens[idx + 1];
|
|
1830
|
-
const info = token.info.trim();
|
|
1831
1825
|
if (token.type === "fence") {
|
|
1832
1826
|
const content = token.content;
|
|
1833
1827
|
token.hidden = true;
|
|
1834
1828
|
token.type = "text";
|
|
1835
1829
|
token.content = "";
|
|
1836
1830
|
const lines = content.split(/(\n|\s*&&\s*)/);
|
|
1837
|
-
return md.render(
|
|
1831
|
+
return md.render(
|
|
1832
|
+
resolveNpmTo(lines, token.info.trim(), idx, tabs2),
|
|
1833
|
+
cleanMarkdownEnv(env)
|
|
1834
|
+
);
|
|
1838
1835
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1836
|
+
console.warn(`${colors2.yellow("[vuepress-plugin-md-power]")} Invalid npm-to container in ${colors2.gray(env.filePathRelative || env.filePath)}`);
|
|
1837
|
+
return "";
|
|
1838
|
+
},
|
|
1839
|
+
after: () => ""
|
|
1840
|
+
});
|
|
1843
1841
|
}
|
|
1844
1842
|
function resolveNpmTo(lines, info, idx, tabs2) {
|
|
1845
1843
|
tabs2 = validateTabs(tabs2);
|
|
@@ -2017,15 +2015,17 @@ function timelinePlugin(md) {
|
|
|
2017
2015
|
before(info, tokens, index) {
|
|
2018
2016
|
parseTimeline(tokens, index);
|
|
2019
2017
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
2020
|
-
|
|
2021
|
-
return `<VPTimeline${
|
|
2018
|
+
attrs2.card ??= void 0;
|
|
2019
|
+
return `<VPTimeline${stringifyAttrs(attrs2, true)}>`;
|
|
2022
2020
|
},
|
|
2023
2021
|
after: () => "</VPTimeline>"
|
|
2024
2022
|
});
|
|
2025
2023
|
md.renderer.rules.timeline_item_open = (tokens, idx) => {
|
|
2026
2024
|
const token = tokens[idx];
|
|
2027
|
-
const
|
|
2028
|
-
|
|
2025
|
+
const attrs2 = token.meta;
|
|
2026
|
+
attrs2.card ??= void 0;
|
|
2027
|
+
const icon = attrs2.icon;
|
|
2028
|
+
return `<VPTimelineItem${stringifyAttrs(attrs2, true)}>${icon ? `<template #icon><VPIcon name="${icon}"/></template>` : ""}`;
|
|
2029
2029
|
};
|
|
2030
2030
|
md.renderer.rules.timeline_item_close = () => "</VPTimelineItem>";
|
|
2031
2031
|
md.renderer.rules.timeline_item_title_open = () => "<template #title>";
|
|
@@ -2122,23 +2122,25 @@ async function containerPlugin(app, md, options) {
|
|
|
2122
2122
|
collapsePlugin(md);
|
|
2123
2123
|
if (options.chat)
|
|
2124
2124
|
chatPlugin(md);
|
|
2125
|
+
if (options.field)
|
|
2126
|
+
fieldPlugin(md);
|
|
2125
2127
|
}
|
|
2126
2128
|
|
|
2127
2129
|
// src/node/demo/demo.ts
|
|
2128
|
-
import
|
|
2130
|
+
import container2 from "markdown-it-container";
|
|
2129
2131
|
|
|
2130
2132
|
// src/node/embed/createEmbedRuleBlock.ts
|
|
2131
2133
|
function createEmbedRuleBlock(md, {
|
|
2132
|
-
type
|
|
2133
|
-
name =
|
|
2134
|
+
type,
|
|
2135
|
+
name = type,
|
|
2134
2136
|
syntaxPattern,
|
|
2135
2137
|
beforeName = "import_code",
|
|
2136
2138
|
ruleOptions = { alt: ["paragraph", "reference", "blockquote", "list"] },
|
|
2137
2139
|
meta,
|
|
2138
2140
|
content
|
|
2139
2141
|
}) {
|
|
2140
|
-
const MIN_LENGTH =
|
|
2141
|
-
const START_CODES = [64, 91, ...
|
|
2142
|
+
const MIN_LENGTH = type.length + 5;
|
|
2143
|
+
const START_CODES = [64, 91, ...type.split("").map((c) => c.charCodeAt(0))];
|
|
2142
2144
|
md.block.ruler.before(
|
|
2143
2145
|
beforeName,
|
|
2144
2146
|
name,
|
|
@@ -2219,7 +2221,7 @@ function markdownEmbed(app, md, env, { url, title, desc, codeSetting = "", expan
|
|
|
2219
2221
|
if (!env.demoFiles.some((d) => d.path === filepath2)) {
|
|
2220
2222
|
env.demoFiles.push(demo);
|
|
2221
2223
|
}
|
|
2222
|
-
return `<VPDemoBasic
|
|
2224
|
+
return `<VPDemoBasic${stringifyAttrs({ type: "markdown", title, desc, expanded })}>
|
|
2223
2225
|
${md.render(code, { filepath: env.filePath, filepathRelative: env.filePathRelative })}
|
|
2224
2226
|
<template #code>
|
|
2225
2227
|
${md.render(`\`\`\`md ${codeSetting}
|
|
@@ -2232,7 +2234,7 @@ var markdownContainerRender = {
|
|
|
2232
2234
|
before(app, md, env, meta, codeMap) {
|
|
2233
2235
|
const { title, desc, expanded = false } = meta;
|
|
2234
2236
|
const code = codeMap.md || "";
|
|
2235
|
-
return `<VPDemoBasic
|
|
2237
|
+
return `<VPDemoBasic${stringifyAttrs({ type: "markdown", title, desc, expanded })}>
|
|
2236
2238
|
${md.render(code, { filepath: env.filePath, filepathRelative: env.filePathRelative })}
|
|
2237
2239
|
<template #code>`;
|
|
2238
2240
|
},
|
|
@@ -2269,8 +2271,8 @@ var compiler = {
|
|
|
2269
2271
|
}),
|
|
2270
2272
|
stylus: importer(() => import("stylus"))
|
|
2271
2273
|
};
|
|
2272
|
-
async function compileScript(source,
|
|
2273
|
-
const key = `${
|
|
2274
|
+
async function compileScript(source, type) {
|
|
2275
|
+
const key = `${type}:::${source}`;
|
|
2274
2276
|
if (cache2.has(key))
|
|
2275
2277
|
return cache2.get(key);
|
|
2276
2278
|
const transform = await compiler.script();
|
|
@@ -2278,31 +2280,31 @@ async function compileScript(source, type2) {
|
|
|
2278
2280
|
target: "es2018",
|
|
2279
2281
|
platform: "browser",
|
|
2280
2282
|
format: "cjs",
|
|
2281
|
-
loader:
|
|
2283
|
+
loader: type === "ts" ? "ts" : "js",
|
|
2282
2284
|
sourcemap: false
|
|
2283
2285
|
});
|
|
2284
2286
|
cache2.set(key, res.code);
|
|
2285
2287
|
return res.code;
|
|
2286
2288
|
}
|
|
2287
|
-
async function compileStyle(source,
|
|
2288
|
-
const key = `${
|
|
2289
|
+
async function compileStyle(source, type) {
|
|
2290
|
+
const key = `${type}:::${source}`;
|
|
2289
2291
|
if (cache2.has(key))
|
|
2290
2292
|
return cache2.get(key);
|
|
2291
|
-
if (
|
|
2293
|
+
if (type === "css")
|
|
2292
2294
|
return source;
|
|
2293
|
-
if (
|
|
2295
|
+
if (type === "less") {
|
|
2294
2296
|
const less = await compiler.less();
|
|
2295
2297
|
const res = await less.render(source);
|
|
2296
2298
|
cache2.set(key, res.css);
|
|
2297
2299
|
return res.css;
|
|
2298
2300
|
}
|
|
2299
|
-
if (
|
|
2301
|
+
if (type === "scss") {
|
|
2300
2302
|
const sass = await compiler.sass();
|
|
2301
2303
|
const res = sass.compileString(source);
|
|
2302
2304
|
cache2.set(key, res.css);
|
|
2303
2305
|
return res.css;
|
|
2304
2306
|
}
|
|
2305
|
-
if (
|
|
2307
|
+
if (type === "stylus") {
|
|
2306
2308
|
const stylus = await compiler.stylus();
|
|
2307
2309
|
const res = stylus.render(source);
|
|
2308
2310
|
cache2.set(key, res);
|
|
@@ -2520,7 +2522,7 @@ function normalEmbed(app, md, env, { url, title, desc, codeSetting = "", expande
|
|
|
2520
2522
|
env.demoFiles.push(demo);
|
|
2521
2523
|
insertSetupScript({ ...demo, path: output }, env);
|
|
2522
2524
|
}
|
|
2523
|
-
return `<VPDemoNormal
|
|
2525
|
+
return `<VPDemoNormal${stringifyAttrs({ ":config": name, title, desc, expanded })}>
|
|
2524
2526
|
${codeToHtml(md, source, codeSetting)}
|
|
2525
2527
|
</VPDemoNormal>`;
|
|
2526
2528
|
}
|
|
@@ -2538,7 +2540,7 @@ var normalContainerRender = {
|
|
|
2538
2540
|
}
|
|
2539
2541
|
const source = parseContainerCode(codeMap);
|
|
2540
2542
|
compileCode(source, output);
|
|
2541
|
-
return `<VPDemoNormal
|
|
2543
|
+
return `<VPDemoNormal${stringifyAttrs({ ":config": name, title, desc, expanded })}>`;
|
|
2542
2544
|
},
|
|
2543
2545
|
after: () => "</VPDemoNormal>",
|
|
2544
2546
|
token(token) {
|
|
@@ -2624,7 +2626,7 @@ function vueEmbed(app, md, env, { url, title, desc, codeSetting = "", expanded =
|
|
|
2624
2626
|
env.demoFiles.push(demo);
|
|
2625
2627
|
insertSetupScript(demo, env);
|
|
2626
2628
|
}
|
|
2627
|
-
return `<VPDemoBasic
|
|
2629
|
+
return `<VPDemoBasic${stringifyAttrs({ type: "vue", title, desc, expanded })}>
|
|
2628
2630
|
<${name} />
|
|
2629
2631
|
<template #code>
|
|
2630
2632
|
${md.render(`\`\`\`${ext}${codeSetting}
|
|
@@ -2637,10 +2639,10 @@ var target3 = "md-power/demo/vue";
|
|
|
2637
2639
|
var vueContainerRender = {
|
|
2638
2640
|
before: (app, md, env, meta, codeMap) => {
|
|
2639
2641
|
const { url, title, desc, expanded = false } = meta;
|
|
2640
|
-
const
|
|
2642
|
+
const componentName = `DemoContainer${url}`;
|
|
2641
2643
|
const prefix = (env.filePathRelative || "").replace(/\.md$/, "").replace(/\//g, "-");
|
|
2642
2644
|
env.demoFiles ??= [];
|
|
2643
|
-
const output = app.dir.temp(path6.join(target3, `${prefix}-${
|
|
2645
|
+
const output = app.dir.temp(path6.join(target3, `${prefix}-${componentName}`));
|
|
2644
2646
|
if (codeMap.vue || codeMap.js || codeMap.ts) {
|
|
2645
2647
|
let scriptOutput = output;
|
|
2646
2648
|
let content = "";
|
|
@@ -2655,7 +2657,7 @@ var vueContainerRender = {
|
|
|
2655
2657
|
content = codeMap.js;
|
|
2656
2658
|
}
|
|
2657
2659
|
content = transformImports(content, env.filePath || "");
|
|
2658
|
-
const script = { type: "vue", export:
|
|
2660
|
+
const script = { type: "vue", export: componentName, path: scriptOutput, gitignore: true };
|
|
2659
2661
|
writeFileSync(scriptOutput, content);
|
|
2660
2662
|
if (!env.demoFiles.some((d) => d.path === scriptOutput)) {
|
|
2661
2663
|
env.demoFiles.push(script);
|
|
@@ -2685,8 +2687,8 @@ var vueContainerRender = {
|
|
|
2685
2687
|
insertSetupScript(style, env);
|
|
2686
2688
|
}
|
|
2687
2689
|
}
|
|
2688
|
-
return `<VPDemoBasic
|
|
2689
|
-
<${
|
|
2690
|
+
return `<VPDemoBasic${stringifyAttrs({ type: "vue", title, desc, expanded })}>
|
|
2691
|
+
<${componentName} />
|
|
2690
2692
|
<template #code>
|
|
2691
2693
|
`;
|
|
2692
2694
|
},
|
|
@@ -2716,24 +2718,24 @@ function demoEmbed(app, md) {
|
|
|
2716
2718
|
createEmbedRuleBlock(md, {
|
|
2717
2719
|
type: "demo",
|
|
2718
2720
|
syntaxPattern: /^@\[demo(?:\s(vue|normal|markdown))?\s?(.*)\]\((.*)\)/,
|
|
2719
|
-
meta: ([,
|
|
2720
|
-
type:
|
|
2721
|
+
meta: ([, type, info, url]) => ({
|
|
2722
|
+
type: type || "normal",
|
|
2721
2723
|
url,
|
|
2722
2724
|
...resolveAttrs(info).attrs
|
|
2723
2725
|
}),
|
|
2724
2726
|
content: (meta, content, env) => {
|
|
2725
|
-
const { url, type
|
|
2727
|
+
const { url, type } = meta;
|
|
2726
2728
|
if (!url) {
|
|
2727
2729
|
console.warn("[vuepress-plugin-md-power] Invalid demo url: ", url);
|
|
2728
2730
|
return content;
|
|
2729
2731
|
}
|
|
2730
|
-
if (
|
|
2732
|
+
if (type === "vue") {
|
|
2731
2733
|
return vueEmbed(app, md, env, meta);
|
|
2732
2734
|
}
|
|
2733
|
-
if (
|
|
2735
|
+
if (type === "normal") {
|
|
2734
2736
|
return normalEmbed(app, md, env, meta);
|
|
2735
2737
|
}
|
|
2736
|
-
if (
|
|
2738
|
+
if (type === "markdown") {
|
|
2737
2739
|
return markdownEmbed(app, md, env, meta);
|
|
2738
2740
|
}
|
|
2739
2741
|
return content;
|
|
@@ -2767,7 +2769,7 @@ function demoContainer(app, md) {
|
|
|
2767
2769
|
return res;
|
|
2768
2770
|
}
|
|
2769
2771
|
};
|
|
2770
|
-
md.use(
|
|
2772
|
+
md.use(container2, "demo", { render });
|
|
2771
2773
|
}
|
|
2772
2774
|
function parseCodeMapping(tokens, index, cb) {
|
|
2773
2775
|
const codeMap = {};
|
|
@@ -2781,11 +2783,11 @@ function parseCodeMapping(tokens, index, cb) {
|
|
|
2781
2783
|
return codeMap;
|
|
2782
2784
|
}
|
|
2783
2785
|
function getContainerMeta(info) {
|
|
2784
|
-
const [,
|
|
2786
|
+
const [, type, raw] = (info.trim().slice(4).trim() || "").match(INFO_RE) || [];
|
|
2785
2787
|
const { attrs: attrs2 } = resolveAttrs(raw);
|
|
2786
2788
|
return {
|
|
2787
2789
|
url: "",
|
|
2788
|
-
type:
|
|
2790
|
+
type: type || "normal",
|
|
2789
2791
|
...attrs2
|
|
2790
2792
|
};
|
|
2791
2793
|
}
|
|
@@ -2795,7 +2797,7 @@ function extendsPageWithDemo(page) {
|
|
|
2795
2797
|
const markdownEnv = page.markdownEnv;
|
|
2796
2798
|
const demoFiles = markdownEnv.demoFiles ?? [];
|
|
2797
2799
|
page.deps.push(
|
|
2798
|
-
...demoFiles.filter(({ type
|
|
2800
|
+
...demoFiles.filter(({ type }) => type === "markdown").map(({ path: path9 }) => path9)
|
|
2799
2801
|
);
|
|
2800
2802
|
(page.frontmatter.gitInclude ??= []).push(
|
|
2801
2803
|
...demoFiles.filter(({ gitignore }) => !gitignore).map(({ path: path9 }) => path9)
|
|
@@ -2849,29 +2851,27 @@ var audioReader = (state, silent) => {
|
|
|
2849
2851
|
state.posMax = labelEnd;
|
|
2850
2852
|
const info = state.src.slice(labelStart, labelEnd).trim();
|
|
2851
2853
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
2852
|
-
const
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
if (attrs2.startTime)
|
|
2856
|
-
tokenOpen.attrs.push([":start-time", attrs2.startTime]);
|
|
2857
|
-
if (attrs2.endTime)
|
|
2858
|
-
tokenOpen.attrs.push([":end-time", attrs2.endTime]);
|
|
2859
|
-
if (attrs2.type)
|
|
2860
|
-
tokenOpen.attrs.push(["type", attrs2.type]);
|
|
2861
|
-
if (attrs2.volume)
|
|
2862
|
-
tokenOpen.attrs.push([":volume", attrs2.volume]);
|
|
2863
|
-
if (attrs2.title)
|
|
2864
|
-
state.push("text", "", 0).content = attrs2.title;
|
|
2865
|
-
state.push("audio_reader_close", "AudioReader", -1);
|
|
2854
|
+
const token = state.push("audio_reader", "AudioReader", 0);
|
|
2855
|
+
token.info = info;
|
|
2856
|
+
token.meta = { src: href, ...attrs2 };
|
|
2866
2857
|
}
|
|
2867
2858
|
state.pos = pos + 1;
|
|
2868
2859
|
state.posMax = max;
|
|
2869
2860
|
return true;
|
|
2870
2861
|
};
|
|
2871
|
-
var audioReaderPlugin = (md) =>
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2862
|
+
var audioReaderPlugin = (md) => {
|
|
2863
|
+
md.renderer.rules.audio_reader = (tokens, idx) => {
|
|
2864
|
+
const meta = tokens[idx].meta ?? {};
|
|
2865
|
+
if (meta.startTime)
|
|
2866
|
+
meta.startTime = Number(meta.startTime);
|
|
2867
|
+
if (meta.endTime)
|
|
2868
|
+
meta.endTime = Number(meta.endTime);
|
|
2869
|
+
if (meta.volume)
|
|
2870
|
+
meta.volume = Number(meta.volume);
|
|
2871
|
+
return `<AudioReader${stringifyAttrs(meta)} />`;
|
|
2872
|
+
};
|
|
2873
|
+
md.inline.ruler.before("link", "audio-reader", audioReader);
|
|
2874
|
+
};
|
|
2875
2875
|
|
|
2876
2876
|
// src/node/utils/nanoid.ts
|
|
2877
2877
|
import { customAlphabet } from "nanoid";
|
|
@@ -2895,23 +2895,14 @@ function legacyCaniuse(md, { mode = "embed" } = {}) {
|
|
|
2895
2895
|
const modeMap = ["image", "embed"];
|
|
2896
2896
|
const isMode = (mode2) => modeMap.includes(mode2);
|
|
2897
2897
|
mode = isMode(mode) ? mode : modeMap[0];
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
const validate = (info) => {
|
|
2901
|
-
return validateReg.test(info.trim());
|
|
2902
|
-
};
|
|
2903
|
-
const render = (tokens, index) => {
|
|
2904
|
-
const token = tokens[index];
|
|
2905
|
-
if (token.nesting === 1) {
|
|
2906
|
-
const info = token.info.trim().slice(type2.length).trim() || "";
|
|
2898
|
+
createContainerPlugin(md, "caniuse", {
|
|
2899
|
+
before: (info) => {
|
|
2907
2900
|
const feature = info.split(/\s+/)[0];
|
|
2908
2901
|
const versions = info.match(/\{(.*)\}/)?.[1] || "";
|
|
2909
2902
|
return feature ? resolveCanIUse({ feature, mode, versions }) : "";
|
|
2910
|
-
}
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
};
|
|
2914
|
-
md.use(container6, type2, { validate, render });
|
|
2903
|
+
},
|
|
2904
|
+
after: () => ""
|
|
2905
|
+
});
|
|
2915
2906
|
}
|
|
2916
2907
|
function resolveCanIUse({ feature, mode, versions }) {
|
|
2917
2908
|
if (!feature)
|
|
@@ -2928,7 +2919,7 @@ function resolveCanIUse({ feature, mode, versions }) {
|
|
|
2928
2919
|
feature = feature.replace(UNDERLINE_RE, "_");
|
|
2929
2920
|
const { past, future } = resolveVersions(versions);
|
|
2930
2921
|
const meta = nanoid();
|
|
2931
|
-
return `<CanIUseViewer
|
|
2922
|
+
return `<CanIUseViewer${stringifyAttrs({ feature, meta, past, future })} />`;
|
|
2932
2923
|
}
|
|
2933
2924
|
function resolveVersions(versions) {
|
|
2934
2925
|
if (!versions)
|
|
@@ -2955,19 +2946,21 @@ var codepenPlugin = (md) => {
|
|
|
2955
2946
|
type: "codepen",
|
|
2956
2947
|
syntaxPattern: /^@\[codepen([^\]]*)\]\(([^)]*)\)/,
|
|
2957
2948
|
meta: ([, info, source]) => {
|
|
2958
|
-
const { width, height, title, tab: tab3,
|
|
2949
|
+
const { width, height, title, tab: tab3, preview, editable, theme } = resolveAttrs(info).attrs;
|
|
2959
2950
|
const [user, slash] = source.split("/");
|
|
2960
2951
|
return {
|
|
2952
|
+
title: title || "Code Pen",
|
|
2953
|
+
tab: tab3 || "result",
|
|
2961
2954
|
width: width ? parseRect(width) : "100%",
|
|
2962
2955
|
height: height ? parseRect(height) : "400px",
|
|
2963
2956
|
user,
|
|
2964
2957
|
slash,
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2958
|
+
preview,
|
|
2959
|
+
editable,
|
|
2960
|
+
theme
|
|
2968
2961
|
};
|
|
2969
2962
|
},
|
|
2970
|
-
content: (
|
|
2963
|
+
content: (meta) => `<CodePenViewer${stringifyAttrs(meta)} />`
|
|
2971
2964
|
});
|
|
2972
2965
|
};
|
|
2973
2966
|
|
|
@@ -2976,7 +2969,7 @@ var codeSandboxPlugin = (md) => {
|
|
|
2976
2969
|
createEmbedRuleBlock(md, {
|
|
2977
2970
|
type: "codesandbox",
|
|
2978
2971
|
syntaxPattern: /^@\[codesandbox(?:\s+(embed|button))?([^\]]*)\]\(([^)]*)\)/,
|
|
2979
|
-
meta([,
|
|
2972
|
+
meta([, type, info, source]) {
|
|
2980
2973
|
const { attrs: attrs2 } = resolveAttrs(info);
|
|
2981
2974
|
const [profile, filepath2 = ""] = source.split("#");
|
|
2982
2975
|
const [user, id] = profile.includes("/") ? profile.split("/") : ["", profile];
|
|
@@ -2989,13 +2982,11 @@ var codeSandboxPlugin = (md) => {
|
|
|
2989
2982
|
console: attrs2.console ?? false,
|
|
2990
2983
|
navbar: attrs2.navbar ?? true,
|
|
2991
2984
|
layout: attrs2.layout ?? "",
|
|
2992
|
-
type:
|
|
2985
|
+
type: type || "embed",
|
|
2993
2986
|
filepath: filepath2
|
|
2994
2987
|
};
|
|
2995
2988
|
},
|
|
2996
|
-
content
|
|
2997
|
-
return `<CodeSandboxViewer title="${title}" height="${height}" width="${width}" user="${user}" id="${id}" type="${type2}" filepath="${filepath2}" :console=${console2} :navbar=${navbar} layout="${layout}" />`;
|
|
2998
|
-
}
|
|
2989
|
+
content: (meta) => `<CodeSandboxViewer${stringifyAttrs(meta)} />`
|
|
2999
2990
|
});
|
|
3000
2991
|
};
|
|
3001
2992
|
|
|
@@ -3015,7 +3006,7 @@ var jsfiddlePlugin = (md) => {
|
|
|
3015
3006
|
theme
|
|
3016
3007
|
};
|
|
3017
3008
|
},
|
|
3018
|
-
content: (
|
|
3009
|
+
content: (meta) => `<JSFiddleViewer${stringifyAttrs(meta)} />`
|
|
3019
3010
|
});
|
|
3020
3011
|
};
|
|
3021
3012
|
|
|
@@ -3034,9 +3025,7 @@ var replitPlugin = (md) => {
|
|
|
3034
3025
|
theme: attrs2.theme || ""
|
|
3035
3026
|
};
|
|
3036
3027
|
},
|
|
3037
|
-
content(
|
|
3038
|
-
return `<ReplitViewer title="${title || ""}" height="${height}" width="${width}" source="${source}" theme="${theme}" />`;
|
|
3039
|
-
}
|
|
3028
|
+
content: (meta) => `<ReplitViewer${stringifyAttrs(meta)} />`
|
|
3040
3029
|
});
|
|
3041
3030
|
};
|
|
3042
3031
|
|
|
@@ -3060,15 +3049,13 @@ var pdfPlugin = (md) => {
|
|
|
3060
3049
|
title: path7.basename(src || "")
|
|
3061
3050
|
};
|
|
3062
3051
|
},
|
|
3063
|
-
content(
|
|
3064
|
-
return `<PDFViewer src="${src}" title="${title}" :page="${page}" :no-toolbar="${noToolbar}" width="${width}" height="${height}" ratio="${ratio}" :zoom="${zoom}" />`;
|
|
3065
|
-
}
|
|
3052
|
+
content: (meta) => `<PDFViewer${stringifyAttrs(meta)} />`
|
|
3066
3053
|
});
|
|
3067
3054
|
};
|
|
3068
3055
|
|
|
3069
3056
|
// src/node/embed/video/artPlayer.ts
|
|
3070
3057
|
import { isPackageExists as isPackageExists2 } from "local-pkg";
|
|
3071
|
-
import { colors as
|
|
3058
|
+
import { colors as colors3 } from "vuepress/utils";
|
|
3072
3059
|
var installed = {
|
|
3073
3060
|
dashjs: isPackageExists2("dashjs"),
|
|
3074
3061
|
hlsjs: isPackageExists2("hls.js"),
|
|
@@ -3085,6 +3072,8 @@ var artPlayerPlugin = (md) => {
|
|
|
3085
3072
|
const url = source.trim();
|
|
3086
3073
|
checkSupportType(attrs2.type ?? url.split(".").pop());
|
|
3087
3074
|
return {
|
|
3075
|
+
url,
|
|
3076
|
+
type: attrs2.type,
|
|
3088
3077
|
autoplay: attrs2.autoplay ?? false,
|
|
3089
3078
|
muted: attrs2.muted ?? attrs2.autoplay ?? false,
|
|
3090
3079
|
autoMini: attrs2.autoMini ?? false,
|
|
@@ -3092,23 +3081,22 @@ var artPlayerPlugin = (md) => {
|
|
|
3092
3081
|
volume: typeof attrs2.volume !== "undefined" ? Number(attrs2.volume) : 0.75,
|
|
3093
3082
|
poster: attrs2.poster,
|
|
3094
3083
|
width: attrs2.width ? parseRect(attrs2.width) : "100%",
|
|
3095
|
-
height: attrs2.height ? parseRect(attrs2.height) :
|
|
3096
|
-
ratio: attrs2.ratio ? parseRect(`${attrs2.ratio}`) :
|
|
3097
|
-
type: attrs2.type,
|
|
3098
|
-
url
|
|
3084
|
+
height: attrs2.height ? parseRect(attrs2.height) : void 0,
|
|
3085
|
+
ratio: attrs2.ratio ? parseRect(`${attrs2.ratio}`) : void 0
|
|
3099
3086
|
};
|
|
3100
3087
|
},
|
|
3101
|
-
content({
|
|
3102
|
-
|
|
3088
|
+
content({ url, ...meta }) {
|
|
3089
|
+
meta.muted = meta.muted || meta.autoplay;
|
|
3090
|
+
return `<ArtPlayer src="${url}" fullscreen flip playback-rate aspect-ratio setting pip${stringifyAttrs(meta)}/>`;
|
|
3103
3091
|
}
|
|
3104
3092
|
});
|
|
3105
3093
|
};
|
|
3106
|
-
function checkSupportType(
|
|
3107
|
-
if (!
|
|
3094
|
+
function checkSupportType(type) {
|
|
3095
|
+
if (!type)
|
|
3108
3096
|
return;
|
|
3109
|
-
if (SUPPORTED_VIDEO_TYPES.includes(
|
|
3097
|
+
if (SUPPORTED_VIDEO_TYPES.includes(type)) {
|
|
3110
3098
|
let name = "";
|
|
3111
|
-
switch (
|
|
3099
|
+
switch (type.toLowerCase()) {
|
|
3112
3100
|
case "m3u8":
|
|
3113
3101
|
case "hls":
|
|
3114
3102
|
name = !installed.hlsjs ? "hls.js" : "";
|
|
@@ -3124,10 +3112,10 @@ function checkSupportType(type2) {
|
|
|
3124
3112
|
break;
|
|
3125
3113
|
}
|
|
3126
3114
|
if (name) {
|
|
3127
|
-
console.warn(`${
|
|
3115
|
+
console.warn(`${colors3.yellow("[vuepress-plugin-md-power] artPlayer: ")} ${colors3.cyan(name)} is not installed, please install it via npm or yarn or pnpm`);
|
|
3128
3116
|
}
|
|
3129
3117
|
} else {
|
|
3130
|
-
console.warn(`${
|
|
3118
|
+
console.warn(`${colors3.yellow("[vuepress-plugin-md-power] artPlayer: ")} unsupported video type: ${colors3.cyan(type)}`);
|
|
3131
3119
|
}
|
|
3132
3120
|
}
|
|
3133
3121
|
|
|
@@ -3166,31 +3154,27 @@ var bilibiliPlugin = (md) => {
|
|
|
3166
3154
|
time: timeToSeconds(attrs2.time),
|
|
3167
3155
|
title: attrs2.title,
|
|
3168
3156
|
width: attrs2.width ? parseRect(attrs2.width) : "100%",
|
|
3169
|
-
height: attrs2.height ? parseRect(attrs2.height) :
|
|
3170
|
-
ratio: attrs2.ratio ? parseRect(attrs2.ratio) :
|
|
3157
|
+
height: attrs2.height ? parseRect(attrs2.height) : void 0,
|
|
3158
|
+
ratio: attrs2.ratio ? parseRect(attrs2.ratio) : void 0
|
|
3171
3159
|
};
|
|
3172
3160
|
},
|
|
3173
3161
|
content(meta) {
|
|
3174
3162
|
const params = new URLSearchParams();
|
|
3175
|
-
if (meta.bvid)
|
|
3163
|
+
if (meta.bvid)
|
|
3176
3164
|
params.set("bvid", meta.bvid);
|
|
3177
|
-
|
|
3178
|
-
if (meta.aid) {
|
|
3165
|
+
if (meta.aid)
|
|
3179
3166
|
params.set("aid", meta.aid);
|
|
3180
|
-
|
|
3181
|
-
if (meta.cid) {
|
|
3167
|
+
if (meta.cid)
|
|
3182
3168
|
params.set("cid", meta.cid);
|
|
3183
|
-
|
|
3184
|
-
if (meta.page) {
|
|
3169
|
+
if (meta.page)
|
|
3185
3170
|
params.set("p", meta.page.toString());
|
|
3186
|
-
|
|
3187
|
-
if (meta.time) {
|
|
3171
|
+
if (meta.time)
|
|
3188
3172
|
params.set("t", meta.time.toString());
|
|
3189
|
-
}
|
|
3190
3173
|
params.set("autoplay", meta.autoplay ? "1" : "0");
|
|
3191
3174
|
params.set("high_quality", "1");
|
|
3192
3175
|
const source = `${BILIBILI_LINK}?${params.toString()}`;
|
|
3193
|
-
|
|
3176
|
+
const { width, height, ratio, title } = meta;
|
|
3177
|
+
return `<VideoBilibili${stringifyAttrs({ src: source, width, height, ratio, title })} />`;
|
|
3194
3178
|
}
|
|
3195
3179
|
});
|
|
3196
3180
|
};
|
|
@@ -3213,26 +3197,23 @@ var youtubePlugin = (md) => {
|
|
|
3213
3197
|
end: timeToSeconds(attrs2.end),
|
|
3214
3198
|
title: attrs2.title,
|
|
3215
3199
|
width: attrs2.width ? parseRect(attrs2.width) : "100%",
|
|
3216
|
-
height: attrs2.height ? parseRect(attrs2.height) :
|
|
3217
|
-
ratio: attrs2.ratio ? parseRect(attrs2.ratio) :
|
|
3200
|
+
height: attrs2.height ? parseRect(attrs2.height) : void 0,
|
|
3201
|
+
ratio: attrs2.ratio ? parseRect(attrs2.ratio) : void 0
|
|
3218
3202
|
};
|
|
3219
3203
|
},
|
|
3220
3204
|
content(meta) {
|
|
3221
3205
|
const params = new URLSearchParams2();
|
|
3222
|
-
if (meta.autoplay)
|
|
3206
|
+
if (meta.autoplay)
|
|
3223
3207
|
params.set("autoplay", "1");
|
|
3224
|
-
|
|
3225
|
-
if (meta.loop) {
|
|
3208
|
+
if (meta.loop)
|
|
3226
3209
|
params.set("loop", "1");
|
|
3227
|
-
|
|
3228
|
-
if (meta.start) {
|
|
3210
|
+
if (meta.start)
|
|
3229
3211
|
params.set("start", meta.start.toString());
|
|
3230
|
-
|
|
3231
|
-
if (meta.end) {
|
|
3212
|
+
if (meta.end)
|
|
3232
3213
|
params.set("end", meta.end.toString());
|
|
3233
|
-
}
|
|
3234
3214
|
const source = `${YOUTUBE_LINK}/${meta.id}?${params.toString()}`;
|
|
3235
|
-
|
|
3215
|
+
const { width, height, ratio, title } = meta;
|
|
3216
|
+
return `<VideoYoutube${stringifyAttrs({ src: source, width, height, ratio, title })} />`;
|
|
3236
3217
|
}
|
|
3237
3218
|
});
|
|
3238
3219
|
};
|
|
@@ -3520,16 +3501,17 @@ var annotationPlugin = (md) => {
|
|
|
3520
3501
|
};
|
|
3521
3502
|
|
|
3522
3503
|
// src/node/inline/icons.ts
|
|
3523
|
-
|
|
3524
|
-
function
|
|
3504
|
+
import { colors as colors4 } from "vuepress/utils";
|
|
3505
|
+
function createIconRule([l1, l2, r1, r2], deprecated) {
|
|
3525
3506
|
return (state, silent) => {
|
|
3526
3507
|
let found = false;
|
|
3527
3508
|
const max = state.posMax;
|
|
3528
3509
|
const start = state.pos;
|
|
3529
|
-
if (state.src.charCodeAt(start) !==
|
|
3510
|
+
if (state.src.charCodeAt(start) !== l1 || state.src.charCodeAt(start + 1) !== l2) {
|
|
3530
3511
|
return false;
|
|
3531
3512
|
}
|
|
3532
|
-
|
|
3513
|
+
const next = state.src.charCodeAt(start + 2);
|
|
3514
|
+
if (next === 32 || next === 58)
|
|
3533
3515
|
return false;
|
|
3534
3516
|
if (silent)
|
|
3535
3517
|
return false;
|
|
@@ -3537,7 +3519,7 @@ function createTokenizer(options) {
|
|
|
3537
3519
|
return false;
|
|
3538
3520
|
state.pos = start + 2;
|
|
3539
3521
|
while (state.pos < max) {
|
|
3540
|
-
if (state.src.charCodeAt(state.pos) ===
|
|
3522
|
+
if (state.src.charCodeAt(state.pos) === r1 && state.src.charCodeAt(state.pos + 1) === r2) {
|
|
3541
3523
|
found = true;
|
|
3542
3524
|
break;
|
|
3543
3525
|
}
|
|
@@ -3547,69 +3529,103 @@ function createTokenizer(options) {
|
|
|
3547
3529
|
state.pos = start;
|
|
3548
3530
|
return false;
|
|
3549
3531
|
}
|
|
3550
|
-
const
|
|
3532
|
+
const info = state.src.slice(start + 2, state.pos);
|
|
3551
3533
|
state.posMax = state.pos;
|
|
3552
3534
|
state.pos = start + 2;
|
|
3553
|
-
const
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
icon.
|
|
3557
|
-
icon.attrs = [["name", name]];
|
|
3558
|
-
if (size || options.size)
|
|
3559
|
-
icon.attrs.push(["size", String(size || options.size)]);
|
|
3560
|
-
if (color)
|
|
3561
|
-
icon.attrs.push(["color", color]);
|
|
3562
|
-
const close = state.push("vp_icon_close", "VPIcon", -1);
|
|
3563
|
-
close.markup = "]:";
|
|
3535
|
+
const icon = state.push("icon", "i", 0);
|
|
3536
|
+
icon.markup = "::";
|
|
3537
|
+
icon.content = info;
|
|
3538
|
+
icon.meta = { deprecated };
|
|
3564
3539
|
state.pos = state.posMax + 2;
|
|
3565
3540
|
state.posMax = max;
|
|
3566
3541
|
return true;
|
|
3567
3542
|
};
|
|
3568
3543
|
}
|
|
3544
|
+
var RE_SIZE = /(?<=\s|^)=(.+?)(?:\s|$)/;
|
|
3545
|
+
var RE_COLOR = /(?<=\s|^)\/(.+?)(?:\s|$)/;
|
|
3546
|
+
function iconRender(content, options) {
|
|
3547
|
+
let size = options.size;
|
|
3548
|
+
let color = options.color;
|
|
3549
|
+
content = content.replace(RE_SIZE, (_, s) => {
|
|
3550
|
+
size = s;
|
|
3551
|
+
return "";
|
|
3552
|
+
}).replace(RE_COLOR, (_, c) => {
|
|
3553
|
+
color = c;
|
|
3554
|
+
return "";
|
|
3555
|
+
}).trim();
|
|
3556
|
+
const [name, ...extra] = content.split(/\s+/);
|
|
3557
|
+
return `<VPIcon${stringifyAttrs({ name, size, color, class: extra.length ? extra.join(" ") : void 0 })} />`;
|
|
3558
|
+
}
|
|
3559
|
+
var iconPlugin = (md, options = {}) => {
|
|
3560
|
+
md.inline.ruler.before(
|
|
3561
|
+
"link",
|
|
3562
|
+
"icon",
|
|
3563
|
+
// : : : :
|
|
3564
|
+
createIconRule([58, 58, 58, 58])
|
|
3565
|
+
);
|
|
3566
|
+
md.inline.ruler.before(
|
|
3567
|
+
"link",
|
|
3568
|
+
"icon_deprecated",
|
|
3569
|
+
// : [ ] :
|
|
3570
|
+
createIconRule([58, 91, 93, 58], true)
|
|
3571
|
+
);
|
|
3572
|
+
md.renderer.rules.icon = (tokens, idx, _, env) => {
|
|
3573
|
+
const { content, meta } = tokens[idx];
|
|
3574
|
+
let icon = content;
|
|
3575
|
+
if (meta.deprecated) {
|
|
3576
|
+
const [name, opt = ""] = content.split(" ");
|
|
3577
|
+
const [size, color] = opt.trim().split("/");
|
|
3578
|
+
icon = `${name}${size ? ` =${size}` : ""}${color ? ` /${color}` : ""}`;
|
|
3579
|
+
console.warn(`The icon syntax of \`${colors4.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors4.green(`::${icon}::`)}\` instead. (${colors4.gray(env.filePathRelative || env.filePath)})`);
|
|
3580
|
+
}
|
|
3581
|
+
return iconRender(icon, options);
|
|
3582
|
+
};
|
|
3583
|
+
};
|
|
3569
3584
|
|
|
3570
3585
|
// src/node/inline/plot.ts
|
|
3571
|
-
var
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
state.pos
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
found = true;
|
|
3591
|
-
break;
|
|
3592
|
-
}
|
|
3593
|
-
state.md.inline.skipToken(state);
|
|
3594
|
-
}
|
|
3595
|
-
if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
|
|
3596
|
-
state.pos = start;
|
|
3597
|
-
return false;
|
|
3586
|
+
var plotDef = (state, silent) => {
|
|
3587
|
+
let found = false;
|
|
3588
|
+
const max = state.posMax;
|
|
3589
|
+
const start = state.pos;
|
|
3590
|
+
if (state.src.charCodeAt(start) !== 33 || state.src.charCodeAt(start + 1) !== 33) {
|
|
3591
|
+
return false;
|
|
3592
|
+
}
|
|
3593
|
+
const next = state.src.charCodeAt(start + 2);
|
|
3594
|
+
if (next === 32 || next === 33)
|
|
3595
|
+
return false;
|
|
3596
|
+
if (silent)
|
|
3597
|
+
return false;
|
|
3598
|
+
if (max - start < 5)
|
|
3599
|
+
return false;
|
|
3600
|
+
state.pos = start + 2;
|
|
3601
|
+
while (state.pos < max) {
|
|
3602
|
+
if (state.src.charCodeAt(state.pos) === 33 && state.src.charCodeAt(state.pos + 1) === 33) {
|
|
3603
|
+
found = true;
|
|
3604
|
+
break;
|
|
3598
3605
|
}
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3606
|
+
state.md.inline.skipToken(state);
|
|
3607
|
+
}
|
|
3608
|
+
if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
|
|
3609
|
+
state.pos = start;
|
|
3610
|
+
return false;
|
|
3611
|
+
}
|
|
3612
|
+
const content = state.src.slice(start + 2, state.pos);
|
|
3613
|
+
state.posMax = state.pos;
|
|
3614
|
+
state.pos = start + 2;
|
|
3615
|
+
const token = state.push("plot_inline", "Plot", 0);
|
|
3616
|
+
token.markup = "!!";
|
|
3617
|
+
token.content = content;
|
|
3618
|
+
state.pos = state.posMax + 2;
|
|
3619
|
+
state.posMax = max;
|
|
3620
|
+
return true;
|
|
3621
|
+
};
|
|
3622
|
+
var plotPlugin = (md) => {
|
|
3623
|
+
md.renderer.rules.plot_inline = (tokens, idx) => {
|
|
3624
|
+
const token = tokens[idx];
|
|
3625
|
+
return `<Plot>${token.content}</Plot>`;
|
|
3611
3626
|
};
|
|
3612
|
-
|
|
3627
|
+
md.inline.ruler.before("emphasis", "plot", plotDef);
|
|
3628
|
+
};
|
|
3613
3629
|
|
|
3614
3630
|
// src/node/inline/index.ts
|
|
3615
3631
|
function inlineSyntaxPlugin(md, options) {
|
|
@@ -3626,7 +3642,7 @@ function inlineSyntaxPlugin(md, options) {
|
|
|
3626
3642
|
md.use(abbrPlugin);
|
|
3627
3643
|
}
|
|
3628
3644
|
if (options.icons) {
|
|
3629
|
-
md.use(
|
|
3645
|
+
md.use(iconPlugin, isPlainObject3(options.icons) ? options.icons : {});
|
|
3630
3646
|
}
|
|
3631
3647
|
if (options.plot === true || isPlainObject3(options.plot) && options.plot.tag !== false) {
|
|
3632
3648
|
md.use(plotPlugin);
|
|
@@ -3689,8 +3705,8 @@ async function prepareConfigFile(app, options) {
|
|
|
3689
3705
|
enhances.add(`app.component('CanIUseViewer', CanIUse)`);
|
|
3690
3706
|
}
|
|
3691
3707
|
if (options.fileTree) {
|
|
3692
|
-
imports.add(`import
|
|
3693
|
-
enhances.add(`app.component('
|
|
3708
|
+
imports.add(`import FileTreeNode from '${CLIENT_FOLDER}components/FileTreeNode.vue'`);
|
|
3709
|
+
enhances.add(`app.component('FileTreeNode', FileTreeNode)`);
|
|
3694
3710
|
}
|
|
3695
3711
|
if (options.artPlayer) {
|
|
3696
3712
|
imports.add(`import ArtPlayer from '${CLIENT_FOLDER}components/ArtPlayer.vue'`);
|
|
@@ -3729,6 +3745,10 @@ async function prepareConfigFile(app, options) {
|
|
|
3729
3745
|
if (options.chat) {
|
|
3730
3746
|
imports.add(`import '${CLIENT_FOLDER}styles/chat.css'`);
|
|
3731
3747
|
}
|
|
3748
|
+
if (options.field) {
|
|
3749
|
+
imports.add(`import VPField from '${CLIENT_FOLDER}components/VPField.vue'`);
|
|
3750
|
+
enhances.add(`app.component('VPField', VPField)`);
|
|
3751
|
+
}
|
|
3732
3752
|
return app.writeTemp(
|
|
3733
3753
|
"md-power/config.js",
|
|
3734
3754
|
`import { defineClientConfig } from 'vuepress/client'
|