📝: chore: 补充文档

This commit is contained in:
sight
2022-06-28 14:07:44 +08:00
parent 21835edb61
commit 8ffb6723d1
6 changed files with 242 additions and 45 deletions

View File

@@ -6,7 +6,7 @@ button + button {
button {
height: 38px;
line-height: 36px;
padding: 0 18px;
padding: 0 18px !important;
color: #fff;
font-size: 14px;
text-align: center;

View File

@@ -5,7 +5,7 @@
</form>
</template>
<script setup>
const emit = defineEmits("add", "sub");
const emit = defineEmits(["add", "sub"]);
const add = () => {
emit("add");

View File

@@ -12,6 +12,7 @@
</div>
</div>
<div :class="{ 'is-fixed': isFixContorl }" class="control">
<i class="layui-icon layui-icon-play btn" @click="onPlayground" />
<i class="layui-icon layui-icon-file btn" @click="copy"></i>
<i class="layui-icon layui-icon-fonts-code btn" @click="toggle"></i>
</div>
@@ -20,6 +21,7 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from "vue";
import { usePlayGround } from "../composable/usePlayground";
const meta = ref<HTMLElement>({} as HTMLElement);
const isFixContorl = ref(false);
@@ -31,6 +33,13 @@ const toggle = function () {
show.value = !show.value;
};
const onPlayground = async function () {
const foundCode = meta.value.querySelector(".language-html");
const sourceCode = foundCode?.textContent ?? "";
const { link } = await usePlayGround(sourceCode, true);
window.open(link);
};
const copy = function () {
const foundCodes = meta.value.getElementsByClassName("language-html");
const foundCode = foundCodes[0];
@@ -64,7 +73,9 @@ const copy = function () {
}
if (successful) {
window.alert("复制成功");
} else {
window.alert("复制失败");
}
};

View File

@@ -0,0 +1,147 @@
import type { BuiltInParserName } from "prettier";
import { zlibSync, unzlibSync, strToU8, strFromU8 } from "fflate";
import extraCss from "../assets/css/index.css?raw";
const scriptRe = /<script[^>]*>([\s\S]*)<\/script>/;
const exportDefaultRe = /export\s*default\s*\{([\s\S]*)\}\;?\s*<\/script>/;
const setupRe = /setup\s*\(\)\s*\{([\s\S]*)return\s*\{([\s\S]*)\}\;?\s*\}\;?/;
const layerRe = /import\s*\{\s*layer\s*\}\s*from\s*[\"|\'][^\;\"\']*[\"|\']/;
const MAIN_FILE_NAME = "App.vue";
/**
* 将代码编码为 URI hash, 生成 playground 链接
* @param source 源码
* @param convertSetupSugar 转换 setup仅字符串替换没有做任何语法分析
* @returns 处理后的代码URI hsah playground 链接
}
*/
export const usePlayGround = async (
source: string,
convertSetupSugar: boolean
) => {
const decodeCode = source;
const scriptResult = decodeCode.match(scriptRe);
// 替换 script 标签
// $1 正则第一个括号匹配的内容
let code: string | undefined = decodeCode;
if (convertSetupSugar) {
if (scriptResult) {
code = decodeCode.replace(
scriptRe,
`<script lang="ts" setup>$1
</script>`
);
} else {
code = `${decodeCode}
<script lang="ts" setup>
</script>`;
}
// 去除 export default,保留其中的内容
const exportDefaultResult = code.match(exportDefaultRe);
if (exportDefaultResult) {
code = code.replace(
exportDefaultRe,
trimBr(exportDefaultResult[1] + `</script>`).trim()
);
// console.log("export",code);
}
// 去除 setup 函数,保留其中的内容
const setupResult = code.match(setupRe);
if (setupResult) {
code = code.replace(setupRe, trimBr(setupResult[1]));
// console.log("setup",code);
}
}
// 替换 layer 引入语句
// playground 中使用最新版 layer 请从 @layui/layer-vue 引入
if (code.match(layerRe)) {
code = code.replace(layerRe, `import { layer } from "@layui/layer-vue"`);
// console.log("layer",code);
}
code = await formatCode(MAIN_FILE_NAME, code);
const originCode = {
[MAIN_FILE_NAME]: code,
"index.css": extraCss,
};
const encoded = utoa(JSON.stringify(originCode));
const link = `https://layui-vue.gitee.io/sandbox-vue/#${encoded}`;
return {
code,
encoded,
link,
};
};
/**
*
* @returns 格式化代码
*/
async function formatCode(filename: string, data: string) {
const [format, parserHtml, parserTypeScript, parserBabel, parserPostcss] =
await Promise.all([
import("prettier/standalone").then((r) => r.format),
import("prettier/parser-html").then((m) => m.default),
import("prettier/parser-typescript").then((m) => m.default),
import("prettier/parser-babel").then((m) => m.default),
import("prettier/parser-postcss").then((m) => m.default),
]);
let code = data;
let parser: BuiltInParserName;
if (filename.endsWith(".vue")) {
parser = "vue";
} else if (filename.endsWith(".js")) {
parser = "babel";
} else if (filename.endsWith(".ts")) {
parser = "typescript";
} else if (filename.endsWith(".json")) {
parser = "json";
} else {
return;
}
code = format(code, {
parser,
plugins: [parserHtml, parserTypeScript, parserBabel, parserPostcss],
semi: false, // 语句末尾打印分号
singleQuote: true, // 使用单引号
vueIndentScriptAndStyle: false, // 是否缩进 Vue 文件中的 script 和 style 标签
});
return code;
}
/**
* 去除字符串两端的空白行
* @param str
* @returns
*/
function trimBr(str: string): string {
return str.replace(/(^[\r\n]*)|([\r\n]*$)/, "");
}
export function utoa(data: string): string {
const buffer = strToU8(data);
const zipped = zlibSync(buffer, { level: 9 });
const binary = strFromU8(zipped, true);
return btoa(binary);
}
export function atou(base64: string): string {
const binary = atob(base64);
// zlib header (x78), level 9 (xDA)
if (binary.startsWith("\x78\xDA")) {
const buffer = strToU8(binary, true);
const unzipped = unzlibSync(buffer);
return strFromU8(unzipped);
}
// old unicode hacks for backward compatibility
// https://base64.guru/developers/javascript/examples/unicode-strings
return decodeURIComponent(escape(binary));
}

View File

@@ -358,7 +358,7 @@ const closeAll = function() {
<legend>通讯</legend>
</fieldset>
::: demo 👉 查看 [Children1.vue](https://gitee.com/layui-vue/layer-vue/blob/master/example/src/components/Children1.vue), 通过 h() 函数的第二个参数向 Children1.vue 传递响应式变量。
::: demo 👉 查看 [Children1.vue](https://layui-vue.gitee.io/sandbox-vue/#eNqdUkGO00AQ/ErLFyeSY5OrSaJFK87LA3yZtTub2R3PjGba0UaWD5w4cUTiCDwA+AGfQZH4BT127HXEjZu7XNVTXd1t9Mba9NhglEcbwtoqQbgrNMDmviEyGm5KJcunbREZi/rW1NZo1LQuot3508/zx++bbCAOIqltQ0Ani6wgfKYiguOqNhUqBipBInVYC/fEeMaSTTY9CoXm2pdOWgIl9EPo4JnnkRrLXMlvO4IWHIqS5BETOCRceKOOODmDDvbO1BDzUPFMpMQJ3fTzhstGZj24umLeHqSqHOo7jRdumo3YOiTFVOi9lkZ7gjATbCdPizb8HmbMIf796+v5/Y84KXS3fNFcR8nqxRK2O+ilvaU0MIZWACRJIfc6f/nw59vn0Cug3IlYncNhMbOc8KS9o2554fmDqFi9F8pjDwUjXUh+iJqDjZJoGH5VC5s+eqP5GtriAvIK8rbrmHQVw78Hszeu7r/+4w5Ykl30s5N4uYfxBsYEsZbEuVW4lxrfcuEXcSmUwiqe5WydsX6ivQvVEGowkMPd/SOWNK5mFkh4l04KwZe8iIqR4G3YjxVVJfVDDutX9vn1GGVg76LuL+G7LGU=), 通过 h() 函数的第二个参数向 Children1.vue 传递响应式变量。
<template>
<button @click="openComponent1">数据</button>
@@ -384,7 +384,7 @@ const openComponent1 = () => {
:::
::: demo 👉 查看 [Children2.vue](https://gitee.com/layui-vue/layer-vue/blob/master/example/src/components/Children2.vue), 通过 h() 函数的第二个参数声明 onXxx() 形式的函数完成 Children2.vue 的事件监听。
::: demo 👉 查看 [Children2.vue](https://layui-vue.gitee.io/sandbox-vue/#eNqNksFum0AQhl9lxAWsYmPnSG2UKOoTtLfSA4Yh3hZ2VzC4sRDnSO2h1x6jPkQP7esklfoWnQXWAaWHcGJmv5n9d+ZvnSutV8cGndDZEpa6SAijWAJs9w2RknCZFiL9tIsdpVFeq1IriZIuYid6+PX14ffPbTCAQ5GQuiGgk0auILyl2IHjslQZFpyQTbnnRMDsNpjcxmGdVkITFIm8MZU1YzVSo/lU8J0VQQsVJimJI/pw8DnIoYO8UiW4rN+dcEVywup8eMlhI4I+uZyR1wdRZBXKd5/VyK4Cm7swQ2E0lqmSNYGulIbdWYLXdgt7ZF7VH+XeZr1ec96ezEfGjLeAXQStGVWvZ2UIr48BSFCBIbh/7u/+/vju+kOWOxFXh3DwJnr9oYn5jLKRBVDyKsu8CuvFEwC9wtUxKRpkDZPgFWws1E1avG32L26xfN6iW/Q/ZkCdWfSwWl6k4zvD5JdlolcfayXZdW08JnnlYdt1DM128NyYuarK/u/JpKPhhoitczZtkmXs1Mcv9zObvqCwbtip0ePdt7m/g/HymX2tea1h7fqxFMTTyjAXEt9wUHvvXVbk+i63dz9MnMLZuT2gr/Z6fBikRbn0/6jpadHJ1I0+OhUIdcpuyzhj3jCUam4v5E0Im7W+fW33ZejI6f4B7opkgw==), 通过 h() 函数的第二个参数声明 onXxx() 形式的函数完成 Children2.vue 的事件监听。
<template>
<button @click="openComponent2">事件</button>