<script setup lang="ts">
import {Marked} from 'marked';
// 默认导入所有语言
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-light.css';
import DOMPurify from 'dompurify';
import markedFootnote from 'marked-footnote'
import markedCodeFormat from 'marked-code-format'
import { markedEmoji } from 'marked-emoji';

const marked = new Marked();


// 自定义行号注入函数
const injectLineNumbers = (highlightedCode: string) => {
    const lines = highlightedCode.split('\n')

    // 移除最后一行空行（常见于代码块末尾的换行）
    if (lines[lines.length - 1] === '') lines.pop()

    // 为每行添加行号容器
    return lines.map((line, index) => `<div class="code-line"><span class="line-number">${index + 1}</span><span class="line-content">${line}</span></div>`).join('')
}

marked.use({
    async: true,
    pedantic: false,
    gfm: true,
    silent: false,
    breaks: false,
    renderer: {
        code: ({text, lang}) => {
            // console.log(text);
            const validLang = hljs.getLanguage(lang) ? lang : 'plaintext'
            const highlighted = hljs.highlight(text, {language: lang}).value
            // console.log(highlighted)
            const withLineNumbers = injectLineNumbers(highlighted)
            return `<pre class="hljs ${validLang}"><code>${withLineNumbers}</code></pre>`;
        }
    }
})
// 支持脚注[^1] 会影响原始文本
marked.use(markedFootnote())
marked.use(markedCodeFormat({
            /* Prettier options */
        }))

const markedEmojiOptions = {
    emojis: {
        "heart": "❤️",
        "tada": "🎉"
    },
    renderer: (token) => {
        console.log(token)
        return token.emoji
    }
};
marked.use(markedEmoji(markedEmojiOptions))

const content = ref(`
# Hello Vue 3!

AAA
AAA

BBB
B

Hello :smile:

- [ ]  xsxs

I :heart: marked! :tada:

## 脚注

这是标记[^1]

[^1]: This is a footnote content.

Here is a simple footnote[^1]. With some additional[^3] text after it[^@#$%] and without disrupting the blocks[^3].

[^2]: The first paragraph of the definition2.

[^3]: The first paragraph of the definition3.

[^4]: ABC

**Markdown 内容示例：**

1. 潇洒些
2. 下洒下阿萨[^4]

3. 想啊伤心啊伤心啊
    1. 下洒下阿萨
    2. 下洒下阿萨
        a. sxaas
        b. xsaxa
        c. xsaxa
            - xasx
            - cascade

1. 潇洒些
2. 下洒下阿萨
3. 想啊伤心啊伤心啊
    1. 下洒下阿萨
    2. 下洒下阿萨
        a. sxaas
        b. xsaxa
        c. xsaxa
            - xasx
            - cascade

> 引用

- 列表项
- 另一项

\`\`\`javascript
// 代码块示例
function greet() {
  console.log('Hello marked!');
}
\`\`\`
| 参数         | \t类型      | \t作用                                          | \t默认值            |
|:-----------|:---------|:---------------------------------------------|:----------------|
| breaks     | \tboolean | \t将换行符 \\n 渲染为 <br>（类似 GitHub）                  | \tfalse         |
| gfm        | \tboolean | \t启用 GitHub Flavored Markdown 扩展（表格、删除线等）     | \ttrue           |
| headerIds\t | boolean  | \t自动为标题添加 id 属性（如 \`<h1 id="hello-world"></h1>\`） | \ttrue           |
| highlight\t | function | \t代码高亮处理函数，需返回高亮后的 HTML                       | \tnull           |
| renderer\t  | object   | \t自定义渲染器对象（覆盖默认渲染逻辑）                          | \tnew Renderer() |
| sanitize\t  | boolean  | \t过滤危险 HTML 标签（防止 XSS 攻击）                     | \tfalse          |
| sanitizer\t | function | \t自定义 HTML 过滤函数                               | \t-              |
| silent\t    | boolean  | \t静默模式：忽略解析错误（如未闭合的代码块）                       | \tfalse          |
`);
// 使用编译
async function make(contents: string){
    // 过滤不能识别，难识别的字符，空字符
    let content = contents.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/,"");
    // 编译
    content = await marked.parse(content)
    // 加强安全，防止xss攻击
    content = DOMPurify.sanitize(content);
    return content
}

const compiledMarkdown = ref(await make(content.value));

const editableDiv = ref(null);  // 绑定可编辑的 div
const rawText = ref("");         // 存储纯文本内容

// 实时监听输入事件
const handleInput = async (event) => {
    if (editableDiv.value) {
        // 直接获取去标签后的纯文本
        rawText.value = editableDiv.value.innerText.trim().replace(/  /g, '  ');
        console.log(rawText.value)
        compiledMarkdown.value = await make(rawText.value);
    }
};

// 手动获取内容（通过按钮触发）
const getContent = () => {
    if (editableDiv.value) {
        const text = editableDiv.value.innerText.trim();
        console.log("手动获取:", text);
    }
};

// 处理粘贴内容（自动去除粘贴的 HTML 标签）
const handlePaste = (event) => {
    event.preventDefault(); // 阻止默认粘贴行为
    const text = event.clipboardData.getData("text/plain"); // 获取纯文本
    document.execCommand("insertText", false, text);       // 插入纯文本
};
onMounted(async () => {

    const worker = new Worker(new URL("~/assets/workers/example.worker.js", import.meta.url));
    worker.postMessage("Hello Worker");

    worker.onmessage = (e) => {
        console.log(e)
        worker.terminate();
    };
})
</script>
<template>
    <div class="NiMarked">
        <div class="inputMarkdown"
             ref="editableDiv"
             contenteditable="true"
             @input="handleInput"
             @paste="handlePaste"
        ></div>
        <div
            ref="markdownContainer"
            class="markdown-content"
            v-html="compiledMarkdown"
        />
    </div>
</template>

<style scoped lang="scss">
.NiMarked{
    position: relative;
    display: flex;
    height: 100%;
    overflow: hidden;
}
.NiMarked>div{
    outline: none;
    border: 1px solid var(--Ni-theme-border-color);
}
.inputMarkdown{
    position: relative;
    height: 100%;
    flex: 1;
    overflow: auto;
}
.markdown-content {
    position: relative;
    height: 100%;
    flex: 1;
    overflow: auto;
    // 基础样式...

    /* 代码块样式 */
    :deep(pre) {
        white-space: pre-wrap;
        background: #cdcdcd;
        padding: 15px;
        border-radius: 5px;

        code {
            font-family: 'Consolas', 'Fira Code', monospace;
            font-size: 14px;
            line-height: 1.5;
            white-space: pre;
        }

        /* 确保代码块正确换行 */
        code {
            display: block;
            overflow-x: auto;
            padding: 1em;
        }

        .code-line {
            display: flex;
            min-height: 1em; /* 防止空行高度塌陷 */
        }

        .line-number {
            width: 40px;
            padding-right: 12px;
            color: #666;
            text-align: right;
            user-select: none;
            flex-shrink: 0;
        }

        .line-content {
            flex-grow: 1;
            white-space: pre-wrap; /* 允许代码换行 */
        }


    }
}
</style>
