135 lines
4.7 KiB
JavaScript
135 lines
4.7 KiB
JavaScript
import MarkdownIt from '@/lib/markdown-it.min.js';
|
|
import hljs from "@/lib/highlight/highlight-uni.min.js";
|
|
import parseHtml from '@/lib/html-parser.js';
|
|
// import DOMPurify from '@/lib/dompurify@3.2.4es.js';
|
|
|
|
export let codeDataList = []
|
|
export let jobMoreMap = new Map()
|
|
|
|
const md = new MarkdownIt({
|
|
html: true, // 允许 HTML 标签
|
|
linkify: true, // 自动解析 URL
|
|
typographer: true, // 美化标点符号
|
|
tables: true,
|
|
breaks: true, // 让 \n 自动换行
|
|
langPrefix: 'language-', // 代码高亮前缀
|
|
// 如果结果以 <pre ... 开头,内部包装器则会跳过。
|
|
highlight: function(str, lang) {
|
|
if (lang === 'job-json') {
|
|
const result = safeExtractJson(str);
|
|
if (result) { // json解析成功
|
|
const jobId = result.appJobUrl.split('jobId=')[1]
|
|
let domContext = `
|
|
<a class="custom-card" data-job-id="${jobId}">
|
|
<div class="card-title">
|
|
<span class="title-text" >${result.jobTitle}</span>
|
|
<div class="card-salary">${result.salary}</div>
|
|
</div>
|
|
<div class="card-company">${result.location}·${result.companyName}</div>
|
|
<div class="card-info">
|
|
<div class="info-item">
|
|
<div class="card-tag">${result.education}</div>
|
|
<div class="card-tag">${result.experience}</div>
|
|
</div>
|
|
<div class="info-item">查看详情<div class="position-nav"></div></div>
|
|
</div>
|
|
</a>
|
|
`
|
|
if (result.data) {
|
|
jobMoreMap.set(jobId, result.data)
|
|
domContext +=
|
|
`<a class="custom-more" data-job-id="${jobId}">查看更多岗位<div class="more-icon"></div></a>`
|
|
}
|
|
return domContext
|
|
}
|
|
}
|
|
// <div class="card-tag">${result.location}</div>
|
|
// <div class="info-item">${result.salary}</div>
|
|
// 代码块
|
|
let preCode = ""
|
|
try {
|
|
preCode = hljs.highlightAuto(str).value
|
|
} catch (err) {
|
|
preCode = markdownIt.utils.escapeHtml(str);
|
|
}
|
|
// 以换行进行分割 , 按行拆分代码
|
|
const lines = preCode.split(/\n/).slice(0, -1);
|
|
const html = lines
|
|
.map((line, index) =>
|
|
line ?
|
|
`<li><span class="line-num" data-line="${index + 1}"></span>${line}</li>` :
|
|
''
|
|
)
|
|
.join('');
|
|
|
|
// 代码复制功能
|
|
const cacheIndex = codeDataList.length;
|
|
codeDataList.push(str);
|
|
return `
|
|
<div class="code-container">
|
|
<div class="code-header">
|
|
<span class="lang-label">${lang || 'plaintext'}</span>
|
|
<a class="copy-btn" data-copy-index="${cacheIndex}">复制代码</a>
|
|
</div>
|
|
<pre class="hljs"><code><ol>${html}</ol></code></pre>
|
|
</div>
|
|
`;
|
|
}
|
|
})
|
|
|
|
function extractFirstJson(text) {
|
|
let stack = [];
|
|
let startIndex = -1;
|
|
let endIndex = -1;
|
|
|
|
for (let i = 0; i < text.length; i++) {
|
|
const char = text[i];
|
|
|
|
if (char === '{') {
|
|
if (stack.length === 0) startIndex = i; // 记录第一个 '{' 的位置
|
|
stack.push(char);
|
|
} else if (char === '}') {
|
|
stack.pop();
|
|
if (stack.length === 0) {
|
|
endIndex = i; // 找到配对的 '}'
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (startIndex !== -1 && endIndex !== -1) {
|
|
const jsonString = text.slice(startIndex, endIndex + 1);
|
|
try {
|
|
const jsonObject = JSON.parse(jsonString);
|
|
return jsonObject;
|
|
} catch (e) {
|
|
return null; // 如果不是有效的 JSON
|
|
}
|
|
}
|
|
|
|
return null; // 如果没有找到有效的 JSON 对象
|
|
}
|
|
|
|
|
|
function safeExtractJson(text) {
|
|
try {
|
|
const jsonObject = extractFirstJson(text);
|
|
return jsonObject
|
|
} catch (e) {
|
|
console.error('JSON 解析失败:', e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function clearJobMoreMap() { // 切换对话清空
|
|
jobMoreMap.clear()
|
|
}
|
|
|
|
export function parseMarkdown(content) {
|
|
if (!content) {
|
|
return //处理特殊情况,比如网络异常导致的响应的 content 的值为空
|
|
}
|
|
codeDataList = []
|
|
const unsafeHtml = md.render(content || '')
|
|
return unsafeHtml
|
|
} |