- 添加 .editorconfig 文件统一代码风格 - 配置 .env.development 环境变量文件 - 创建 .env.example 环境变量示例文件 - 设置 .eslintignore 忽略检查规则 - 配置 .eslintrc.js 代码检查规则 - 添加 .gitignore 文件忽略版本控制 - 设置 .prettierignore 忽略格式化规则 - 新增隐私政策HTML页面文件 - 创建API密钥编辑组件基础结构
94 lines
1.9 KiB
Vue
94 lines
1.9 KiB
Vue
<!-- markdown 解析 -->
|
|
<template>
|
|
<!-- eslint-disable vue/no-v-html -->
|
|
<div
|
|
ref="rootRef"
|
|
v-html="content"
|
|
class="markdown-body"
|
|
@click="handleClick"
|
|
>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
|
import type { BytemdPlugin } from 'bytemd';
|
|
import { getProcessor } from 'bytemd';
|
|
|
|
const props = defineProps<{
|
|
value: string;
|
|
plugins?: BytemdPlugin[];
|
|
sanitize?: (schema: any) => any;
|
|
}>();
|
|
|
|
const rootRef = ref<HTMLElement | null>(null);
|
|
const content = ref<any | null>(null);
|
|
const cbs = ref<(void | (() => void))[]>([]);
|
|
|
|
const on = () => {
|
|
if (props.plugins && rootRef.value && content.value) {
|
|
cbs.value = props.plugins.map(({ viewerEffect }) => {
|
|
return (
|
|
viewerEffect &&
|
|
viewerEffect({
|
|
markdownBody: rootRef.value as HTMLElement,
|
|
file: content.value
|
|
})
|
|
);
|
|
});
|
|
}
|
|
};
|
|
|
|
const off = () => {
|
|
if (cbs.value) {
|
|
cbs.value.forEach((cb) => cb && cb());
|
|
}
|
|
};
|
|
|
|
const handleClick = (e: MouseEvent) => {
|
|
const $ = e.target as HTMLElement;
|
|
if ($.tagName !== 'A') {
|
|
return;
|
|
}
|
|
|
|
const href = $.getAttribute('href');
|
|
if (!href || !href.startsWith('#')) {
|
|
return;
|
|
}
|
|
|
|
const dest = rootRef.value?.querySelector('#user-content-' + href.slice(1));
|
|
if (dest) {
|
|
dest.scrollIntoView();
|
|
}
|
|
};
|
|
|
|
watch(
|
|
[() => props.value, () => props.plugins, () => props.sanitize],
|
|
() => {
|
|
try {
|
|
content.value = getProcessor({
|
|
plugins: props.plugins,
|
|
sanitize: props.sanitize
|
|
}).processSync(props.value);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
off();
|
|
nextTick(() => {
|
|
on();
|
|
});
|
|
},
|
|
{
|
|
immediate: true
|
|
}
|
|
);
|
|
|
|
onMounted(() => {
|
|
on();
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
off();
|
|
});
|
|
</script>
|