Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 4 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,5 @@
# mpMath — 微信公众号公式编辑插件
这个项目最初基于 [mpMath 公式一键转换](https://github.com/latentcat/mpmath/pull/6) 构建, 但随着微信公众号基于 ProseMirror 的新编辑器的推出, 原插件所有功能基本上都失效了, 因为她们都是基于 ueditor 接口实现的. 本项目将笔者需要的功能, 即 '公式一键转换' 单独抽了出来, 基于 ProseMirror 接口进行了重新实现, 细节见 [mpMath: 与微信公众号的斗智之旅(2)](https://blog.hidva.com/2025/03/02/wechat-mpmath-2/).

以下文档或有延时。查看最新文档:[troyni.com/mpmath](https://troyni.com/mpmath)。

想要在微信公众号的编辑器里输入公式吗?来试试我们的 Chrome 插件吧~

相信不少人有在微信公众号上输入数学公式的需求,而微信至今没有推出官方的公式编辑器。有人被迫去选择一些新的工作流程,比如我在文章《[一道从初中做到大学的数学题](https://mp.weixin.qq.com/s/uCdL9gJUbIs0X5WCXiskgA)》中采用了 TeX -> PDF -> SVG 的制作流程,这对普通用户来说都有一定的门槛。有人妥协,选择用截图来插入公式,或是干脆用文字字符来拼凑公式,而等等这些都有一定的问题。在这样的情况下,我们选择自己写一个插件来满足公众号输入公式的需求。

完全开源。
能力有限,许多问题尚未解决,许多功能尚未实现。如果大家能提供帮助的话,我们将感激不尽!

### 特性

- 使用 MathJax 渲染 SVG 格式的 LaTeX 公式
- 嵌入微信公众号原生编辑器
- 公式显示清晰、可调字号、支持字体颜色改变、支持 Dark Mode
- 完整的快捷键支持
- 适配通过 [Markdown Nice](https://mdnice.com) 插入的公式

### 下载与安装

#### 方式

- Github:[mpMath](https://github.com/ciaochaos/mpMath)
- 直接下载:[mpMath v0.2.1](https://github.com/ciaochaos/mpMath/releases/download/v0.2.1/mpMath.crx)
- Chrome 应用商店:[mpMath](https://chrome.google.com/webstore/detail/mpmath/nodhgmlcnikgcdfnllmiodlimcdglchh)

#### 安装步骤:

1. 下载 CRX 文件
2. 在 Chrome 中点击右上角 ︙ -> 更多工具 -> 扩展程序
或打开 [chrome://extensions/](chrome://extensions/)
3. 打开右上角开发者模式
4. 将 CRX 文件拖入 Chrome 窗口
5. 单击「添加扩展程序」,安装完成

### 使用

打开微信公众平台图文编辑界面,若 `公式` 已经出现在页面顶部 `音频` 的右侧,则说明插件成功运行。

![](https://troyni.com/assets/building-mpmath/1fa9214e84c1455ee3278fb11b1e391a_MD5.jpg)

点击 `公式` 即可新建公式并插入。点击已经插入的公式即可二次编辑。

> 如果你不太熟悉 LaTeX 语法,可以参考语雀的[数学公式举例](https://www.yuque.com/yuque/help/brzicb)、Apple 的[示例方程](https://support.apple.com/zh-cn/HT202501#sample),或是这一份 [MathJax 基本教程和快速参考](https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference)(英文)。

> 如果你正在寻找基于 TeX 编写的数学题,推荐一个网站:[橘子数学](https://www.mathcrowd.cn/)。

> 如果你偏好非所见即所得的写作方式,试试这个:[Markdown Nice](https://mdnice.com),同样对数学公式有着很好的支持。

强烈推荐使用以下快捷键,提高输入效率。

#### 快捷键

| 操作 | 快捷键 |
| ------------ | ------------------------------------------------------------ |
| 新建公式 | <kbd>control</kbd> + <kbd>/</kbd><br /><kbd>command</kbd> + <kbd>/</kbd> |
| 退出公式编辑 | <kbd>esc</kbd> |
| 插入公式 | <kbd>shift</kbd> + <kbd>enter</kbd> |

#### 可能遇到的问题

- 输入行内公式的显式样式
- 公式前添加 `\displaystyle`
- 公式右侧的空格会与公式捆绑在一起
- 可以在空格右侧使用 <kbd>shift</kbd> + <kbd>←</kbd> 选中空格并删除
- 公式不能被高亮选中、拖动
- 可同时选中公式左右侧的字符进行复制等操作

### 反馈

- 本页评论区
- 邮箱:1272777550@qq.com
- 微信:nhciao
- 微信公众号:Isle of Chaos

### 开发计划

- 公式输入提示
- 如 Typora 等的无模态弹窗公式输入
- 一键转换 LaTeX 公式

### 许可

[The MIT License](https://opensource.org/licenses/MIT)

### 作者

- ciaochaos - CUC
- CPunisher - BUAA
使用姿势:
1. 像往常一样安装插件.
2. 控制台输入 `HidvaMpMathGo()`! 或许可以加个按钮啥的.
15 changes: 0 additions & 15 deletions mpMath/.vscode/launch.json

This file was deleted.

16 changes: 0 additions & 16 deletions mpMath/assets/css/mpMath.css

This file was deleted.

40 changes: 0 additions & 40 deletions mpMath/assets/css/popup.css

This file was deleted.

1 change: 0 additions & 1 deletion mpMath/assets/css/weui.css

This file was deleted.

Binary file removed mpMath/assets/images/formula.png
Binary file not shown.
Binary file removed mpMath/assets/images/mpMath_logo128.png
Binary file not shown.
Binary file removed mpMath/assets/images/mpMath_logo16.png
Binary file not shown.
Binary file removed mpMath/assets/images/mpMath_logo32.png
Binary file not shown.
Binary file removed mpMath/assets/images/mpMath_logo48.png
Binary file not shown.
12 changes: 0 additions & 12 deletions mpMath/assets/js/background.js

This file was deleted.

169 changes: 27 additions & 142 deletions mpMath/assets/js/content-script.js
Original file line number Diff line number Diff line change
@@ -1,151 +1,36 @@
function formulaClick(event) {
$('#popup').css('display', 'block');
$('#popup')[0].contentWindow.postMessage({ type: 'CHANGE_INPUT', text: '' }, '*');
$('#popup')[0].focus();
$('.tpl_dropdown_menu', '.formula').css('display', 'none');
if (event) event.stopPropagation();
}

function fixClick(event) {
revise();
$('.tpl_dropdown_menu', '.formula').css('display', 'none');
event.stopPropagation();
}

function guideClick(event) {
alert('指南还在施工!');
$('.tpl_dropdown_menu', '.formula').css('display', 'none');
event.stopPropagation();
}

setTimeout(function () {
// 注入脚本
let script_inject = document.createElement('script');
script_inject.src = chrome.runtime.getURL('assets/js/mpm-inject.js');
script_inject.src = chrome.runtime.getURL('client/mpm-inject.js');
script_inject.onload = function () {
this.remove;
};
(document.head || document.documentElement).appendChild(script_inject);
console.log("hidva.com: load mpm-inject.js");
}
document.documentElement.appendChild(script_inject);
}, 1000);

// 等待文档加载完毕
chrome.runtime.sendMessage({}, function (response) {
var readyStateCheckInterval = setInterval(function () {
if (document.readyState === 'complete') {
clearInterval(readyStateCheckInterval);

if ($('#js_media_list')[0]) {
// 公式编辑弹窗
let iframe = document.createElement('iframe');
iframe.src = chrome.runtime.getURL('./pages/popup.html');
iframe.setAttribute('class', 'mpm-modal');
iframe.frameBorder = 0;
iframe.allowTransparency = true;
iframe.id = 'popup';
iframe.style.display = 'none';
document.body.appendChild(iframe);
console.log(iframe)

// 上方菜单栏公式按钮
let formulaMenu = document.createElement('li');
formulaMenu.setAttribute('class', 'tpl_item tpl_item_dropdown jsInsertIcon formula');
formulaMenu.id = 'js_editor_insert_formula';
$(formulaMenu).append('<span>公式</span>');

// 分别为 下拉菜单栏、插入公式、修复SVG、指南
let dropdownMenu = document.createElement('ul');
dropdownMenu.setAttribute('class', 'tpl_dropdown_menu');
dropdownMenu.style.display = 'none';

let formulaInsertItem = document.createElement('li');
formulaInsertItem.setAttribute('class', 'tpl_dropdown_menu_item');
formulaInsertItem.innerText = '插入公式 ⌘/';
formulaInsertItem.onclick = formulaClick;
dropdownMenu.appendChild(formulaInsertItem);

let formulaFixItem = document.createElement('li');
formulaFixItem.setAttribute('class', 'tpl_dropdown_menu_item');
formulaFixItem.innerText = '修复SVG';
formulaFixItem.onclick = fixClick;
dropdownMenu.appendChild(formulaFixItem);

let formulaGuide = document.createElement('li');
formulaGuide.setAttribute('class', 'tpl_dropdown_menu_item');
formulaGuide.innerText = '指南';
formulaGuide.onclick = guideClick;
dropdownMenu.appendChild(formulaGuide);

formulaMenu.appendChild(dropdownMenu);
$(formulaMenu).click(function () {
$(dropdownMenu).css('display', 'none');
});

$(document).click(function(event) {
// 检查点击的元素是否是formulaMenu
if (!$(event.target).closest(formulaMenu).length) {
// 如果不是,下拉菜单消失
$(dropdownMenu).css('display', 'none');
}
else {
// 如果是,下拉菜单显示
$(dropdownMenu).css('display', 'block');
}
});

$('#js_media_list')[0].appendChild(formulaMenu);

// 热键绑定 Ctrl/⌘ + /
$('#ueditor_0').contents().find('.view').keydown(function (event) {
let keyCode = event.keyCode || event.which || event.charCode;
let ctrlKey = event.ctrlKey || event.metaKey;
if (ctrlKey && keyCode == 191) {
formulaClick();
}
});
}
}
}, 10);
});
setTimeout(function () {
// 好像一定要先 load mpm-inject 之后再 load mathjax,
// 这样 mpm inject 中定义的 MathJax 对 mathjax 才可见
var script = document.createElement('script');
script.id = 'MathJax-script';
script.async = true;
script.src = chrome.runtime.getURL('assets/js/tex-svg-full.js');
script.onload = function () {
console.log("hidva.com: load tex-svg-full.js");
}
document.head.appendChild(script);
}, 3000);

/*
以下代码源于 https://github.com/kongxiangyan/bookmarklet
修复修正微信公众号图文编辑器粘贴 SVG 时部分转换为 Embed 导致不支持 Dark Mode 的问题
*/
function loadSVG(src) {
return new Promise((resolve) => {
let ajax = new XMLHttpRequest();
ajax.open('GET', src, true);
ajax.send();
ajax.onload = function(e) {
let div = document.createElement('div');
div.innerHTML = ajax.responseText;
let svg = div.childNodes[1];
resolve(svg);
}
})
}

function revise() {
console.log(`【MP_SVG_REVISE】 Start`);
let ueditor = document.getElementById('ueditor_0');
let view = ueditor.contentDocument.getElementsByClassName('view')[0];
let embeds = view.querySelectorAll('embed');
console.log(`【MP_SVG_REVISE】 检测到 ${embeds.length} 个目标……`);
let promises = [];
embeds.forEach((embed, index) => {
console.log(`【MP_SVG_REVISE】 第 ${index} 个……`);
let parent_node = embed.parentNode;
promises.push(new Promise(resolve => {
loadSVG(embed.src).then(svg => {
parent_node.insertBefore(svg, embed);
parent_node.removeChild(embed);
resolve();
})
}))
});
Promise.all(promises).then(() => {
console.log('Revise complete!');
//alert('Revise complete!');
alert(`修复了 ${embeds.length} 个目标!`);
})
}
setTimeout(function () {
let iframe = document.createElement('iframe');
iframe.src = chrome.runtime.getURL('server/mathjax.html');
iframe.setAttribute('class', 'mpm-modal');
iframe.frameBorder = 0;
iframe.allowTransparency = true;
iframe.id = 'hidva_com_mathjax_server';
iframe.style.display = 'none';
document.body.appendChild(iframe);
console.log("hidva.com: inject mathjax.html");
}, 100);
2 changes: 0 additions & 2 deletions mpMath/assets/js/jquery-3.4.1.min.js

This file was deleted.

Loading