142 lines
4.4 KiB
Plaintext
142 lines
4.4 KiB
Plaintext
import markdown from "markdown-it";
|
|
import highlight from "./highlight";
|
|
import type Token from "markdown-it/lib/token";
|
|
|
|
function assignScript(script: string) {
|
|
const dependencies = {} as Record<string, string[]>;
|
|
const attrs = {} as Record<string, string>;
|
|
const content = script
|
|
.replace(/import\s?\{.*\}.*/g, (item) => {
|
|
const key = getInnerString(item.replace(/'/g, '"'), '"', '"');
|
|
const value = getInnerString(item.replace(/\s+/g, ""), "{", "}");
|
|
const list = value ? value.split(",") : [];
|
|
if (key && dependencies[key]) {
|
|
dependencies[key] = dependencies[key].concat(list);
|
|
} else if (key) {
|
|
dependencies[key] = list;
|
|
}
|
|
return "";
|
|
})
|
|
/**
|
|
* const -> let
|
|
*
|
|
* const a = -> let a =
|
|
* const a = -> a =
|
|
*/
|
|
.replace(/(const|let|var)\s\w*\s?=/g, (item) => {
|
|
const attr = getInnerString(item, "\\s", "\\s?=");
|
|
if (attr && !(attr in attrs)) {
|
|
attrs[attr] = attr;
|
|
return `let ${attr} =`;
|
|
} else {
|
|
return attr + " =";
|
|
}
|
|
})
|
|
// Remove extra line breaks
|
|
.replace(/\n+/gm, "\n");
|
|
// Combine the import
|
|
const reImport = Object.keys(dependencies).reduce((all, item) => {
|
|
const filterAttrs = [...new Set(dependencies[item])];
|
|
return all + `import {${filterAttrs + ","}} from '${item}';\n`;
|
|
}, "");
|
|
|
|
return reImport + content;
|
|
}
|
|
|
|
/**
|
|
* Extract part of the new string from the middle of the string
|
|
* @param {string} string string
|
|
* @param {string} prefix RegExp string
|
|
* @param {string} postfix RegExp string
|
|
* @param {string} type g | m | i
|
|
*/
|
|
function getInnerString(
|
|
string: string,
|
|
prefix: string,
|
|
postfix = "",
|
|
type: "i" | "g" | "m" = "i"
|
|
): string | undefined {
|
|
const result = new RegExp(`${prefix}(.*)${postfix}`, type);
|
|
const match = string.match(result);
|
|
return match ? match[1].trim() : undefined;
|
|
}
|
|
|
|
let script = ""; // Record the <script> label of the current page
|
|
|
|
export default {
|
|
render: (tokens: Token[], idx: number): string => {
|
|
// the `demo` block of the current page
|
|
const htmlBlock = tokens.filter((item) => item.type === "html_block");
|
|
const { nesting, info = "", map } = tokens[idx];
|
|
|
|
if (nesting === -1) {
|
|
return "</lay-code>";
|
|
}
|
|
|
|
const matchedInfo = info.trim().match(/^demo\s+(.*)$/);
|
|
const description = matchedInfo && matchedInfo[1];
|
|
const descTemplate = markdown().render(description || "");
|
|
let str = ""; // copy the current `demo` block code
|
|
let lastLine = NaN;
|
|
|
|
for (let i = 0; i < htmlBlock.length; i++) {
|
|
const item = htmlBlock[i];
|
|
|
|
if (item.map && map && item.map[0] >= map[0] && item.map[1] <= map[1]) {
|
|
const { map, content } = item;
|
|
const delta = map[0] - (lastLine || map[1]);
|
|
|
|
if (delta > 0) {
|
|
str += "\n".repeat(delta);
|
|
}
|
|
str += content;
|
|
lastLine = map[1];
|
|
if (i === 0) {
|
|
script = "";
|
|
}
|
|
// Remove top <template>
|
|
if (/^<template>/.test(content)) {
|
|
const reContent = content.match(/^<template>((\s|\S)*)<\/template>/m);
|
|
|
|
htmlBlock[i].content = (reContent && reContent[1]) || "";
|
|
}
|
|
// Extract the <script> label content
|
|
if (content.includes("<script")) {
|
|
if (/export\sdefault\s?\{/m.test(content)) {
|
|
const setup = content.match(
|
|
/setup\s?\(\)\s?\{((\s|\S)*)return\s?\{/m
|
|
);
|
|
const reContent = content.replace(
|
|
/export\sdefault\s?\{((\s|\S)*)\}/m,
|
|
(setup && setup[1]) || ""
|
|
);
|
|
const reScript = reContent.match(
|
|
/^<script\s?.*?>((\s|\S)*)<\/script>/m
|
|
);
|
|
script += (reScript && reScript[1]) || "";
|
|
} else {
|
|
const reScript = content.match(
|
|
/^<script\s?.*?>((\s|\S)*)<\/script>/m
|
|
);
|
|
script += (reScript && reScript[1]) || "";
|
|
}
|
|
htmlBlock[i].content = "";
|
|
}
|
|
// Change the last content to <script> of the current page
|
|
if (i + 1 === htmlBlock.length) {
|
|
htmlBlock[i].content = `
|
|
<script setup>
|
|
${assignScript(script)}
|
|
</script>`;
|
|
}
|
|
}
|
|
}
|
|
|
|
return `
|
|
<lay-code>
|
|
${description ? `<template #description>${descTemplate}</template>` : ""}
|
|
<template #code>${highlight(str, "vue")}</template>
|
|
`;
|
|
},
|
|
};
|