禁用打开页面时弹窗

This commit is contained in:
liushuang 2024-08-06 10:13:26 +08:00
parent 200e9d06bb
commit 5a24639b69
3 changed files with 152 additions and 85 deletions

1
.gitignore vendored

@ -1,5 +1,6 @@
# Node dependencies # Node dependencies
node_modules node_modules
build
# Logs # Logs
logs logs

@ -1,9 +1,9 @@
import React, {Component} from "react"; import React, { Component } from "react";
import CodeMirror from "@uiw/react-codemirror"; import CodeMirror from "@uiw/react-codemirror";
import "codemirror/addon/search/searchcursor"; import "codemirror/addon/search/searchcursor";
import "codemirror/keymap/sublime"; import "codemirror/keymap/sublime";
import "antd/dist/antd.css"; import "antd/dist/antd.css";
import {observer, inject} from "mobx-react"; import { observer, inject } from "mobx-react";
import classnames from "classnames"; import classnames from "classnames";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
@ -25,13 +25,17 @@ import {
IMAGE_HOSTING_NAMES, IMAGE_HOSTING_NAMES,
IMAGE_HOSTING_TYPE, IMAGE_HOSTING_TYPE,
MJX_DATA_FORMULA, MJX_DATA_FORMULA,
MJX_DATA_FORMULA_TYPE, MJX_DATA_FORMULA_TYPE
} from "./utils/constant"; } from "./utils/constant";
import {markdownParser, markdownParserWechat, updateMathjax} from "./utils/helper"; import {
markdownParser,
markdownParserWechat,
updateMathjax
} from "./utils/helper";
import pluginCenter from "./utils/pluginCenter"; import pluginCenter from "./utils/pluginCenter";
import appContext from "./utils/appContext"; import appContext from "./utils/appContext";
import {uploadAdaptor} from "./utils/imageHosting"; import { uploadAdaptor } from "./utils/imageHosting";
import bindHotkeys, {betterTab, rightClick} from "./utils/hotkey"; import bindHotkeys, { betterTab, rightClick } from "./utils/hotkey";
@inject("content") @inject("content")
@inject("navbar") @inject("navbar")
@ -46,7 +50,7 @@ class App extends Component {
this.scale = 1; this.scale = 1;
this.handleUpdateMathjax = throttle(updateMathjax, 1500); this.handleUpdateMathjax = throttle(updateMathjax, 1500);
this.state = { this.state = {
focus: false, focus: false
}; };
} }
@ -60,25 +64,25 @@ class App extends Component {
tex: { tex: {
inlineMath: [["$", "$"]], inlineMath: [["$", "$"]],
displayMath: [["$$", "$$"]], displayMath: [["$$", "$$"]],
tags: "ams", tags: "ams"
}, },
svg: { svg: {
fontCache: "none", fontCache: "none"
}, },
options: { options: {
renderActions: { renderActions: {
addMenu: [0, "", ""], addMenu: [0, "", ""],
addContainer: [ addContainer: [
190, 190,
(doc) => { doc => {
for (const math of doc.math) { for (const math of doc.math) {
this.addContainer(math, doc); this.addContainer(math, doc);
} }
}, },
this.addContainer, this.addContainer
], ]
}, }
}, }
}; };
// eslint-disable-next-line // eslint-disable-next-line
require("mathjax/es5/tex-svg-full"); require("mathjax/es5/tex-svg-full");
@ -98,7 +102,10 @@ class App extends Component {
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener("fullscreenchange", this.solveScreenChange); document.removeEventListener("fullscreenchange", this.solveScreenChange);
document.removeEventListener("webkitfullscreenchange", this.solveScreenChange); document.removeEventListener(
"webkitfullscreenchange",
this.solveScreenChange
);
document.removeEventListener("mozfullscreenchange", this.solveScreenChange); document.removeEventListener("mozfullscreenchange", this.solveScreenChange);
document.removeEventListener("MSFullscreenChange", this.solveScreenChange); document.removeEventListener("MSFullscreenChange", this.solveScreenChange);
} }
@ -107,7 +114,15 @@ class App extends Component {
if (this.props.useImageHosting === undefined) { if (this.props.useImageHosting === undefined) {
return; return;
} }
const {url, name, isSmmsOpen, isQiniuyunOpen, isAliyunOpen, isGiteeOpen, isGitHubOpen} = this.props.useImageHosting; const {
url,
name,
isSmmsOpen,
isQiniuyunOpen,
isAliyunOpen,
isGiteeOpen,
isGitHubOpen
} = this.props.useImageHosting;
if (name) { if (name) {
this.props.imageHosting.setHostingUrl(url); this.props.imageHosting.setHostingUrl(url);
this.props.imageHosting.setHostingName(name); this.props.imageHosting.setHostingName(name);
@ -149,7 +164,7 @@ class App extends Component {
}; };
setEditorContent = () => { setEditorContent = () => {
const {defaultText} = this.props; const { defaultText } = this.props;
if (defaultText) { if (defaultText) {
this.props.content.setContent(defaultText); this.props.content.setContent(defaultText);
} }
@ -160,20 +175,23 @@ class App extends Component {
} }
solveScreenChange = () => { solveScreenChange = () => {
const {isImmersiveEditing} = this.props.view; const { isImmersiveEditing } = this.props.view;
this.props.view.setImmersiveEditing(!isImmersiveEditing); this.props.view.setImmersiveEditing(!isImmersiveEditing);
}; };
getInstance = (instance) => { getInstance = instance => {
instance.editor.on("inputRead", function(cm, event) { instance.editor.on("inputRead", function(cm, event) {
if (event.origin === "paste") { if (event.origin === "paste") {
var text = event.text[0]; // pasted string var text = event.text[0]; // pasted string
var new_text = ""; // any operations here var new_text = ""; // any operations here
cm.refresh(); cm.refresh();
const {length} = cm.getSelections(); const { length } = cm.getSelections();
// my first idea was // my first idea was
// note: for multiline strings may need more complex calculations // note: for multiline strings may need more complex calculations
cm.replaceRange(new_text, event.from, {line: event.from.line, ch: event.from.ch + text.length}); cm.replaceRange(new_text, event.from, {
line: event.from.line,
ch: event.from.ch + text.length
});
// first solution did'nt work (before i guess to call refresh) so i tried that way, works too // first solution did'nt work (before i guess to call refresh) so i tried that way, works too
if (length === 1) { if (length === 1) {
cm.execCommand("undo"); cm.execCommand("undo");
@ -189,11 +207,15 @@ class App extends Component {
handleScroll = () => { handleScroll = () => {
if (this.props.navbar.isSyncScroll) { if (this.props.navbar.isSyncScroll) {
const {markdownEditor} = this.props.content; const { markdownEditor } = this.props.content;
const cmData = markdownEditor.getScrollInfo(); const cmData = markdownEditor.getScrollInfo();
const editorToTop = cmData.top; const editorToTop = cmData.top;
const editorScrollHeight = cmData.height - cmData.clientHeight; const editorScrollHeight = cmData.height - cmData.clientHeight;
this.scale = (this.previewWrap.offsetHeight - this.previewContainer.offsetHeight + 55) / editorScrollHeight; this.scale =
(this.previewWrap.offsetHeight -
this.previewContainer.offsetHeight +
55) /
editorScrollHeight;
if (this.index === 1) { if (this.index === 1) {
this.previewContainer.scrollTop = editorToTop * this.scale; this.previewContainer.scrollTop = editorToTop * this.scale;
} else { } else {
@ -203,7 +225,7 @@ class App extends Component {
} }
}; };
handleChange = (editor) => { handleChange = editor => {
if (this.state.focus) { if (this.state.focus) {
const content = editor.getValue(); const content = editor.getValue();
this.props.content.setContent(content); this.props.content.setContent(content);
@ -211,21 +233,21 @@ class App extends Component {
} }
}; };
handleFocus = (editor) => { handleFocus = editor => {
this.setState({ this.setState({
focus: true, focus: true
}); });
this.props.onTextFocus && this.props.onTextFocus(editor.getValue()); this.props.onTextFocus && this.props.onTextFocus(editor.getValue());
}; };
handleBlur = (editor) => { handleBlur = editor => {
this.setState({ this.setState({
focus: false, focus: false
}); });
this.props.onTextBlur && this.props.onTextBlur(editor.getValue()); this.props.onTextBlur && this.props.onTextBlur(editor.getValue());
}; };
getStyleInstance = (instance) => { getStyleInstance = instance => {
if (instance) { if (instance) {
this.styleEditor = instance.editor; this.styleEditor = instance.editor;
this.styleEditor.on("keyup", (cm, e) => { this.styleEditor.on("keyup", (cm, e) => {
@ -244,7 +266,10 @@ class App extends Component {
} }
for (let i = 0; i < e.dataTransfer.files.length; i++) { for (let i = 0; i < e.dataTransfer.files.length; i++) {
// console.log(e.dataTransfer.files[i]); // console.log(e.dataTransfer.files[i]);
uploadAdaptor({file: e.dataTransfer.files[i], content: this.props.content}); uploadAdaptor({
file: e.dataTransfer.files[i],
content: this.props.content
});
} }
}; };
@ -252,21 +277,24 @@ class App extends Component {
const cbData = e.clipboardData; const cbData = e.clipboardData;
const insertPasteContent = (cm, content) => { const insertPasteContent = (cm, content) => {
const {length} = cm.getSelections(); const { length } = cm.getSelections();
cm.replaceSelections(Array(length).fill(content)); cm.replaceSelections(Array(length).fill(content));
this.setState( this.setState(
{ {
focus: true, focus: true
}, },
() => { () => {
this.handleChange(cm); this.handleChange(cm);
}, }
); );
}; };
if (e.clipboardData && e.clipboardData.files) { if (e.clipboardData && e.clipboardData.files) {
for (let i = 0; i < e.clipboardData.files.length; i++) { for (let i = 0; i < e.clipboardData.files.length; i++) {
uploadAdaptor({file: e.clipboardData.files[i], content: this.props.content}); uploadAdaptor({
file: e.clipboardData.files[i],
content: this.props.content
});
} }
} }
@ -289,18 +317,29 @@ class App extends Component {
addContainer(math, doc) { addContainer(math, doc) {
const tag = "span"; const tag = "span";
const spanClass = math.display ? "span-block-equation" : "span-inline-equation"; const spanClass = math.display
? "span-block-equation"
: "span-inline-equation";
const cls = math.display ? "block-equation" : "inline-equation"; const cls = math.display ? "block-equation" : "inline-equation";
math.typesetRoot.className = cls; math.typesetRoot.className = cls;
math.typesetRoot.setAttribute(MJX_DATA_FORMULA, math.math); math.typesetRoot.setAttribute(MJX_DATA_FORMULA, math.math);
math.typesetRoot.setAttribute(MJX_DATA_FORMULA_TYPE, cls); math.typesetRoot.setAttribute(MJX_DATA_FORMULA_TYPE, cls);
math.typesetRoot = doc.adaptor.node(tag, {class: spanClass, style: "cursor:pointer"}, [math.typesetRoot]); math.typesetRoot = doc.adaptor.node(
tag,
{ class: spanClass, style: "cursor:pointer" },
[math.typesetRoot]
);
} }
render() { render() {
const {codeNum, previewType} = this.props.navbar; const { codeNum, previewType } = this.props.navbar;
const {isEditAreaOpen, isPreviewAreaOpen, isStyleEditorOpen, isImmersiveEditing} = this.props.view; const {
const {isSearchOpen} = this.props.dialog; isEditAreaOpen,
isPreviewAreaOpen,
isStyleEditorOpen,
isImmersiveEditing
} = this.props.view;
const { isSearchOpen } = this.props.dialog;
const parseHtml = const parseHtml =
codeNum === 0 codeNum === 0
@ -310,38 +349,48 @@ class App extends Component {
const mdEditingClass = classnames({ const mdEditingClass = classnames({
"nice-md-editing": !isImmersiveEditing, "nice-md-editing": !isImmersiveEditing,
"nice-md-editing-immersive": isImmersiveEditing, "nice-md-editing-immersive": isImmersiveEditing,
"nice-md-editing-hide": !isEditAreaOpen, "nice-md-editing-hide": !isEditAreaOpen
}); });
const styleEditingClass = classnames({ const styleEditingClass = classnames({
"nice-style-editing": true, "nice-style-editing": true,
"nice-style-editing-hide": isImmersiveEditing, "nice-style-editing-hide": isImmersiveEditing
}); });
const richTextClass = classnames({ const richTextClass = classnames({
"nice-marked-text": true, "nice-marked-text": true,
"nice-marked-text-pc": previewType === "pc", "nice-marked-text-pc": previewType === "pc",
"nice-marked-text-hide": isImmersiveEditing || !isPreviewAreaOpen, "nice-marked-text-hide": isImmersiveEditing || !isPreviewAreaOpen
}); });
const richTextBoxClass = classnames({ const richTextBoxClass = classnames({
"nice-wx-box": true, "nice-wx-box": true,
"nice-wx-box-pc": previewType === "pc", "nice-wx-box-pc": previewType === "pc"
}); });
const textContainerClass = classnames({ const textContainerClass = classnames({
"nice-text-container": !isImmersiveEditing, "nice-text-container": !isImmersiveEditing,
"nice-text-container-immersive": isImmersiveEditing, "nice-text-container-immersive": isImmersiveEditing
}); });
return ( return (
<appContext.Consumer> <appContext.Consumer>
{({defaultTitle, onStyleChange, onStyleBlur, onStyleFocus, token}) => ( {({
defaultTitle,
onStyleChange,
onStyleBlur,
onStyleFocus,
token
}) => (
<div className="nice-app"> <div className="nice-app">
<Navbar title={defaultTitle} token={token} /> <Navbar title={defaultTitle} token={token} />
<Toobar token={token} /> <Toobar token={token} />
<div className={textContainerClass}> <div className={textContainerClass}>
<div id="nice-md-editor" className={mdEditingClass} onMouseOver={(e) => this.setCurrentIndex(1, e)}> <div
id="nice-md-editor"
className={mdEditingClass}
onMouseOver={e => this.setCurrentIndex(1, e)}
>
{isSearchOpen && <SearchBox />} {isSearchOpen && <SearchBox />}
<CodeMirror <CodeMirror
value={this.props.content.content} value={this.props.content.content}
@ -354,8 +403,8 @@ class App extends Component {
extraKeys: { extraKeys: {
...bindHotkeys(this.props.content, this.props.dialog), ...bindHotkeys(this.props.content, this.props.dialog),
Tab: betterTab, Tab: betterTab,
RightClick: rightClick, RightClick: rightClick
}, }
}} }}
onChange={this.handleChange} onChange={this.handleChange}
onScroll={this.handleScroll} onScroll={this.handleScroll}
@ -366,24 +415,28 @@ class App extends Component {
ref={this.getInstance} ref={this.getInstance}
/> />
</div> </div>
<div id="nice-rich-text" className={richTextClass} onMouseOver={(e) => this.setCurrentIndex(2, e)}> <div
id="nice-rich-text"
className={richTextClass}
onMouseOver={e => this.setCurrentIndex(2, e)}
>
<Sidebar /> <Sidebar />
<div <div
id={BOX_ID} id={BOX_ID}
className={richTextBoxClass} className={richTextBoxClass}
onScroll={this.handleScroll} onScroll={this.handleScroll}
ref={(node) => { ref={node => {
this.previewContainer = node; this.previewContainer = node;
}} }}
> >
<section <section
id={LAYOUT_ID} id={LAYOUT_ID}
data-tool="markdown2wechat编辑器" data-tool="markdown2html编辑器"
data-website="https://aizhuanqian.com" data-website="https://md.luckday.cn"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: parseHtml, __html: parseHtml
}} }}
ref={(node) => { ref={node => {
this.previewWrap = node; this.previewWrap = node;
}} }}
/> />
@ -392,7 +445,11 @@ class App extends Component {
{isStyleEditorOpen && ( {isStyleEditorOpen && (
<div id="nice-style-editor" className={styleEditingClass}> <div id="nice-style-editor" className={styleEditingClass}>
<StyleEditor onStyleChange={onStyleChange} onStyleBlur={onStyleBlur} onStyleFocus={onStyleFocus} /> <StyleEditor
onStyleChange={onStyleChange}
onStyleBlur={onStyleBlur}
onStyleFocus={onStyleFocus}
/>
</div> </div>
)} )}

@ -1,8 +1,8 @@
import React, {Component} from "react"; import React, { Component } from "react";
import {observer, inject} from "mobx-react"; import { observer, inject } from "mobx-react";
import {Modal, Timeline, Button} from "antd"; import { Modal, Timeline, Button } from "antd";
import axios from "axios"; import axios from "axios";
import {NEWEST_VERSION} from "../../utils/constant"; import { NEWEST_VERSION } from "../../utils/constant";
import SvgIcon from "../../icon"; import SvgIcon from "../../icon";
import "./VersionDialog.css"; import "./VersionDialog.css";
@ -17,7 +17,7 @@ class VersionDialog extends Component {
versionNumber: 0, versionNumber: 0,
versionTimeline: [], versionTimeline: [],
recommend: null, recommend: null,
specialInfo: "", specialInfo: ""
}; };
} }
@ -31,7 +31,8 @@ class VersionDialog extends Component {
handleMore = () => { handleMore = () => {
const w = window.open("about:blank"); const w = window.open("about:blank");
w.location.href = "https://git.luckday.cn/Markdown2Html/master/CHANGELOG.md"; w.location.href =
"https://git.luckday.cn/Markdown2Html/master/CHANGELOG.md";
}; };
handleDocs = () => { handleDocs = () => {
@ -44,21 +45,26 @@ class VersionDialog extends Component {
const data = { const data = {
versionId: 1, versionId: 1,
versionNumber: "1.0.0", versionNumber: "1.0.0",
versionTimeline: ["2023-09-20 增加网格黑主题", "2023-09-14 解决超链接文字复制到公众号颜色失效的问题", "2023-09-01 优化部分配置与信息", "2023-08-30 Fork 自 markdown2html"], versionTimeline: [
"2023-09-20 增加网格黑主题",
"2023-09-14 解决超链接文字复制到公众号颜色失效的问题",
"2023-09-01 优化部分配置与信息",
"2023-08-30 Fork 自 markdown2html"
],
recommend: { recommend: {
link: "https://github.com/shenweiyan/Knowledge-Garden", link: "https://github.com/shenweiyan/Knowledge-Garden",
mainInfo: "欢迎关注我的知识花园", mainInfo: "欢迎关注我的知识花园"
}, },
specialInfo: '' specialInfo: ""
//specialInfo: //specialInfo:
// '<div style="display:flex;justify-content:center;align-items:center;"><img style="width:50%;" src="http://md.aizhuanqian.online/img/wechat_qr.df324554.jpeg"/></div>', // '<div style="display:flex;justify-content:center;align-items:center;"><img style="width:50%;" src="http://md.aizhuanqian.online/img/wechat_qr.df324554.jpeg"/></div>',
}; };
const newestVersion = localStorage.getItem(NEWEST_VERSION); const newestVersion = localStorage.getItem(NEWEST_VERSION);
if (data.versionNumber !== newestVersion) { if (data.versionNumber !== newestVersion) {
this.props.dialog.setVersionOpen(true); // this.props.dialog.setVersionOpen(true);
localStorage.setItem(NEWEST_VERSION, data.versionNumber); localStorage.setItem(NEWEST_VERSION, data.versionNumber);
} }
this.setState({...data}); this.setState({ ...data });
} catch (err) { } catch (err) {
console.error("读取最新版本信息错误"); console.error("读取最新版本信息错误");
} }
@ -74,24 +80,27 @@ class VersionDialog extends Component {
footer={[ footer={[
<Button key="submit" type="primary" onClick={this.handleOk}> <Button key="submit" type="primary" onClick={this.handleOk}>
确认 确认
</Button>, </Button>
]} ]}
destroyOnClose destroyOnClose
> >
<Timeline> <Timeline>
<Timeline.Item dot={<SvgIcon name="environment" style={style.svgIcon} />}> <Timeline.Item
<strong>更多版本更新与说明信息请查看 dot={<SvgIcon name="environment" style={style.svgIcon} />}
<a >
id="more-info" <strong>
style={{fontWeight: "bold", borderBottom: "solid"}} 更多版本更新与说明信息请查看
alt="" <a
href="https://github.com/shenweiyan/Markdown2Html" id="more-info"
rel="noopener noreferrer" style={{ fontWeight: "bold", borderBottom: "solid" }}
target="_blank" alt=""
> href="https://github.com/shenweiyan/Markdown2Html"
这里 rel="noopener noreferrer"
</a> target="_blank"
</strong> >
这里
</a>
</strong>
</Timeline.Item> </Timeline.Item>
{this.state.versionTimeline.map((version, index) => { {this.state.versionTimeline.map((version, index) => {
/*if (index === 0) { /*if (index === 0) {
@ -109,7 +118,7 @@ class VersionDialog extends Component {
了解更多请查看 了解更多请查看
<a <a
id="nice-version-dialog-doc" id="nice-version-dialog-doc"
style={{fontWeight: "bold"}} style={{ fontWeight: "bold" }}
alt="" alt=""
href="https://github.com/shenweiyan/Markdown2Html" href="https://github.com/shenweiyan/Markdown2Html"
rel="noopener noreferrer" rel="noopener noreferrer"
@ -122,7 +131,7 @@ class VersionDialog extends Component {
<Timeline.Item dot={<SvgIcon name="more" style={style.svgIcon} />}> <Timeline.Item dot={<SvgIcon name="more" style={style.svgIcon} />}>
<a <a
id="nice-version-dialog-recommend" id="nice-version-dialog-recommend"
style={{fontWeight: "bold", borderBottom: "double"}} style={{ fontWeight: "bold", borderBottom: "double" }}
alt="" alt=""
href={this.state.recommend.link} href={this.state.recommend.link}
rel="noopener noreferrer" rel="noopener noreferrer"
@ -136,7 +145,7 @@ class VersionDialog extends Component {
{this.state.specialInfo && ( {this.state.specialInfo && (
<div <div
id="nice-version-dialog-special" id="nice-version-dialog-special"
dangerouslySetInnerHTML={{__html: this.state.specialInfo}} dangerouslySetInnerHTML={{ __html: this.state.specialInfo }}
className="specialInfo" className="specialInfo"
/> />
)} )}
@ -148,8 +157,8 @@ class VersionDialog extends Component {
const style = { const style = {
svgIcon: { svgIcon: {
width: "16px", width: "16px",
height: "16px", height: "16px"
}, }
}; };
export default VersionDialog; export default VersionDialog;