423 lines
13 KiB
TypeScript
423 lines
13 KiB
TypeScript
import { Component, useRef } from 'react';
|
||
import { Input } from 'antd';
|
||
import { Button, Flex, Modal, Space } from 'antd';
|
||
// import Taro from "@tarojs/taro";
|
||
// import {
|
||
// View,
|
||
// Text,
|
||
// Image,
|
||
// Button,
|
||
// Input,
|
||
// Editor,
|
||
// Textarea,
|
||
// } from "@tarojs/components";
|
||
// import './APP.scss';
|
||
import styles from './App.module.scss';
|
||
|
||
// import { AtTabBar } from "taro-ui";
|
||
import React, { useCallback, useEffect, useState } from 'react';
|
||
// import { AtGrid } from "taro-ui";
|
||
// import { Swiper, SwiperItem } from "@tarojs/components";
|
||
// import { AtCard } from "taro-ui";
|
||
// import { AtImagePicker } from "taro-ui";
|
||
// import { AtButton } from "taro-ui";
|
||
// import { AtSearchBar } from "taro-ui";
|
||
// import { Picker } from "@tarojs/components";
|
||
// import { AtList, AtListItem } from "taro-ui";
|
||
// import { AtNavBar } from "taro-ui";
|
||
// import { AtModal, AtModalHeader, AtModalContent, AtModalAction } from "taro-ui";
|
||
// import { AtToast } from "taro-ui";
|
||
// import { AtIcon } from "taro-ui";
|
||
import see from '../../images/see.png';
|
||
import group from '../../images/group.png';
|
||
import { marked } from 'marked';
|
||
// import _ from "lodash";
|
||
import OriginMark from './conpoments/OriginMark/index';
|
||
import TextArea from 'antd/es/input/TextArea';
|
||
|
||
// marked.use(`marked-code-jsx-renderer`);
|
||
// marked.use(`marked-extended-tables`);
|
||
|
||
// 
|
||
|
||
const createDecoratedTitleHTML = (text: any) => {
|
||
const padding = 2; // 内容左右两边的空格数
|
||
const lineChar = '─'; // 水平线字符
|
||
const edgeChar = '━'; // 边框装饰字符
|
||
const cornerTopLeft = '╔';
|
||
const cornerTopRight = '╗';
|
||
const cornerBottomLeft = '╚';
|
||
const cornerBottomRight = '╝';
|
||
|
||
// 计算标题长度
|
||
const titleLength = text.length + padding * 2;
|
||
const lineLength = lineChar.repeat(titleLength);
|
||
const edgeLength = edgeChar.repeat(titleLength);
|
||
|
||
// 构造 HTML
|
||
const topBorder = `${cornerTopLeft}${edgeLength}${cornerTopRight}`;
|
||
const bottomBorder = `${cornerBottomLeft}${edgeLength}${cornerBottomRight}`;
|
||
const middleLine = ` 📢 ${text}`;
|
||
|
||
return `<div>${topBorder}<br/>${middleLine}<br/>${bottomBorder}</div><br/>\n`;
|
||
};
|
||
|
||
marked.setOptions({
|
||
breaks: true, // 是否回车换行
|
||
gfm: true, //使用经批准的 GitHub Flavored Markdown (GFM) 规范
|
||
// pedantic: true, //严格模式
|
||
// highlight(code:any, lang:any) {
|
||
// // 语法高亮
|
||
// let val = code;
|
||
// if (lang) {
|
||
// val = hljs.highlight(lang, code).value;
|
||
// } else {
|
||
// val = hljs.highlightAuto(code).value;
|
||
// }
|
||
// return val;
|
||
// },
|
||
});
|
||
// 符号
|
||
// 🔥❓👉
|
||
// 0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟
|
||
// ©️⭐🔍〰️➖
|
||
|
||
// 修改 marked 的解析规则
|
||
// const block = marked.Lexer.rules.block;
|
||
// block.gfm.hr = /^( *[-*_]){3,} *(?:\n+|$)/;
|
||
// 自定义水平线规则,确保它们在文档中被正确识别
|
||
// block.gfm.hr =
|
||
// /^ {0,3}(?:(?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
|
||
|
||
const renderer = new marked.Renderer();
|
||
// const originRenderer = _.cloneDeep(renderer);
|
||
|
||
// 图片调整300px
|
||
renderer.image = function (href, title, text) {
|
||
// console.log("href, title, text", href, title, text);
|
||
// <div class="desc">${text}</div>
|
||
return `<img width="300px" src="${href}" alt="${text}"/>`;
|
||
};
|
||
|
||
// let listSinbal="▫️ "
|
||
let listSinbal = '🔸';
|
||
|
||
// 有序列表
|
||
renderer.list = function (body, ordered, start) {
|
||
// console.log("body,ordered, start", body, ordered, start);
|
||
const type = ordered ? 'ol' : 'ul';
|
||
// console.log("type===>", type);
|
||
const startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
|
||
// 正则取值
|
||
// const regex = /▫️\s*(.*?)<br\/?>/g;
|
||
const regex = /([^<]*)<br\/?>/g;
|
||
const input = body;
|
||
const matches = [...input.matchAll(regex)];
|
||
const texts = matches.map((match) => match[1]);
|
||
// 不含▫️的元素数量
|
||
// const diffcCount=texts.length-texts.filter(item => item.includes('▫️')).length;
|
||
// console.log("texts===>", texts); // 输出: ["测试111", "测试222", "if"]
|
||
const newArray = texts.filter((item) => item.includes(listSinbal));
|
||
// 0️⃣',
|
||
const numbers = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'];
|
||
|
||
const string = texts
|
||
.map((value, index) => {
|
||
// console.log("value, index==>", value, index);
|
||
// ${ value.indexOf("▫️ ") === -1 ? '<br/><span>111</sapn>' : ""}
|
||
return value.indexOf(listSinbal) !== -1
|
||
? `<div>${
|
||
type === 'ol' ? numbers[newArray.indexOf(value)] : listSinbal
|
||
}${value.replace(listSinbal, '')} </div>`
|
||
: `<div style="white-space:pre;">\t${value}</div>`;
|
||
})
|
||
.join('');
|
||
// return `1️⃣`
|
||
// console.log("string===>", string);
|
||
|
||
return `${string}`;
|
||
};
|
||
|
||
// 无序列表 ▫️
|
||
renderer.listitem = function (text, task, checked) {
|
||
// return `<li>${text}</li>\n`;
|
||
return `${listSinbal}${text}<br/>`;
|
||
// return `➖${text}<br/>`;
|
||
};
|
||
|
||
// 任务列表
|
||
renderer.checkbox = function (checked) {
|
||
// ✅❌
|
||
return !!checked ? '✅' : '❌';
|
||
return (
|
||
'<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox">'
|
||
);
|
||
};
|
||
|
||
// 标题
|
||
renderer.heading = function (text, level, raw) {
|
||
console.log('text, level, raw', text, level, raw);
|
||
// ignore IDs
|
||
// return `📋<span>${text}</span> <br/>`;
|
||
// return `🔥<span>${text}</span> <br/>`;
|
||
if (level == 1) {
|
||
return createDecoratedTitleHTML(text);
|
||
} else if (level == 2) {
|
||
return `<div>🔥${text}</div>\n`;
|
||
} else {
|
||
return `<div>🔥${text}</div>\n`;
|
||
}
|
||
|
||
return `<div>╔═━──────━═╗<br/>
|
||
🔥 ${text}<br/>
|
||
╚═━──────━═╝
|
||
</div>\n`;
|
||
|
||
// return `<div>* * * * * * * * * * *<br/>
|
||
// * ${text} *<br/>
|
||
// * * * * * * * * * * *
|
||
// </div>\n`;
|
||
|
||
// return `<div>==================<br/>
|
||
// || 📢 ${text} 📢 ||<br/>
|
||
// ==================</div>\n`;
|
||
|
||
// return `<h${level}>🔥<span>${text}</span></h${level}>\n`;
|
||
// return `<h${level}>🔥${text}</h${level}><br/>`;
|
||
};
|
||
|
||
renderer.text = function (text) {
|
||
return text;
|
||
};
|
||
|
||
// 分隔符
|
||
renderer.hr = function () {
|
||
// return '<hr>\n';
|
||
// return '➖➖➖➖➖<br/>';
|
||
return '➖➖➖➖➖\n';
|
||
};
|
||
|
||
// 自定义分隔线解析规则
|
||
// marked.Lexer.rules.block.gfm.hr = /^(\*{3,}|-{3,}|_{3,})(?:\s*)$/;
|
||
// hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
|
||
|
||
// 内联样式,使用直角引号「」
|
||
renderer.codespan = function (text) {
|
||
// return `「${text}」`;
|
||
return `『${text}』`;
|
||
};
|
||
|
||
// 引用符号
|
||
renderer.blockquote = function (quote) {
|
||
// console.log("quote", quote);
|
||
let content = null;
|
||
// var regex = /<p>(.*?)<\/p>/;
|
||
var regex = /<div>(.*?)<\/div>/;
|
||
|
||
var str = quote;
|
||
var match = regex.exec(str);
|
||
if (match != null) {
|
||
content = match[1]; // 获取第一个捕获组的内容
|
||
// console.log(content);
|
||
}
|
||
// <pre></pre>
|
||
//
|
||
// return `<span style="white-space:pre;" class="blockquote">\t 👉${content}</span><br/> `
|
||
// return `<div style="white-space:pre;" class="blockquote">\t 📌${content}</div>\n`; //ok
|
||
// ├─
|
||
return `<div style="white-space:pre;" class="blockquote">            └─📌${content}</div>`;
|
||
};
|
||
|
||
renderer.table = function (header, body) {
|
||
if (body) body = `<tbody>${body}</tbody>`;
|
||
|
||
return (
|
||
'📊 表格 📊<br/><table>\n' +
|
||
'<thead>\n' +
|
||
header +
|
||
'</thead>\n' +
|
||
body +
|
||
'</table>\n'
|
||
);
|
||
};
|
||
|
||
renderer.tablerow = function (content) {
|
||
return `<tr>\n${content}</tr>\n`;
|
||
};
|
||
|
||
renderer.tablecell = function (content, flags) {
|
||
const type = flags.header ? 'th' : 'td';
|
||
const tag = flags.align ? `<${type} align="${flags.align}">` : `<${type}>`;
|
||
return tag + `|${content}` + `</${type}>\n`;
|
||
};
|
||
|
||
function cleanUrl(href: any) {
|
||
try {
|
||
href = encodeURI(href).replace(/%25/g, '%');
|
||
} catch (e) {
|
||
return null;
|
||
}
|
||
return href;
|
||
}
|
||
|
||
renderer.link = function (href, title, text) {
|
||
const cleanHref = cleanUrl(href);
|
||
if (cleanHref === null) {
|
||
return text;
|
||
}
|
||
href = cleanHref;
|
||
let out = '<a href="' + href + '"';
|
||
if (title) {
|
||
out += ' title="' + title + '"';
|
||
}
|
||
out += '>' + `🌐` + text + '</a>';
|
||
// out += ">" +`🌐`+ text + "</a>"+`(${href})`;
|
||
|
||
return out;
|
||
};
|
||
|
||
renderer.paragraph = function (text) {
|
||
// return `<p>${text}</p>\n`;
|
||
// return `<p>${text}</p>`;
|
||
return `<div>${text}</div>`;
|
||
};
|
||
renderer.br = function () {
|
||
return '<br>';
|
||
};
|
||
renderer.html = function (html, block) {
|
||
return html;
|
||
};
|
||
|
||
// 使用拓展
|
||
marked.use({ renderer });
|
||
|
||
// export default class Index extends Component {
|
||
const Index = () => {
|
||
const divRef = useRef(null);
|
||
const [inputValue, setinputValue] = useState('');
|
||
const [markText, setmarkText] = useState(``);
|
||
|
||
const [oldmarkText, setoldmarkText] = useState(null);
|
||
const [currentRender, setcurrentRender] = useState(null);
|
||
const [markdownTable, setmarkdownTable] = useState();
|
||
const [tablecellArr, settablecellArr] = useState([]);
|
||
|
||
const onConfirm = (onConfirmtxt: any) => {
|
||
console.log('onConfirmtxt--->', onConfirmtxt.detail.value);
|
||
};
|
||
const onBlur = (onBlurtxt: any) => {
|
||
console.log('onBlurtxt--->', onBlurtxt.detail.value);
|
||
if (onBlurtxt.detail.value) {
|
||
setmarkText(onBlurtxt.detail.value);
|
||
}
|
||
};
|
||
const onInput = (onInputtxt: any) => {
|
||
console.log('onInputtxt--->', onInputtxt?.target?.value);
|
||
setinputValue(onInputtxt.target.value);
|
||
// console.log('inputValue',inputValue)
|
||
// let value = onInputtxt?.target?.value;
|
||
let value = onInputtxt?.target?.value;
|
||
|
||
if (value?.length > 10) {
|
||
// +`🅥🟢🆔:hackrobot`
|
||
// +`➕🅥=>🟩🆔: hackrobot,可以找我聊天💬 `
|
||
// let contactMe=`<br>➖➖➖➖➖<br/>在🟩【wΞ𝗫𝗜𝗡】➡️联系我 【➕🅥】:
|
||
// ╭────────────────╮
|
||
// │ 🆔 hackrobot
|
||
// ╰────────────────╯
|
||
// 💬 随时欢迎聊天
|
||
// `
|
||
|
||
// │ 💬 随时欢迎聊天
|
||
let contactMe = `<br>╭────────────────╮
|
||
│ 🟩【wΞ𝗫𝗜𝗡】➡️联系我【➕🅥】
|
||
│
|
||
│ 🆔 hackrobot
|
||
╰────────────────╯<br>💬 随时欢迎聊天`;
|
||
|
||
if (value?.length < 10) {
|
||
setmarkText(value);
|
||
} else {
|
||
setmarkText(value + contactMe);
|
||
}
|
||
}
|
||
};
|
||
|
||
useEffect(() => {}, []);
|
||
|
||
const copyToClipboard = () => {
|
||
if (divRef.current) {
|
||
const htmlContentinnerHTML = divRef.current.innerHTML;
|
||
console.log('htmlContentinnerHTML', htmlContentinnerHTML);
|
||
const htmlContentouterHTML = divRef.current.outerHTML;
|
||
console.log('htmlContentouterHTML', htmlContentouterHTML);
|
||
|
||
const htmlContent = divRef.current.innerText;
|
||
// const htmlContent = divRef.current.textContent;
|
||
|
||
navigator.clipboard
|
||
.writeText(htmlContent)
|
||
.then(() => {
|
||
// alert('Content copied to clipboard!');
|
||
})
|
||
.catch((err) => {
|
||
console.error('Error copying text: ', err);
|
||
});
|
||
}
|
||
};
|
||
|
||
const info = () => {
|
||
Modal.info({
|
||
title: 'This is a notification message',
|
||
content: (
|
||
<div>
|
||
<p>some messages...some messages...</p>
|
||
<p>some messages...some messages...</p>
|
||
</div>
|
||
),
|
||
onOk() {},
|
||
});
|
||
};
|
||
|
||
return (
|
||
<div className={styles.index}>
|
||
<div className={styles.up}>
|
||
<div className={styles.upLeft}>
|
||
{/* <Button type="text" danger>
|
||
公众号: 异度世界
|
||
</Button> */}
|
||
</div>
|
||
<div className={styles.upRight}>
|
||
{/* <button onClick={copyToClipboard}>Copy to Clipboarrd</button> */}
|
||
{/* <Button type="primary" onClick={copyToClipboard}>复制</Button> */}
|
||
<Button onClick={copyToClipboard}>复制</Button>
|
||
</div>
|
||
</div>
|
||
<div className={styles.down}>
|
||
<div className={styles.left}>
|
||
<TextArea
|
||
// styles="background:#fff;width:100%;min-height:80px;padding:0 30rpx;"
|
||
className={styles.TextArea}
|
||
autoFocus
|
||
allowClear
|
||
onChange={onInput}
|
||
showCount
|
||
/>
|
||
</div>
|
||
<div className={styles.right}>
|
||
<div
|
||
className={styles.rightHtml}
|
||
ref={divRef}
|
||
dangerouslySetInnerHTML={{ __html: marked(markText) }}
|
||
></div>
|
||
</div>
|
||
{/* <div className="origin">
|
||
<OriginMark markText={markText} />
|
||
</div> */}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Index;
|