16 Commits

Author SHA1 Message Date
douboer
28942bea17 update at 2025-10-16 16:10:58 2025-10-16 16:10:58 +08:00
douboer
9f3a4e8812 update at 2025-10-16 14:24:10 2025-10-16 14:24:10 +08:00
douboer
5e1351408e update at 2025-10-16 14:06:24 2025-10-16 14:06:24 +08:00
douboer
93afc99e7d update at 2025-10-16 14:03:45 2025-10-16 14:03:45 +08:00
douboer
b9feb2f764 update at 2025-10-13 20:53:32 2025-10-13 20:53:32 +08:00
douboer
97a70bc23b update at 2025-10-10 23:45:02 2025-10-10 23:45:03 +08:00
douboer
437619cfff update at 2025-10-10 22:48:36 2025-10-10 22:48:36 +08:00
douboer
10ef109353 update at 2025-10-10 22:21:06 2025-10-10 22:21:06 +08:00
douboer
1d52f79e0c update at 2025-10-10 21:55:46 2025-10-10 21:55:46 +08:00
douboer
0ab20de880 update at 2025-10-10 21:54:05 2025-10-10 21:54:05 +08:00
douboer
1db58695e8 update at 2025-10-10 19:14:59 2025-10-10 19:14:59 +08:00
douboer
90933673f3 update at 2025-10-10 19:13:38 2025-10-10 19:13:38 +08:00
douboer
86c3beea49 update at 2025-10-10 17:00:09 2025-10-10 17:00:09 +08:00
douboer
1309caddc3 update at 2025-10-09 21:19:57 2025-10-09 21:19:57 +08:00
douboer
002feedbe1 update at 2025-10-09 16:23:27 2025-10-09 16:23:27 +08:00
douboer
a71b4c4d4f update at 2025-10-09 15:46:43 2025-10-09 15:46:43 +08:00
86 changed files with 7365 additions and 4361 deletions

View File

@@ -1,8 +1,8 @@
## 更新说明
> [!IMPORTANT]
> NoteToMP 1.3.0版本对主题进行了优化,升级后请先清理旧版本主题文件,再重新下载新版主题。
> Note2Any 1.3.0版本对主题进行了优化,升级后请先清理旧版本主题文件,再重新下载新版主题。
>
> 操作步骤在NoteToMP插件设置中,先点击『清空主题-清空』,然后点击『获取更多主题-下载』
> 操作步骤在Note2Any插件设置中,先点击『清空主题-清空』,然后点击『获取更多主题-下载』
>
> 注意:如果修改过主题文件请做备份后再操作。
@@ -49,30 +49,30 @@
```
路径日志做了节流:同一文件 3 秒内不重复打印。后续可加"调试开关"以完全关闭。
### 摘要、封面裁剪、原文链接等ges/screenshot.png)
### 摘要、封面裁剪、原文链接等
## 2、安装
首先,**请确认已关闭了Obsidian的安全模式**。如未关闭,请通过**设置——第三方插件——关闭安全模式**关闭。
### 2.1 插件安装
#### 从官方**社区插件市场**安装
通过Obsidian**设置——第三方插件——社区插件市场**,输入**NoteToMP**搜索安装。
通过Obsidian**设置——第三方插件——社区插件市场**,输入**Note2Any**搜索安装。
### 2.2 主题资源安装
如果采用的是用从插件市场或者Github下载安装的方式在插件安装完成后还需要再下载主题资源。网盘里的安装包已经集成了主题样式无需下载。
**1通过设置下载**
为了尽可能保证插件符合官方规范主题和代码高亮需要打开Obsidian的**设置**界面,在底部的**第三方插件**——**Note to MP**——**获取更多主题**手动下载。
为了尽可能保证插件符合官方规范主题和代码高亮需要打开Obsidian的**设置**界面,在底部的**第三方插件**——**Note 2 Any**——**获取更多主题**手动下载。
**2手动下载**
也可以直接在[Release](https://github.com/sunbooshi/note-to-mp/releases)页面下载`assets.zip`文件,解压后放到`.obsidian/plugins/note-to-mp/assets`目录下。
也可以直接在[Release](https://biboer.cn/gitea/gavin/note2any/releases)页面下载`assets.zip`文件,解压后放到`.obsidian/plugins/note2any/assets`目录下。
### 2.3 常见安装问题
**只有默认主题**
确认根据**2.2 主题资源安装**里的步骤操作了,然后检查一下插件目录内容,应如下所示:
```
.obsidian/plugins/note-to-mp/
.obsidian/plugins/note2any/
├── assets
│ ├── themes.json
│ ├── highlights.json
@@ -95,8 +95,6 @@
检查样式无误后,点击**复制**按钮,然后到公众号粘贴即可。
![](images/20240630221748.jpg)
**★ 公众号**
插件支持多公众号,在下拉菜单中进行不同公众号的切换。该功能需要订阅才能使用。
@@ -158,6 +156,15 @@ c=+-sqrt(a^2+b^2)
数学公式的渲染效果可以看这篇文章:[公众号文章里的数学公式排版秘籍](https://mp.weixin.qq.com/s/-kpT2U1gT_5W3TsDCAVgsw)👈️
### 自定义CSS使用指南
## 开发与构建
本仓库的构建脚本分为“未混淆”和“启用混淆”两个版本:
- `npm run build`:生成未混淆的 `main.js`,便于调试。
- `npm run build:obf`:在生产模式下启用 `javascript-obfuscator`,生成混淆后的 `main.js`。
- `./build.sh`:执行默认(未混淆)构建并同步到本地 Obsidian 插件目录。
- `./build.sh obf`:执行混淆构建后再进行同步。
如需自定义混淆行为,可在执行命令时设置环境变量(例如 `OBFUSCATE=1 npm run build:bundle`),详细参数见 `esbuild.config.mjs`。
新建一篇笔记,例如**自定义样式**,直接将如下内容粘贴进笔记:
````CSS
@@ -170,36 +177,36 @@ c=+-sqrt(a^2+b^2)
```
````
然后打开NoteToMP插件设置,将**自定义样式**即包含自定义CSS内容的笔记名称粘贴到**自定义CSS笔记**中即可。如果不使用自定义CSS留空即可。
然后打开Note2Any插件设置,将**自定义样式**即包含自定义CSS内容的笔记名称粘贴到**自定义CSS笔记**中即可。如果不使用自定义CSS留空即可。
关于自定义CSS的写法可以参考下面的代码
```css
/* 全局属性
* 这里可以设置字体,字体大小,边距,背景颜色等
*/
.note-to-mp {
.note2any {
/* 注:请在大括号内改写!!! */
}
/* 段落 */
.note-to-mp p {
.note2any p {
/* 注:请在大括号内改写!!! */
}
/* 一级标题 */
.note-to-mp h1 {
.note2any h1 {
/* 注:请在大括号内改写!!! */
}
/* 二级标题 */
.note-to-mp h2 {
.note2any h2 {
/* 注:请在大括号内改写!!! */
}
/* 三级标题 */
.note-to-mp h3 {
.note2any h3 {
/* 注:请在大括号内改写!!! */
}
@@ -207,38 +214,38 @@ c=+-sqrt(a^2+b^2)
/* 无序列表整体样式
* list-style-type: square|circle|disc;
*/
.note-to-mp ul {
.note2any ul {
/* 注:请在大括号内改写!!! */
}
/* 加粗 */
.note-to-mp strong {
.note2any strong {
/* 注:请在大括号内改写!!! */
}
/* 斜体 */
.note-to-mp em {
.note2any em {
/* 注:请在大括号内改写!!! */
}
/* 加粗斜体 */
.note-to-mp em strong {
.note2any em strong {
/* 注:请在大括号内改写!!! */
}
/* 删除线 */
.note-to-mp del {
.note2any del {
/* 注:请在大括号内改写!!! */
}
/* 分隔线
*/
.note-to-mp hr {
.note2any hr {
/* 注:请在大括号内改写!!! */
}
/* 图片
*/
.note-to-mp img {
.note2any img {
/* 注:请在大括号内改写!!! */
}
/*
@@ -281,7 +288,7 @@ c=+-sqrt(a^2+b^2)
例如这篇文章[几个让公众号排版更精致的小技巧,手机上也可以!](https://mp.weixin.qq.com/s/Q4_pV9TW8un3qZ0vrUvD1A)👈️使用的自定义样式如下:
```css
.note-to-mp {
.note2any {
font-family: Optima-regular, Optima, "Microsoft YaHei", PingFangSC-regular, serif;
}
@@ -306,7 +313,7 @@ section .note-callout-example {
background-color: rgba(90, 185, 131, 0.1);
}
```
上面的例子,通过`.note-to-mp`指定了文章的字体,通过`h2 strong`单独定义了h2标题下strong的样式这样可以在标题中通过使用粗体增加了一个边框样式。通过`h2`定义了h2标题的底部线条的宽度和文本颜色。这样配合**Olive Dunk**主题就形成了自己的风格。
上面的例子,通过`.note2any`指定了文章的字体,通过`h2 strong`单独定义了h2标题下strong的样式这样可以在标题中通过使用粗体增加了一个边框样式。通过`h2`定义了h2标题的底部线条的宽度和文本颜色。这样配合**Olive Dunk**主题就形成了自己的风格。
### 公众号名片
请参考 https://mp.weixin.qq.com/s/1wYd15Irmv9BPabgp5XMCA
@@ -334,7 +341,7 @@ NoteToMP插件支持该语法。
![[文件名称#^段落标记]]
```
在NoteToMP插件中有两种展示文件嵌入内容的样式一种是引用也就是Obsidian默认的方式一种是正文相当于模板的方式。与模板不同的是采用嵌入方式内容会跟随被嵌入文件的内容更改。
在Note2Any插件中有两种展示文件嵌入内容的样式一种是引用也就是Obsidian默认的方式一种是正文相当于模板的方式。与模板不同的是采用嵌入方式内容会跟随被嵌入文件的内容更改。
## 批量发布Batch Publish
@@ -356,7 +363,7 @@ NoteToMP插件支持该语法。
- 你想要把所有标记为 `篆刻` 的文章筛选出来,批量上传到公众号草稿箱并逐条完善后发布。
- 按文件夹 `content/post` 筛选并批量发布该文件夹下的近期文章。
### 详细使用指南(一步步)
### 使用指南
1. 打开模态
- 命令面板Ctrl/Cmd+P→ 输入“批量发布文章”,回车打开模态窗口。
@@ -537,13 +544,6 @@ https://www.bilibili.com/video/BV15XWVeEEJa/
---
```
视频教程https://www.bilibili.com/video/BV15XWVeEEmA/
## 4、反馈交流群
**微信群:**
加微信:**Genius35Plus**,备注:**NoteToMP**
## 附:批量发布 - 快速交互速览与截图占位
如果你想把功能教学放到 README 中,这里是推荐的简短速览(已在模态中实现):
@@ -559,3 +559,6 @@ https://www.bilibili.com/video/BV15XWVeEEJa/
2. 在 README 中替换占位为图片预览并附带关键交互标注说明。
如果你更愿意手动截屏我也可以把一个标注模板SVG 或说明)发给你,方便手动粘贴到 `images/` 目录。

View File

@@ -1,22 +1,22 @@
/* =========================================================== */
/* 笔记样式 https://github.com/xbmlz/hexo-theme-maple */
/* =========================================================== */
.note-to-mp {
.note2any {
user-select: text;
-webkit-user-select: text;
color: #555;
font-family: "Inter", Inter var, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
.note-to-mp:last-child {
.note2any:last-child {
margin-bottom: 0;
}
.note-to-mp .fancybox-img {
.note2any .fancybox-img {
border: none;
}
.note-to-mp .fancybox-img:hover {
.note2any .fancybox-img:hover {
opacity: none;
border: none;
}
@@ -26,7 +26,7 @@
Heading
==================================
*/
.note-to-mp h1 {
.note2any h1 {
color: #222;
font-weight: 800;
font-size: 2.25em;
@@ -35,7 +35,7 @@
line-height: 1.1111111;
}
.note-to-mp h2 {
.note2any h2 {
color: inherit;
font-weight: 700;
font-size: 1.5em;
@@ -44,7 +44,7 @@
line-height: 1.3333333;
}
.note-to-mp h3 {
.note2any h3 {
color: inherit;
font-weight: 600;
font-size: 1.25em;
@@ -53,7 +53,7 @@
line-height: 1.6;
}
.note-to-mp h4 {
.note2any h4 {
color: inherit;
font-weight: 600;
margin-top: 1.5em;
@@ -66,7 +66,7 @@
Horizontal Rules
==================================
*/
.note-to-mp hr {
.note2any hr {
border-color: rgba(125, 125, 125, 0.3);
margin-top: 3em;
margin-bottom: 3em;
@@ -77,7 +77,7 @@
Paragraphs
==================================
*/
.note-to-mp p {
.note2any p {
margin: 1em 0;
}
@@ -86,16 +86,16 @@
Emphasis
==================================
*/
.note-to-mp strong {
.note2any strong {
color: #222;
font-weight: 600;
}
.note-to-mp em {
.note2any em {
color: inherit;
}
.note-to-mp s {
.note2any s {
color: inherit;
}
@@ -104,7 +104,7 @@
Blockquotes
==================================
*/
.note-to-mp blockquote {
.note2any blockquote {
font-size: 1rem;
display: block;
margin: 1em 0;
@@ -114,11 +114,11 @@
border-left: 0.25rem solid rgba(125, 125, 125, 0.302);
}
.note-to-mp blockquote p {
.note2any blockquote p {
margin: 0;
}
.note-to-mp blockquote footer strong {
.note2any blockquote footer strong {
margin-right: 0.5em;
}
@@ -127,26 +127,26 @@
List
==================================
*/
.note-to-mp ul {
.note2any ul {
margin: 0;
/* padding: 0; */
margin-top: 1.25em;
margin-bottom: 1.25em;
}
.note-to-mp ul>li {
.note2any ul>li {
position: relative;
/* padding-left: 1.75rem; */
line-height: 1.8em;
}
.note-to-mp ul>li::marker {
.note2any ul>li::marker {
color: #555;
/* font-size: 1.5em; */
}
.note-to-mp ol {
.note2any ol {
margin: 0;
padding: 0;
margin-top: 1.25em;
@@ -154,7 +154,7 @@
list-style-type: decimal;
}
.note-to-mp ol>li {
.note2any ol>li {
position: relative;
padding-left: 0.8em;
margin-left: 2em;
@@ -166,7 +166,7 @@
Link
==================================
*/
.note-to-mp a {
.note2any a {
color: #000;
text-decoration: none;
font-weight: 500;
@@ -175,7 +175,7 @@
transition: border 0.3s ease-in-out;
}
.note-to-mp a:hover {
.note2any a:hover {
border-bottom: 1px solid #555;
}
@@ -184,7 +184,7 @@
Table
==================================
*/
.note-to-mp table {
.note2any table {
width: 100%;
table-layout: auto;
text-align: left;
@@ -197,38 +197,38 @@
text-indent: 0;
}
.note-to-mp table thead {
.note2any table thead {
color: #000;
font-weight: 600;
border-bottom-width: 1px;
border-bottom-color: #d1d5db;
}
.note-to-mp table thead th {
.note2any table thead th {
vertical-align: bottom;
padding-right: 0.5714286em;
padding-bottom: 0.5714286em;
padding-left: 0.5714286em;
}
.note-to-mp table thead th:first-child {
.note2any table thead th:first-child {
padding-left: 0;
}
.note-to-mp table thead th:last-child {
.note2any table thead th:last-child {
padding-right: 0;
}
.note-to-mp table tbody tr {
.note2any table tbody tr {
border-bottom-width: 1px;
border-bottom-color: #e5e7eb;
}
.note-to-mp table tbody tr:last-child {
.note2any table tbody tr:last-child {
border-bottom-width: 0;
}
.note-to-mp table tbody td {
.note2any table tbody td {
vertical-align: top;
padding-top: 0.5714286em;
padding-right: 0.5714286em;
@@ -236,11 +236,11 @@
padding-left: 0.5714286em;
}
.note-to-mp table tbody td:first-child {
.note2any table tbody td:first-child {
padding-left: 0;
}
.note-to-mp table tbody td:last-child {
.note2any table tbody td:last-child {
padding-right: 0;
}
@@ -249,11 +249,11 @@
Images
==================================
*/
.note-to-mp img {
.note2any img {
margin: 2em auto;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
@@ -263,7 +263,7 @@
Code
==================================
*/
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(240, 240, 240);
margin: 1.5em 0;
@@ -272,7 +272,7 @@
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -284,12 +284,12 @@
list-style-type: none;
}
.note-to-mp .code-section ul>li {
.note2any .code-section ul>li {
line-height: 26px;
text-align: right;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -299,7 +299,7 @@
background: transparent !important;
}
.note-to-mp code {
.note2any code {
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
color: #333;
background: rgb(250, 250, 250);
@@ -308,7 +308,7 @@
text-wrap: nowrap;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
color: inherit;
display: flex;
text-wrap: nowrap;

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(217, 215, 209);
background-color: rgb(31, 35, 47);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(159, 170, 185);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(60, 66, 84);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(254, 203, 102);
color: rgb(217, 215, 209);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(254, 203, 102);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(254, 203, 102) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(254, 203, 102);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(120, 126, 140);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(17, 110, 84);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(207, 208, 203);
border-collapse: collapse;
background-color: rgb(24, 28, 37);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(60, 66, 84);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(207, 208, 203);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(60, 66, 84);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(107, 104, 132);
background-color: rgb(250, 250, 250);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(77, 82, 85);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(191, 193, 196);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(255, 106, 0);
color: rgb(107, 104, 132);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(255, 106, 0);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(255, 106, 0) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(230, 103, 0);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(141, 143, 149);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(230, 249, 189);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(39, 45, 56);
border-collapse: collapse;
background-color: rgb(255, 255, 255);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(191, 193, 196);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(39, 45, 56);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(191, 193, 196);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: #222222;
background-color: white;
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 0 0;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: #262626;
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: #bfbfbf;
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid #353535;
color: #222222;
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: #353535;
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, #353535 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: #2478c5;
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: #525252;
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: #fcffc0;
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: #424242;
border-collapse: collapse;
background-color: white;
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid #bfbfbf;
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: #424242;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #bfbfbf;
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(166, 166, 166);
background-color: rgb(46, 50, 53);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(172, 172, 172);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(62, 67, 72);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(155, 183, 196);
color: rgb(166, 166, 166);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(155, 183, 196);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(155, 183, 196) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(171, 196, 207);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(122, 122, 122);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(7, 16, 25);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(153, 153, 153);
border-collapse: collapse;
background-color: rgb(47, 51, 55);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(62, 67, 72);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(153, 153, 153);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(62, 67, 72);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(219, 240, 239);
background-color: rgb(20, 39, 56);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(211, 200, 69);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(16, 36, 50);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(252, 133, 30);
color: rgb(219, 240, 239);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(252, 133, 30);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(252, 133, 30) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(54, 201, 155);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(172, 191, 195);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(61, 0, 77);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(225, 239, 243);
border-collapse: collapse;
background-color: rgb(21, 45, 62);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(16, 36, 50);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(225, 239, 243);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(16, 36, 50);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: #222222;
background-color: #F9F9F9;
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: #262626;
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: #bfbfbf;
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid #2478c5;
color: #222222;
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: #2478c5;
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, #2478c5 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: #2478c5;
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: #525252;
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: #d3ffa4;
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: #424242;
border-collapse: collapse;
background-color: white;
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid #bfbfbf;
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: #424242;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #bfbfbf;
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(0, 0, 0);
background-color: rgb(251, 250, 252);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(0, 0, 0);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(199, 199, 199);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(127, 127, 127);
color: rgb(0, 0, 0);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(127, 127, 127);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(127, 127, 127) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(80, 112, 139);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(128, 126, 128);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(254, 255, 83);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(38, 37, 38);
border-collapse: collapse;
background-color: rgb(253, 253, 253);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(199, 199, 199);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(38, 37, 38);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(199, 199, 199);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(221, 221, 221);
background-color: rgb(30, 32, 34);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(203, 219, 229);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(87, 87, 87);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(74, 168, 251);
color: rgb(221, 221, 221);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(74, 168, 251);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(74, 168, 251) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(107, 202, 251);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(111, 115, 115);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(38, 60, 146);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(255, 254, 255);
border-collapse: collapse;
background-color: rgb(36, 36, 36);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(87, 87, 87);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(255, 254, 255);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(87, 87, 87);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -17,10 +17,10 @@
* 各个属性的默认值为 chrome 的默认样式,见 variables/default.scss。
*/
/**
* MWeb 包裹 markdown 的容器是 .note-to-mp
* MWeb 包裹 markdown 的容器是 .note2any
* Typora 中是 #write
*/
.note-to-mp {
.note2any {
line-height: 1.6em;
-webkit-text-size-adjust: 100%;
margin: 0 0;
@@ -36,11 +36,11 @@
/* table */
/* svg */
}
.note-to-mp p, .note-to-mp details, .note-to-mp dl, .note-to-mp ol, .note-to-mp ul, .note-to-mp pre, .note-to-mp xmp, .note-to-mp plaintext, .note-to-mp listing, .note-to-mp blockquote, .note-to-mp table, .note-to-mp figure, .note-to-mp hr {
.note2any p, .note2any details, .note2any dl, .note2any ol, .note2any ul, .note2any pre, .note2any xmp, .note2any plaintext, .note2any listing, .note2any blockquote, .note2any table, .note2any figure, .note2any hr {
margin-top: 0.75em;
margin-bottom: 0.75em;
}
.note-to-mp h1 {
.note2any h1 {
font-size: 2em;
font-weight: bold;
margin-top: 1.5em;
@@ -48,7 +48,7 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.5em;
font-weight: bold;
margin-top: 1.5em;
@@ -56,7 +56,7 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.17em;
font-weight: bold;
margin-top: 1.5em;
@@ -64,7 +64,7 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
font-weight: bold;
margin-top: 1.5em;
@@ -72,7 +72,7 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 0.83em;
font-weight: bold;
margin-top: 1.5em;
@@ -80,7 +80,7 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 0.67em;
font-weight: bold;
margin-top: 1.5em;
@@ -88,91 +88,91 @@
margin-left: 0;
margin-right: 0;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre, .note-to-mp xmp, .note-to-mp plaintext, .note-to-mp listing {
.note2any pre, .note2any xmp, .note2any plaintext, .note2any listing {
font-family: monospace, Menlo-Regular, Menlo, Monaco, Consolas, "Courier New";
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp hr {
.note2any hr {
border-style: inset;
border-width: 1px;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp li + li {
.note2any li + li {
margin-top: 0.25em;
}
.note-to-mp ul ul, .note-to-mp ol ul, .note-to-mp ul ol, .note-to-mp ol ol {
.note2any ul ul, .note2any ol ul, .note2any ul ol, .note2any ol ol {
margin-top: 0;
margin-bottom: 0;
}
.note-to-mp .task-list-item {
.note2any .task-list-item {
list-style-type: none;
}
.note-to-mp a {
.note2any a {
color: -webkit-link;
text-decoration: underline;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b, .note-to-mp strong {
.note2any b, .note2any strong {
font-weight: bold;
}
.note-to-mp i, .note-to-mp cite, .note-to-mp em, .note-to-mp var, .note-to-mp address, .note-to-mp dfn {
.note2any i, .note2any cite, .note2any em, .note2any var, .note2any address, .note2any dfn {
font-style: italic;
}
.note-to-mp code, .note-to-mp kbd, .note-to-mp tt, .note-to-mp samp {
.note2any code, .note2any kbd, .note2any tt, .note2any samp {
font-family: monospace, Menlo-Regular, Menlo, Monaco, Consolas, "Courier New";
}
.note-to-mp mark {
.note2any mark {
padding: 0.2em 0;
background-color: yellow;
}
.note-to-mp del, .note-to-mp s {
.note2any del, .note2any s {
color: inherit;
}
.note-to-mp table {
.note2any table {
color: black;
border-collapse: collapse;
background-color: white;
border-spacing: 2px;
font-size: 1em;
}
.note-to-mp th, .note-to-mp td {
.note2any th, .note2any td {
border-color: gray;
border-width: 1px;
border-style: solid;
}
.note-to-mp th {
.note2any th {
padding: 4px 8px;
font-size: 1em;
font-weight: bold;
}
.note-to-mp td {
.note2any td {
padding: 4px 8px;
font-size: 1em;
font-weight: normal;
}
.note-to-mp div[id^=mweb-chart-ele] svg {
.note2any div[id^=mweb-chart-ele] svg {
background-color: white;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px gray;
margin: 1.5em 0;
@@ -180,7 +180,7 @@
padding: 0.5em;
font-family: monospace, Menlo-Regular, Menlo, Monaco, Consolas, "Courier New";
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -188,12 +188,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: monospace, Menlo-Regular, Menlo, Monaco, Consolas, "Courier New";
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -204,10 +204,10 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}
.note-to-mp .code-section ul li {
.note2any .code-section ul li {
margin: 0;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(212, 212, 212);
background-color: rgb(0, 0, 0);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(252, 206, 35);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(29, 29, 29);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(242, 148, 41);
color: rgb(212, 212, 212);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(242, 148, 41);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(242, 148, 41) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(227, 146, 9);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(146, 147, 146);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(16, 68, 3);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(229, 227, 229);
border-collapse: collapse;
background-color: rgb(16, 16, 16);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(29, 29, 29);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(229, 227, 229);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(29, 29, 29);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(255, 255, 255);
background-color: rgb(53, 56, 70);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(80, 250, 123);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgba(187, 145, 248, 0.4);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(205, 174, 249);
color: rgb(255, 255, 255);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(205, 174, 249);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(205, 174, 249) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(139, 233, 253);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(178, 184, 163);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(95, 99, 117);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(249, 249, 245);
border-collapse: collapse;
background-color: rgb(31, 32, 42);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgba(187, 145, 248, 0.4);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(249, 249, 245);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgba(187, 145, 248, 0.4);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(101, 96, 101);
background-color: rgb(251, 250, 249);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(138, 74, 169);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(211, 197, 211);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(202, 124, 208);
color: rgb(101, 96, 101);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(202, 124, 208);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(202, 124, 208) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(183, 71, 175);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(146, 142, 147);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(242, 193, 209);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(89, 84, 89);
border-collapse: collapse;
background-color: rgb(255, 253, 253);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(211, 197, 211);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(89, 84, 89);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(211, 197, 211);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(75, 53, 8);
background-color: rgb(250, 248, 245);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(99, 90, 71);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgba(182, 173, 155, 0.3);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(115, 144, 201);
color: rgb(75, 53, 8);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(115, 144, 201);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(115, 144, 201) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(11, 53, 135);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(136, 102, 42);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(211, 255, 164);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(66, 66, 66);
border-collapse: collapse;
background-color: rgb(255, 252, 249);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgba(182, 173, 155, 0.3);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(66, 66, 66);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgba(182, 173, 155, 0.3);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(69, 82, 96);
background-color: rgb(240, 240, 240);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(61, 81, 109);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(200, 205, 218);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(160, 76, 107);
color: rgb(69, 82, 96);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(160, 76, 107);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(160, 76, 107) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(128, 57, 75);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgba(69, 82, 96, 0.7);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(211, 255, 164);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(62, 74, 98);
border-collapse: collapse;
background-color: rgb(248, 247, 249);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(200, 205, 218);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(62, 74, 98);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(200, 205, 218);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(106, 169, 185);
background-color: rgb(17, 21, 28);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(46, 184, 140);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(18, 42, 63);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(42, 168, 137);
color: rgb(106, 169, 185);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(42, 168, 137);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(42, 168, 137) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(242, 130, 90);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgba(89, 156, 171, 0.7);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(43, 56, 79);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(89, 156, 171);
border-collapse: collapse;
background-color: rgb(10, 23, 34);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(18, 42, 63);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(89, 156, 171);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(18, 42, 63);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,4 +1,4 @@
.note-to-mp {
.note2any {
padding: 0 1em;
color: #595959;
font-size: 16px;
@@ -11,7 +11,7 @@
/* 主题自定义 end */
/* 布局,一般不需要改动 */
}
.note-to-mp blockquote {
.note2any blockquote {
margin-left: 0;
background-color: #ebf4ff;
border-color: #7f9cf5;
@@ -19,34 +19,34 @@
padding-bottom: 0.5rem;
color: #667eea;
}
.note-to-mp strong {
.note2any strong {
color: #5a67d8;
}
.note-to-mp a {
.note2any a {
border-color: #667eea;
}
.note-to-mp blockquote,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp ol,
.note-to-mp p,
.note-to-mp pre,
.note-to-mp table,
.note-to-mp ul {
.note2any blockquote,
.note2any details,
.note2any dl,
.note2any ol,
.note2any p,
.note2any pre,
.note2any table,
.note2any ul {
margin-bottom: 1rem;
}
.note-to-mp ol {
.note2any ol {
list-style: decimal;
}
.note-to-mp ul {
.note2any ul {
list-style: disc;
}
.note-to-mp ol,
.note-to-mp ul {
.note2any ol,
.note2any ul {
padding-left: 2em;
}
.note-to-mp h1,
.note-to-mp h2 {
.note2any h1,
.note2any h2 {
border-color: #5a67d8;
border-style: solid;
border-top-width: 0px;
@@ -56,50 +56,50 @@
padding-bottom: 0.25rem;
padding-left: 0.75rem;
}
.note-to-mp h1,
.note-to-mp h2 {
.note2any h1,
.note2any h2 {
border-bottom: 1px solid #eaecef !important;
border-left-width: 6px;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-bottom: 16px;
line-height: 1.25;
}
.note-to-mp blockquote {
.note2any blockquote {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
border-left: 0.25em solid;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp strong {
.note2any strong {
font-weight: bold;
}
.note-to-mp strong::before {
.note2any strong::before {
content: "「";
}
.note-to-mp strong::after {
.note2any strong::after {
content: "」";
}
.note-to-mp a {
.note2any a {
text-decoration: none;
border-bottom: 1px solid;
}
.note-to-mp .footnote-ref {
.note2any .footnote-ref {
border-width: 0px;
}
.note-to-mp picture img {
.note2any picture img {
border-radius: 6px;
display: block;
margin: 10px auto;
@@ -107,7 +107,7 @@
object-fit: contain;
box-shadow: 2px 4px 7px #999;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
display: block;
margin: 10px auto;
@@ -115,7 +115,7 @@
border-radius: 6px;
box-shadow: 2px 4px 7px #999;
}
.note-to-mp picture {
.note2any picture {
display: flex;
flex-direction: column;
justify-content: center;
@@ -123,31 +123,31 @@
margin-top: 6px;
margin-bottom: 6px;
}
.note-to-mp .footnotes {
.note2any .footnotes {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code,
.note-to-mp a {
.note2any code,
.note2any a {
color: #5a67d8;
}
.note-to-mp a {
.note2any a {
border-color: #667eea;
}
.note-to-mp code {
.note2any code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
background-color: #ebf4ff;
}
.note-to-mp pre > code {
.note2any pre > code {
background-color: transparent;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #5a67d8;
margin: 1.5em 0;
@@ -155,7 +155,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -163,12 +163,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -179,6 +179,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,4 +1,4 @@
.note-to-mp {
.note2any {
padding: 0 1em;
word-break: break-word;
line-height: 1.8;
@@ -12,32 +12,32 @@
background-size: 20px 20px;
background-position: center center;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
line-height: 1.5;
margin-top: 35px;
margin-bottom: 10px;
padding-bottom: 5px;
font-weight: 600;
}
.note-to-mp h1 {
.note2any h1 {
font-size: 30px;
margin-bottom: 5px;
}
.note-to-mp h2 {
.note2any h2 {
padding-bottom: 12px;
font-size: 24px;
border-bottom: 1px solid #ececec;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 18px;
padding-bottom: 0;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1.2em;
border-bottom: 2px solid rgb(239, 112, 96);
word-spacing: 0px !important;
@@ -53,21 +53,21 @@
border-top-left-radius: 3px;
margin-right: 3px;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 15px;
}
.note-to-mp h6 {
.note2any h6 {
margin-top: 5px;
}
.note-to-mp p {
.note2any p {
line-height: inherit;
margin-top: 22px;
margin-bottom: 22px;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
}
.note-to-mp hr {
.note2any hr {
border-top: 1px solid #ddd;
border-bottom: none;
border-left: none;
@@ -75,12 +75,12 @@
margin-top: 32px;
margin-bottom: 32px;
}
.note-to-mp a {
.note2any a {
text-decoration: none;
color: #0269c8;
border-bottom: 1px solid #d1e9ff;
}
.note-to-mp table {
.note2any table {
display: inline-block !important;
font-size: 12px;
width: auto;
@@ -88,55 +88,55 @@
overflow: auto;
border: solid 1px #f6f6f6;
}
.note-to-mp thead {
.note2any thead {
background: #f6f6f6;
color: #000;
text-align: left;
}
.note-to-mp tr:nth-child(2n) {
.note2any tr:nth-child(2n) {
background-color: #fcfcfc;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 12px 7px;
line-height: 24px;
}
.note-to-mp td {
.note2any td {
min-width: 120px;
}
.note-to-mp blockquote {
.note2any blockquote {
color: #666;
padding: 1px 23px;
margin: 22px 0;
border-left: 4px solid #cbcbcb;
background-color: #f8f8f8;
}
.note-to-mp blockquote > p {
.note2any blockquote > p {
margin: 10px 0;
}
.note-to-mp ol,
.note-to-mp ul {
.note2any ol,
.note2any ul {
padding-left: 28px;
}
.note-to-mp ol li,
.note-to-mp ul li {
.note2any ol li,
.note2any ul li {
margin-bottom: 0;
list-style: inherit;
}
.note-to-mp ol ul,
.note-to-mp ol ol,
.note-to-mp ul ul,
.note-to-mp ul ol {
.note2any ol ul,
.note2any ol ol,
.note2any ul ul,
.note2any ul ol {
margin-top: 3px;
}
.note-to-mp ol li {
.note2any ol li {
padding-left: 6px;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
word-break: break-word;
border-radius: 2px;
@@ -145,7 +145,7 @@
font-size: 0.87em;
padding: 0.065em 0.4em;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
font-size: inherit;
padding: 0;
margin: 0;
@@ -154,7 +154,7 @@
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #cbcbcb;
margin: 1.5em 0;
@@ -162,7 +162,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -170,12 +170,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -186,6 +186,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -14,26 +14,26 @@
/* header */
/* spacing */
/* table */
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
color: #1f2329;
line-height: 1.4;
font-weight: 600;
margin-top: 1em;
margin-bottom: 0.37em;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
margin-left: 0;
padding-left: 14px;
border-left: 2px solid #3370ff;
color: rgba(31, 35, 41, 0.7);
}
.note-to-mp a {
.note2any a {
overflow-wrap: break-word;
word-wrap: break-word;
white-space: pre-wrap;
@@ -42,7 +42,7 @@
color: #3370ff;
text-decoration: none;
}
.note-to-mp hr {
.note2any hr {
margin: 13px 0 12px;
border: 0px;
height: 1px;
@@ -50,41 +50,41 @@
background-image: linear-gradient(90deg, rgb(187, 191, 196), rgb(187, 191, 196));
background-repeat: no-repeat;
}
.note-to-mp ul > li:not([class*=task-list-item]) {
.note2any ul > li:not([class*=task-list-item]) {
word-wrap: break-all;
padding-left: 12px;
color: #3370ff;
}
.note-to-mp ul > li:not([class*=task-list-item]) > section {
.note2any ul > li:not([class*=task-list-item]) > section {
color: #1f2329;
}
.note-to-mp ul > li:not([class*=task-list-item])::marker {
.note2any ul > li:not([class*=task-list-item])::marker {
color: #3370ff;
}
.note-to-mp ol > li:not([class*=task-list-item]) {
.note2any ol > li:not([class*=task-list-item]) {
word-wrap: break-all;
padding-left: 12px;
}
.note-to-mp ol > li:not([class*=task-list-item]) > section {
.note2any ol > li:not([class*=task-list-item]) > section {
color: #1f2329;
}
.note-to-mp ol > li:not([class*=task-list-item])::marker {
.note2any ol > li:not([class*=task-list-item])::marker {
color: #3370ff;
}
.note-to-mp li + li,
.note-to-mp ul ul,
.note-to-mp ol ul,
.note-to-mp ul ol,
.note-to-mp ol ol,
.note-to-mp li ul,
.note-to-mp li ol {
.note2any li + li,
.note2any ul ul,
.note2any ol ul,
.note2any ul ol,
.note2any ol ol,
.note2any li ul,
.note2any li ol {
margin-top: 4px;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
border-radius: 4px;
margin-left: 2px;
margin-right: 2px;
@@ -94,7 +94,7 @@
line-height: 1.6em;
padding: 0 2px;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
border: none;
background-color: transparent;
line-height: inherit;
@@ -102,13 +102,13 @@
margin: 0;
text-wrap: nowrap;
}
.note-to-mp .code-section ul li {
.note2any .code-section ul li {
color: inherit;
margin: 0;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #dee0e3;
margin: 1.5em 0;
@@ -116,7 +116,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -124,12 +124,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -140,10 +140,10 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}
.note-to-mp strong {
.note2any strong {
color: rgb(36, 91, 219);
}

View File

@@ -14,26 +14,26 @@
/* header */
/* spacing */
/* table */
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
color: #1f2329;
line-height: 1.4;
font-weight: 600;
margin-top: 1em;
margin-bottom: 0.37em;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
margin-left: 0;
padding-left: 14px;
border-left: 2px solid #3370ff;
color: rgba(31, 35, 41, 0.7);
}
.note-to-mp a {
.note2any a {
overflow-wrap: break-word;
word-wrap: break-word;
white-space: pre-wrap;
@@ -42,7 +42,7 @@
color: #3370ff;
text-decoration: none;
}
.note-to-mp hr {
.note2any hr {
margin: 13px 0 12px;
border: 0px;
height: 1px;
@@ -50,41 +50,41 @@
background-image: linear-gradient(90deg, rgb(187, 191, 196), rgb(187, 191, 196));
background-repeat: no-repeat;
}
.note-to-mp ul > li:not([class*=task-list-item]) {
.note2any ul > li:not([class*=task-list-item]) {
word-wrap: break-all;
padding-left: 12px;
color: #3370ff;
}
.note-to-mp ul > li:not([class*=task-list-item]) > section {
.note2any ul > li:not([class*=task-list-item]) > section {
color: #1f2329;
}
.note-to-mp ul > li:not([class*=task-list-item])::marker {
.note2any ul > li:not([class*=task-list-item])::marker {
color: #3370ff;
}
.note-to-mp ol > li:not([class*=task-list-item]) {
.note2any ol > li:not([class*=task-list-item]) {
word-wrap: break-all;
padding-left: 12px;
}
.note-to-mp ol > li:not([class*=task-list-item]) > section {
.note2any ol > li:not([class*=task-list-item]) > section {
color: #1f2329;
}
.note-to-mp ol > li:not([class*=task-list-item])::marker {
.note2any ol > li:not([class*=task-list-item])::marker {
color: #3370ff;
}
.note-to-mp li + li,
.note-to-mp ul ul,
.note-to-mp ol ul,
.note-to-mp ul ol,
.note-to-mp ol ol,
.note-to-mp li ul,
.note-to-mp li ol {
.note2any li + li,
.note2any ul ul,
.note2any ol ul,
.note2any ul ol,
.note2any ol ol,
.note2any li ul,
.note2any li ol {
margin-top: 4px;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
border-radius: 4px;
margin-left: 2px;
margin-right: 2px;
@@ -94,7 +94,7 @@
line-height: 1.6em;
padding: 0 2px;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
border: none;
background-color: transparent;
line-height: inherit;
@@ -102,13 +102,13 @@
margin: 0;
text-wrap: nowrap;
}
.note-to-mp .code-section ul li {
.note2any .code-section ul li {
color: inherit;
margin: 0;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #dee0e3;
margin: 1.5em 0;
@@ -116,7 +116,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -124,12 +124,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -140,6 +140,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(253, 250, 224);
background-color: rgb(24, 24, 30);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(251, 239, 137);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(100, 176, 119);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(209, 95, 38);
color: rgb(253, 250, 224);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(209, 95, 38);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(209, 95, 38) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(123, 206, 171);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(204, 204, 204);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(21, 109, 104);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(204, 203, 204);
border-collapse: collapse;
background-color: rgb(27, 26, 34);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(100, 176, 119);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(204, 203, 204);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(100, 176, 119);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(237, 238, 243);
background-color: rgb(47, 52, 64);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(217, 221, 231);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(99, 110, 132);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(144, 185, 201);
color: rgb(237, 238, 243);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(144, 185, 201);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(144, 185, 201) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(167, 189, 144);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(160, 163, 171);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(155, 98, 100);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(237, 238, 243);
border-collapse: collapse;
background-color: rgb(54, 57, 69);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(99, 110, 132);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(237, 238, 243);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(99, 110, 132);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(66, 63, 55);
background-color: rgb(251, 250, 240);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(43, 100, 81);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(221, 219, 214);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(149, 175, 163);
color: rgb(66, 63, 55);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(149, 175, 163);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(149, 175, 163) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(33, 95, 79);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(126, 150, 143);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(249, 220, 175);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(89, 88, 82);
border-collapse: collapse;
background-color: rgb(254, 254, 248);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(221, 219, 214);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(89, 88, 82);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(221, 219, 214);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(246, 247, 238);
background-color: rgb(17, 28, 42);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(249, 181, 55);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(45, 69, 98);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(249, 181, 55);
color: rgb(246, 247, 238);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(249, 181, 55);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(249, 181, 55) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(84, 193, 220);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(176, 176, 176);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(45, 78, 120);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(246, 247, 238);
border-collapse: collapse;
background-color: rgb(23, 33, 52);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(45, 69, 98);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(246, 247, 238);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(45, 69, 98);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: #222222;
background-color: #fcfcfc;
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: #262626;
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: #bfbfbf;
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid #e06e73;
color: #222222;
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: #e06e73;
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, #e06e73 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: #de4c4f;
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: #525252;
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: #fcffc0;
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: #424242;
border-collapse: collapse;
background-color: white;
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid #bfbfbf;
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: #424242;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #bfbfbf;
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,4 +1,4 @@
.note-to-mp {
.note2any {
color: #595959;
font-size: 15px;
background-image: linear-gradient(90deg, rgba(60, 10, 30, 0.04) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(60, 10, 30, 0.04) 3%, rgba(0, 0, 0, 0) 3%);
@@ -21,101 +21,101 @@
/* 分隔线 */
/* 表格 */
}
.note-to-mp p {
.note2any p {
color: #595959;
font-size: 15px;
line-height: 2;
font-weight: 400;
}
.note-to-mp p + p {
.note2any p + p {
margin-top: 16px;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
padding: 30px 0;
margin: 0;
color: #135ce0;
font-weight: 600;
}
.note-to-mp h1 {
.note2any h1 {
position: relative;
text-align: center;
font-size: 22px;
margin: 50px 0;
}
.note-to-mp h2 {
.note2any h2 {
position: relative;
font-size: 20px;
border-left: 4px solid;
padding: 0 0 0 10px;
margin: 30px 0;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 16px;
}
.note-to-mp ul {
.note2any ul {
list-style: disc outside;
margin-left: 2em;
margin-top: 1em;
}
.note-to-mp li {
.note2any li {
line-height: 2;
color: #595959;
margin-bottom: 0;
list-style: inherit;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
}
.note-to-mp blockquote {
.note2any blockquote {
background: #fff9f9;
margin: 2em 0;
padding: 2px 20px;
border-left: 4px solid #b2aec5;
}
.note-to-mp blockquote p {
.note2any blockquote p {
color: #666;
line-height: 2;
}
.note-to-mp a {
.note2any a {
color: #036aca;
border-bottom: 1px solid rgba(3, 106, 202, 0.8);
font-weight: 400;
text-decoration: none;
}
.note-to-mp strong {
.note2any strong {
color: #036aca;
}
.note-to-mp em strong {
.note2any em strong {
color: #036aca;
}
.note-to-mp hr {
.note2any hr {
border-top: 1px solid #135ce0;
}
.note-to-mp table {
.note2any table {
border-collapse: collapse;
margin: 1rem 0;
overflow-x: auto;
}
.note-to-mp table th,
.note-to-mp table td {
.note2any table th,
.note2any table td {
border: 1px solid #dfe2e5;
padding: 0.6em 1em;
}
.note-to-mp table tr {
.note2any table tr {
border-top: 1px solid #dfe2e5;
}
.note-to-mp table tr:nth-child(2n) {
.note2any table tr:nth-child(2n) {
background-color: #f6f8fa;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
word-break: break-word;
border-radius: 2px;
background-color: #fff5f5;
@@ -123,7 +123,7 @@
font-size: 0.87em;
padding: 0.065em 0.4em;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
border: none;
background-color: transparent;
font-size: inherit;
@@ -131,12 +131,12 @@
margin: 0 !important;
text-wrap: nowrap;
}
.note-to-mp .code-section ul li {
.note2any .code-section ul li {
line-height: inherit;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #ff502c;
margin: 1.5em 0;
@@ -144,7 +144,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -152,12 +152,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -168,6 +168,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(155, 166, 164);
background-color: rgb(11, 55, 66);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(171, 181, 180);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(3, 44, 54);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(44, 146, 133);
color: rgb(155, 166, 164);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(44, 146, 133);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(44, 146, 133) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(63, 198, 180);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(106, 134, 144);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(31, 0, 50);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(148, 162, 162);
border-collapse: collapse;
background-color: rgb(6, 33, 40);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(3, 44, 54);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(148, 162, 162);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(3, 44, 54);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(50, 62, 69);
background-color: rgb(253, 246, 227);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(59, 79, 84);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgba(147, 161, 161, 0.5);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(165, 104, 18);
color: rgb(50, 62, 69);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(165, 104, 18);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(165, 104, 18) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(172, 117, 20);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(113, 127, 125);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(202, 255, 147);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(101, 123, 131);
border-collapse: collapse;
background-color: rgb(252, 244, 220);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgba(147, 161, 161, 0.5);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(101, 123, 131);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgba(147, 161, 161, 0.5);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -19,7 +19,7 @@
* Bear 的默认样式表。通过调整各个颜色变量的取值,就可以得到不同的 bear 主题。
* Bear 的配色方案位于 src/themes/bear-palettes 目录下。
*/
.note-to-mp {
.note2any {
font-size: 16px;
color: rgb(220, 227, 232);
background-color: rgb(34, 46, 51);
@@ -27,29 +27,29 @@
margin: 0 0;
padding: 1em 1em;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp details,
.note-to-mp dl,
.note-to-mp blockquote,
.note-to-mp table,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp figure {
.note2any p,
.note2any pre,
.note2any dl,
.note2any form,
.note2any details,
.note2any dl,
.note2any blockquote,
.note2any table,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any figure {
margin: 0.75em 0 0.45em;
}
.note-to-mp hr {
.note2any hr {
margin: 0.75em auto;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin-top: 1.5em;
margin-bottom: 0.75em;
margin-left: 0;
@@ -58,122 +58,122 @@
line-height: 1.5em;
color: rgb(131, 209, 221);
}
.note-to-mp h1 {
.note2any h1 {
font-size: 1.5em;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.3em;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.1em;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1em;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1em;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1em;
}
.note-to-mp hr {
.note2any hr {
height: 1px;
border: 0;
background-color: rgb(15, 21, 23);
border-style: inset;
border-width: 1px;
}
.note-to-mp p {
.note2any p {
margin-left: 0;
margin-right: 0;
}
.note-to-mp pre {
.note2any pre {
padding: 0;
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
display: block;
padding-left: 0.8em;
border-left: 0.2em solid rgb(199, 191, 127);
color: rgb(220, 227, 232);
}
.note-to-mp blockquote > :first-child {
.note2any blockquote > :first-child {
margin-top: 0;
}
.note-to-mp blockquote > :last-child {
.note2any blockquote > :last-child {
margin-bottom: 0;
}
.note-to-mp li {
.note2any li {
word-wrap: break-all;
}
.note-to-mp ul {
.note2any ul {
margin-left: 1.3em;
padding: 0;
}
.note-to-mp li::marker {
.note2any li::marker {
color: rgb(199, 191, 127);
}
.note-to-mp li > p {
.note2any li > p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
padding-left: 1.3em;
list-style-type: decimal;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
height: auto;
}
.note-to-mp u {
.note2any u {
text-decoration: none;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgb(199, 191, 127) 50%);
background-repeat: repeat-x;
background-size: 2px 2px;
background-position: 0 1em;
}
.note-to-mp a {
.note2any a {
color: rgb(214, 92, 92);
text-decoration: none;
}
.note-to-mp a img {
.note2any a img {
border: none;
}
.note-to-mp b,
.note-to-mp strong {
.note2any b,
.note2any strong {
font-weight: bold;
}
.note-to-mp i,
.note-to-mp cite,
.note-to-mp em,
.note-to-mp var,
.note-to-mp address,
.note-to-mp dfn {
.note2any i,
.note2any cite,
.note2any em,
.note2any var,
.note2any address,
.note2any dfn {
font-style: italic;
}
.note-to-mp del,
.note-to-mp s {
.note2any del,
.note2any s {
color: rgb(191, 191, 191);
}
.note-to-mp pre,
.note-to-mp xmp,
.note-to-mp plaintext,
.note-to-mp listing,
.note-to-mp code,
.note-to-mp kbd,
.note-to-mp tt,
.note-to-mp samp {
.note2any pre,
.note2any xmp,
.note2any plaintext,
.note2any listing,
.note2any code,
.note2any kbd,
.note2any tt,
.note2any samp {
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp mark {
.note2any mark {
color: inherit;
display: inline;
padding: 0.2em 0.5em;
background-color: rgb(64, 65, 113);
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
}
.note-to-mp table {
.note2any table {
color: rgb(168, 176, 181);
border-collapse: collapse;
background-color: rgb(18, 24, 27);
@@ -182,33 +182,33 @@
border: 1px;
border-spacing: 0;
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 0.7em 1em;
font-size: 0.9em;
border: 1px solid rgb(15, 21, 23);
}
.note-to-mp caption,
.note-to-mp th,
.note-to-mp td {
.note2any caption,
.note2any th,
.note2any td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
.note-to-mp .footnotes > ol li {
.note2any .footnotes > ol li {
text-indent: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
display: inline;
color: rgb(168, 176, 181);
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px rgb(15, 21, 23);
margin: 1.5em 0;
@@ -216,7 +216,7 @@
padding: 0.5em;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -224,12 +224,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo-Regular, Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -240,6 +240,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,5 +1,5 @@
/* MWeb增大字体便于阅读 */
.note-to-mp {
.note2any {
font-size: 16px;
min-width: 200px;
max-width: 760px;
@@ -41,70 +41,70 @@
/* Responsive images */
/* 代码片断 */
}
.note-to-mp dl,
.note-to-mp dt,
.note-to-mp dd,
.note-to-mp ul,
.note-to-mp ol,
.note-to-mp li,
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6,
.note-to-mp pre,
.note-to-mp code,
.note-to-mp form,
.note-to-mp fieldset,
.note-to-mp legend,
.note-to-mp input,
.note-to-mp textarea,
.note-to-mp p,
.note-to-mp blockquote,
.note-to-mp th,
.note-to-mp td,
.note-to-mp hr,
.note-to-mp button,
.note-to-mp article,
.note-to-mp aside,
.note-to-mp details,
.note-to-mp figcaption,
.note-to-mp figure,
.note-to-mp footer,
.note-to-mp header,
.note-to-mp menu,
.note-to-mp nav,
.note-to-mp section {
.note2any dl,
.note2any dt,
.note2any dd,
.note2any ul,
.note2any ol,
.note2any li,
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6,
.note2any pre,
.note2any code,
.note2any form,
.note2any fieldset,
.note2any legend,
.note2any input,
.note2any textarea,
.note2any p,
.note2any blockquote,
.note2any th,
.note2any td,
.note2any hr,
.note2any button,
.note2any article,
.note2any aside,
.note2any details,
.note2any figcaption,
.note2any figure,
.note2any footer,
.note2any header,
.note2any menu,
.note2any nav,
.note2any section {
margin: 0;
padding: 0;
}
.note-to-mp article,
.note-to-mp aside,
.note-to-mp details,
.note-to-mp figcaption,
.note-to-mp figure,
.note-to-mp footer,
.note-to-mp header,
.note-to-mp menu,
.note-to-mp nav,
.note-to-mp section {
.note2any article,
.note2any aside,
.note2any details,
.note2any figcaption,
.note2any figure,
.note2any footer,
.note2any header,
.note2any menu,
.note2any nav,
.note2any section {
display: block;
}
.note-to-mp audio,
.note-to-mp canvas,
.note-to-mp video {
.note2any audio,
.note2any canvas,
.note2any video {
display: inline-block;
}
.note-to-mp table {
.note2any table {
border-collapse: collapse;
border-spacing: 0;
}
.note-to-mp fieldset,
.note-to-mp img {
.note2any fieldset,
.note2any img {
border: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
position: relative;
color: #999;
font-weight: 400;
@@ -112,251 +112,251 @@
padding-left: 1em;
margin: 1em 3em 1em 2em;
}
.note-to-mp acronym,
.note-to-mp abbr {
.note2any acronym,
.note2any abbr {
border-bottom: 1px dotted;
font-variant: normal;
text-decoration: none;
}
.note-to-mp abbr {
.note2any abbr {
cursor: help;
}
.note-to-mp del {
.note2any del {
text-decoration: line-through;
}
.note-to-mp address,
.note-to-mp caption,
.note-to-mp cite,
.note-to-mp code,
.note-to-mp dfn,
.note-to-mp em,
.note-to-mp th,
.note-to-mp var {
.note2any address,
.note2any caption,
.note2any cite,
.note2any code,
.note2any dfn,
.note2any em,
.note2any th,
.note2any var {
font-style: normal;
font-weight: 400;
}
.note-to-mp ul,
.note-to-mp ol {
.note2any ul,
.note2any ol {
list-style: none;
}
.note-to-mp caption,
.note-to-mp th {
.note2any caption,
.note2any th {
text-align: left;
}
.note-to-mp sub,
.note-to-mp sup {
.note2any sub,
.note2any sup {
font-size: 75%;
line-height: 0;
position: relative;
}
.note-to-mp :root sub,
.note-to-mp :root sup {
.note2any :root sub,
.note2any :root sup {
vertical-align: baseline;
/* for ie9 and other modern browsers */
}
.note-to-mp sup {
.note2any sup {
top: -0.5em;
}
.note-to-mp sub {
.note2any sub {
bottom: -0.25em;
}
.note-to-mp a {
.note2any a {
color: #1abc9c;
}
.note-to-mp a:hover {
.note2any a:hover {
text-decoration: underline;
}
.note-to-mp a {
.note2any a {
border-bottom: 1px solid #1abc9c;
}
.note-to-mp a:hover {
.note2any a:hover {
border-bottom-color: #555;
color: #555;
text-decoration: none;
}
.note-to-mp ins,
.note-to-mp a {
.note2any ins,
.note2any a {
text-decoration: none;
}
.note-to-mp u,
.note-to-mp .typo-u {
.note2any u,
.note2any .typo-u {
text-decoration: underline;
}
.note-to-mp mark {
.note2any mark {
background: #fffdd1;
border-bottom: 1px solid #ffedce;
padding: 2px;
/* margin: 0 5px; */
}
.note-to-mp hr {
.note2any hr {
border: none;
border-bottom: 1px solid #cfcfcf;
margin-bottom: 0.8em;
height: 10px;
}
.note-to-mp small,
.note-to-mp .typo-small,
.note-to-mp figcaption {
.note2any small,
.note2any .typo-small,
.note2any figcaption {
font-size: 0.9em;
color: #888;
}
.note-to-mp strong,
.note-to-mp b {
.note2any strong,
.note2any b {
font-weight: bold;
color: #000;
}
.note-to-mp [draggable] {
.note2any [draggable] {
cursor: move;
}
.note-to-mp .clearfix {
.note2any .clearfix {
zoom: 1;
}
.note-to-mp .textwrap,
.note-to-mp .textwrap td,
.note-to-mp .textwrap th {
.note2any .textwrap,
.note2any .textwrap td,
.note2any .textwrap th {
word-wrap: break-word;
word-break: break-all;
}
.note-to-mp .textwrap-table {
.note2any .textwrap-table {
table-layout: fixed;
}
.note-to-mp .serif {
.note2any .serif {
font-family: Palatino, Optima, Georgia, serif;
}
.note-to-mp p,
.note-to-mp pre,
.note-to-mp ul,
.note-to-mp ol,
.note-to-mp dl,
.note-to-mp form,
.note-to-mp hr,
.note-to-mp table,
.note-to-mp .typo-p,
.note-to-mp .typo-pre,
.note-to-mp .typo-ul,
.note-to-mp .typo-ol,
.note-to-mp .typo-dl,
.note-to-mp .typo-form,
.note-to-mp .typo-hr,
.note-to-mp .typo-table,
.note-to-mp blockquote {
.note2any p,
.note2any pre,
.note2any ul,
.note2any ol,
.note2any dl,
.note2any form,
.note2any hr,
.note2any table,
.note2any .typo-p,
.note2any .typo-pre,
.note2any .typo-ul,
.note2any .typo-ol,
.note2any .typo-dl,
.note2any .typo-form,
.note2any .typo-hr,
.note2any .typo-table,
.note2any blockquote {
margin-bottom: 1.2em;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
font-family: PingFang SC, Verdana, Helvetica Neue, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif;
font-weight: lighter;
color: #000;
line-height: 1.35;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6,
.note-to-mp .typo-h1,
.note-to-mp .typo-h2,
.note-to-mp .typo-h3,
.note-to-mp .typo-h4,
.note-to-mp .typo-h5,
.note-to-mp .typo-h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6,
.note2any .typo-h1,
.note2any .typo-h2,
.note2any .typo-h3,
.note2any .typo-h4,
.note2any .typo-h5,
.note2any .typo-h6 {
margin-top: 1.2em;
margin-bottom: 0.6em;
line-height: 1.35;
}
.note-to-mp h1,
.note-to-mp .typo-h1 {
.note2any h1,
.note2any .typo-h1 {
font-size: 2em;
}
.note-to-mp h2,
.note-to-mp .typo-h2 {
.note2any h2,
.note2any .typo-h2 {
font-size: 1.8em;
}
.note-to-mp h3,
.note-to-mp .typo-h3 {
.note2any h3,
.note2any .typo-h3 {
font-size: 1.6em;
}
.note-to-mp h4,
.note-to-mp .typo-h4 {
.note2any h4,
.note2any .typo-h4 {
font-size: 1.4em;
}
.note-to-mp h5,
.note-to-mp h6,
.note-to-mp .typo-h5,
.note-to-mp .typo-h6 {
.note2any h5,
.note2any h6,
.note2any .typo-h5,
.note2any .typo-h6 {
font-size: 1.2em;
}
.note-to-mp ul,
.note-to-mp .typo-ul {
.note2any ul,
.note2any .typo-ul {
margin-left: 1.3em;
list-style: disc;
}
.note-to-mp ol,
.note-to-mp .typo-ol {
.note2any ol,
.note2any .typo-ol {
list-style: decimal;
margin-left: 1.9em;
}
.note-to-mp li ul,
.note-to-mp li ol,
.note-to-mp .typo-ul ul,
.note-to-mp .typo-ul ol,
.note-to-mp .typo-ol ul,
.note-to-mp .typo-ol ol {
.note2any li ul,
.note2any li ol,
.note2any .typo-ul ul,
.note2any .typo-ul ol,
.note2any .typo-ol ul,
.note2any .typo-ol ol {
margin-bottom: 0.8em;
margin-left: 2em;
}
.note-to-mp li ul,
.note-to-mp .typo-ul ul,
.note-to-mp .typo-ol ul {
.note2any li ul,
.note2any .typo-ul ul,
.note2any .typo-ol ul {
list-style: circle;
}
.note-to-mp table th,
.note-to-mp table td,
.note-to-mp .typo-table th,
.note-to-mp .typo-table td,
.note-to-mp table caption {
.note2any table th,
.note2any table td,
.note2any .typo-table th,
.note2any .typo-table td,
.note2any table caption {
border: 1px solid #ddd;
padding: 0.5em 1em;
color: #666;
}
.note-to-mp table th,
.note-to-mp .typo-table th {
.note2any table th,
.note2any .typo-table th {
background: #fbfbfb;
}
.note-to-mp table thead th,
.note-to-mp .typo-table thead th {
.note2any table thead th,
.note2any .typo-table thead th {
background: #f1f1f1;
}
.note-to-mp table caption {
.note2any table caption {
border-bottom: none;
}
.note-to-mp .typo-em,
.note-to-mp em,
.note-to-mp legend,
.note-to-mp caption {
.note2any .typo-em,
.note2any em,
.note2any legend,
.note2any caption {
color: #000;
font-weight: inherit;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp pre,
.note-to-mp code,
.note-to-mp pre tt {
.note2any pre,
.note2any code,
.note2any pre tt {
font-family: Courier, "Courier New", monospace;
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #ddd;
margin: 1.5em 0;
@@ -364,7 +364,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -372,12 +372,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -388,6 +388,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,4 +1,4 @@
.note-to-mp {
.note2any {
word-break: break-word;
line-height: 1.75;
font-weight: 400;
@@ -6,79 +6,79 @@
overflow-x: hidden;
color: #333;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
line-height: 1.5;
margin-top: 35px;
margin-bottom: 10px;
padding-bottom: 5px;
}
.note-to-mp h1:first-child,
.note-to-mp h2:first-child,
.note-to-mp h3:first-child,
.note-to-mp h4:first-child,
.note-to-mp h5:first-child,
.note-to-mp h6:first-child {
.note2any h1:first-child,
.note2any h2:first-child,
.note2any h3:first-child,
.note2any h4:first-child,
.note2any h5:first-child,
.note2any h6:first-child {
margin-top: 0;
margin-bottom: 1rem;
}
.note-to-mp h1::before,
.note-to-mp h2::before,
.note-to-mp h3::before,
.note-to-mp h4::before,
.note-to-mp h5::before,
.note-to-mp h6::before {
.note2any h1::before,
.note2any h2::before,
.note2any h3::before,
.note2any h4::before,
.note2any h5::before,
.note2any h6::before {
content: "#";
display: inline-block;
color: #3eaf7c;
padding-right: 0.23em;
}
.note-to-mp h1 {
.note2any h1 {
position: relative;
font-size: 2.5rem;
margin-bottom: 5px;
}
.note-to-mp h1::before {
.note2any h1::before {
font-size: 2.5rem;
}
.note-to-mp h2 {
.note2any h2 {
padding-bottom: 0.5rem;
font-size: 2.2rem;
border-bottom: 1px solid #ececec;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.5rem;
padding-bottom: 0;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1.25rem;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1rem;
}
.note-to-mp h6 {
.note2any h6 {
margin-top: 5px;
}
.note-to-mp p {
.note2any p {
line-height: inherit;
margin-top: 22px;
margin-bottom: 22px;
}
.note-to-mp strong {
.note2any strong {
color: #3eaf7c;
}
.note-to-mp img {
.note2any img {
max-width: 100%;
border-radius: 2px;
display: block;
margin: auto;
border: 3px solid rgba(62, 175, 124, 0.2);
}
.note-to-mp hr {
.note2any hr {
border-top: 1px solid #3eaf7c;
border-bottom: none;
border-left: none;
@@ -86,12 +86,12 @@
margin-top: 32px;
margin-bottom: 32px;
}
.note-to-mp a {
.note2any a {
font-weight: 500;
text-decoration: none;
color: #3eaf7c;
}
.note-to-mp table {
.note2any table {
display: inline-block !important;
font-size: 12px;
width: auto;
@@ -99,23 +99,23 @@
overflow: auto;
border: solid 1px #3eaf7c;
}
.note-to-mp thead {
.note2any thead {
background: #3eaf7c;
color: #fff;
text-align: left;
}
.note-to-mp tr:nth-child(2n) {
.note2any tr:nth-child(2n) {
background-color: rgba(62, 175, 124, 0.2);
}
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
padding: 12px 7px;
line-height: 24px;
}
.note-to-mp td {
.note2any td {
min-width: 120px;
}
.note-to-mp blockquote {
.note2any blockquote {
color: #666;
padding: 1px 23px;
margin: 22px 0;
@@ -123,65 +123,65 @@
border-color: #42b983;
background-color: #f8f8f8;
}
.note-to-mp blockquote > p {
.note2any blockquote > p {
margin: 10px 0;
}
.note-to-mp details {
.note2any details {
border: none;
outline: none;
border-left: 4px solid #3eaf7c;
padding-left: 10px;
margin-left: 4px;
}
.note-to-mp details summary {
.note2any details summary {
cursor: pointer;
border: none;
outline: none;
background: white;
margin: 0px -17px;
}
.note-to-mp details summary::-webkit-details-marker {
.note2any details summary::-webkit-details-marker {
color: #3eaf7c;
}
.note-to-mp ol,
.note-to-mp ul {
.note2any ol,
.note2any ul {
padding-left: 28px;
}
.note-to-mp ol li,
.note-to-mp ul li {
.note2any ol li,
.note2any ul li {
margin-bottom: 0;
list-style: inherit;
}
.note-to-mp ol li .task-list-item,
.note-to-mp ul li .task-list-item {
.note2any ol li .task-list-item,
.note2any ul li .task-list-item {
list-style: none;
}
.note-to-mp ol li .task-list-item ul,
.note-to-mp ul li .task-list-item ul,
.note-to-mp ol li .task-list-item ol,
.note-to-mp ul li .task-list-item ol {
.note2any ol li .task-list-item ul,
.note2any ul li .task-list-item ul,
.note2any ol li .task-list-item ol,
.note2any ul li .task-list-item ol {
margin-top: 0;
}
.note-to-mp ol ul,
.note-to-mp ul ul,
.note-to-mp ol ol,
.note-to-mp ul ol {
.note2any ol ul,
.note2any ul ul,
.note2any ol ol,
.note2any ul ol {
margin-top: 3px;
}
.note-to-mp ol li {
.note2any ol li {
padding-left: 6px;
}
.note-to-mp ol li::marker {
.note2any ol li::marker {
color: #3eaf7c;
}
.note-to-mp ul li::marker {
.note2any ul li::marker {
color: #3eaf7c;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code {
.note2any code {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
word-break: break-word;
padding: 0.2rem 0.5rem;
@@ -191,10 +191,10 @@
background-color: rgba(27, 31, 35, 0.05);
border-radius: 3px;
}
.note-to-mp .code-section {
.note2any .code-section {
border-radius: 6px;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
border: none;
background-color: transparent;
font-size: inherit;
@@ -205,7 +205,7 @@
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #3eaf7c;
margin: 1.5em 0;
@@ -213,7 +213,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -221,12 +221,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -237,6 +237,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -1,4 +1,4 @@
.note-to-mp {
.note2any {
font-size: 16px;
color: #34495e;
line-height: 1.6rem;
@@ -7,23 +7,23 @@
overflow-x: hidden;
/* MWeb代码块高亮 */
}
.note-to-mp img {
.note2any img {
max-width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.note-to-mp a {
.note2any a {
color: #42b983;
font-weight: 600;
padding: 0 2px;
text-decoration: none;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
position: relative;
margin-top: 1rem;
margin-bottom: 1rem;
@@ -31,74 +31,74 @@
line-height: 1.4;
cursor: text;
}
.note-to-mp h1 tt,
.note-to-mp h1 code {
.note2any h1 tt,
.note2any h1 code {
font-size: inherit !important;
}
.note-to-mp h2 tt,
.note-to-mp h2 code {
.note2any h2 tt,
.note2any h2 code {
font-size: inherit !important;
}
.note-to-mp h3 tt,
.note-to-mp h3 code {
.note2any h3 tt,
.note2any h3 code {
font-size: inherit !important;
}
.note-to-mp h4 tt,
.note-to-mp h4 code {
.note2any h4 tt,
.note2any h4 code {
font-size: inherit !important;
}
.note-to-mp h5 tt,
.note-to-mp h5 code {
.note2any h5 tt,
.note2any h5 code {
font-size: inherit !important;
}
.note-to-mp h6 tt,
.note-to-mp h6 code {
.note2any h6 tt,
.note2any h6 code {
font-size: inherit !important;
}
.note-to-mp h2 a,
.note-to-mp h3 a {
.note2any h2 a,
.note2any h3 a {
color: #34495e;
}
.note-to-mp h1 {
.note2any h1 {
padding-bottom: 0.4rem;
font-size: 2.2rem;
line-height: 1.3;
}
.note-to-mp h2 {
.note2any h2 {
font-size: 1.75rem;
line-height: 1.225;
margin: 35px 0 15px;
padding-bottom: 0.5em;
border-bottom: 1px solid #ddd;
}
.note-to-mp h3 {
.note2any h3 {
font-size: 1.4rem;
line-height: 1.43;
margin: 20px 0 7px;
}
.note-to-mp h4 {
.note2any h4 {
font-size: 1.2rem;
}
.note-to-mp h5 {
.note2any h5 {
font-size: 1rem;
}
.note-to-mp h6 {
.note2any h6 {
font-size: 1rem;
color: #777;
}
.note-to-mp p,
.note-to-mp blockquote,
.note-to-mp ul,
.note-to-mp ol,
.note-to-mp dl,
.note-to-mp table {
.note2any p,
.note2any blockquote,
.note2any ul,
.note2any ol,
.note2any dl,
.note2any table {
margin: 0.8em 0;
}
.note-to-mp li > ol,
.note-to-mp li > ul {
.note2any li > ol,
.note2any li > ul {
margin: 0 0;
}
.note-to-mp hr {
.note2any hr {
height: 2px;
padding: 0;
margin: 16px 0;
@@ -107,50 +107,50 @@
overflow: hidden;
box-sizing: content-box;
}
.note-to-mp h1 p,
.note-to-mp h2 p,
.note-to-mp h3 p,
.note-to-mp h4 p,
.note-to-mp h5 p,
.note-to-mp h6 p {
.note2any h1 p,
.note2any h2 p,
.note2any h3 p,
.note2any h4 p,
.note2any h5 p,
.note2any h6 p {
margin-top: 0;
}
.note-to-mp li p.first {
.note2any li p.first {
display: inline-block;
}
.note-to-mp ul,
.note-to-mp ol {
.note2any ul,
.note2any ol {
padding-left: 30px;
}
.note-to-mp ul:first-child,
.note-to-mp ol:first-child {
.note2any ul:first-child,
.note2any ol:first-child {
margin-top: 0;
}
.note-to-mp ul:last-child,
.note-to-mp ol:last-child {
.note2any ul:last-child,
.note2any ol:last-child {
margin-bottom: 0;
}
.note-to-mp blockquote {
.note2any blockquote {
border-left: 4px solid #42b983;
padding: 10px 15px;
color: #777;
background-color: rgba(66, 185, 131, 0.1);
}
.note-to-mp table {
.note2any table {
padding: 0;
word-break: initial;
border-collapse: collapse;
}
.note-to-mp table tr {
.note2any table tr {
border-top: 1px solid #dfe2e5;
margin: 0;
padding: 0;
}
.note-to-mp table tr:nth-child(2n),
.note-to-mp thead {
.note2any table tr:nth-child(2n),
.note2any thead {
background-color: #fafafa;
}
.note-to-mp table tr th {
.note2any table tr th {
font-weight: bold;
border: 1px solid #dfe2e5;
border-bottom: 0;
@@ -158,40 +158,40 @@
margin: 0;
padding: 6px 13px;
}
.note-to-mp table tr td {
.note2any table tr td {
border: 1px solid #dfe2e5;
text-align: left;
margin: 0;
padding: 6px 13px;
}
.note-to-mp table tr th:first-child,
.note-to-mp table tr td:first-child {
.note2any table tr th:first-child,
.note2any table tr td:first-child {
margin-top: 0;
}
.note-to-mp table tr th:last-child,
.note-to-mp table tr td:last-child {
.note2any table tr th:last-child,
.note2any table tr td:last-child {
margin-bottom: 0;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
.note-to-mp code,
.note-to-mp tt {
.note2any code,
.note2any tt {
border-radius: 2px;
font-family: Roboto Mono, Source Sans Pro, Monaco, courier, monospace !important;
font-size: 0.92rem;
color: #e96900;
background-color: #f8f8f8;
}
.note-to-mp code {
.note2any code {
margin: 0 2px;
padding: 2px 4px;
}
.note-to-mp .code-section {
.note2any .code-section {
border-radius: 2px;
}
.note-to-mp .code-section pre code {
.note2any .code-section pre code {
border: none;
background-color: transparent;
font-size: inherit;
@@ -203,7 +203,7 @@
}
/* 代码块 */
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: solid 1px #e96900;
margin: 1.5em 0;
@@ -211,7 +211,7 @@
padding: 0.5em;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin: 0;
margin-block-start: 0;
margin-block-end: 0;
@@ -219,12 +219,12 @@
overflow-x: auto;
padding: 0 0 0 1em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
margin: 0;
padding: 0;
margin-block-start: 0;
@@ -235,6 +235,6 @@
line-height: 26px;
list-style-type: none;
}
.note-to-mp .code-section ul > li {
.note2any .code-section ul > li {
text-align: right;
}

View File

@@ -10,7 +10,7 @@
* - 在导出设置中选择 wx-mp-pro 主题
*/
.note-to-mp {
.note2any {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
font-size: 16px;
line-height: 1.75;
@@ -21,18 +21,18 @@
}
/* 段落 */
.note-to-mp p {
.note2any p {
margin: 1.2em 0;
letter-spacing: 0.05px;
}
/* 标题:更专业清晰的层级感 */
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5,
.note-to-mp h6 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5,
.note2any h6 {
margin: 2.2em 0 1em;
line-height: 1.4;
color: #111111;
@@ -41,15 +41,15 @@
letter-spacing: 2px;
}
.note-to-mp h1,
.note-to-mp h2,
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5 {
.note2any h1,
.note2any h2,
.note2any h3,
.note2any h4,
.note2any h5 {
}
/* H1卡片式 */
.note-to-mp h1 {
.note2any h1 {
font-size: 1.8em;
margin: 1.5em 0;
color: #1565F6;
@@ -59,7 +59,7 @@
}
/* H2左条卡片 */
.note-to-mp h2 {
.note2any h2 {
font-size: 1.5em;
margin: 2em 0 1.2em;
padding: 0.6em 1em;
@@ -70,36 +70,36 @@
}
/* H3-H5渐进缩小 */
.note-to-mp h3,
.note-to-mp h4,
.note-to-mp h5 {
.note2any h3,
.note2any h4,
.note2any h5 {
background: #f7f9fb;
color: #244b74;
padding: 0.7em 1.2em 0.7em 1.35em;
}
.note-to-mp h3 { font-size: 1.25em; }
.note-to-mp h4 { font-size: 1.1em; }
.note-to-mp h5 { font-size: 1em; }
.note2any h3 { font-size: 1.25em; }
.note2any h4 { font-size: 1.1em; }
.note2any h5 { font-size: 1em; }
/* 列表 */
.note-to-mp ul,
.note-to-mp ol {
.note2any ul,
.note2any ol {
margin: 1.2em 0 1.2em 1.4em;
padding: 0;
}
.note-to-mp li {
.note2any li {
margin: 0.4em 0;
line-height: 1.6;
}
.note-to-mp li p {
.note2any li p {
margin: 0.5em 0;
}
/* 链接 */
.note-to-mp a {
.note2any a {
color: #576b95;
text-decoration: none;
border-bottom: 1px solid rgba(87,107,149,0.3);
@@ -107,7 +107,7 @@
}
/* 引用:清晰专业的样式 */
.note-to-mp blockquote {
.note2any blockquote {
background: #f7f7f7;
border-left: 4px solid #07c160;
margin: 1.5em 0;
@@ -116,27 +116,27 @@
font-size: 0.95em;
}
.note-to-mp blockquote p {
.note2any blockquote p {
margin: 0.6em 0;
}
.note-to-mp blockquote p:first-child {
.note2any blockquote p:first-child {
margin-top: 0;
}
.note-to-mp blockquote p:last-child {
.note2any blockquote p:last-child {
margin-bottom: 0;
}
/* 代码块:清晰易读 */
.note-to-mp pre {
.note2any pre {
background: #f6f8fa !important;
border-radius: 5px;
overflow-x: auto;
border: 1px solid #e8e8e8 !important;
}
.note-to-mp pre code {
.note2any pre code {
display: block;
background: transparent !important;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
@@ -147,7 +147,7 @@
}
/* 行内代码 */
.note-to-mp code:not(pre code) {
.note2any code:not(pre code) {
background: #f6f8fa;
padding: 2px 4px;
border-radius: 3px;
@@ -158,7 +158,7 @@
}
/* 表格整体:连贯圆角边框 */
.note-to-mp table {
.note2any table {
width: 100%;
border-collapse: collapse; /* 合并边框,避免断开 */
margin: 1.8em 0;
@@ -169,8 +169,8 @@
}
/* 单元格 */
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
border: 1px solid #e0e0e0; /* 内部网格线 */
padding: 8px 10px;
text-align: left;
@@ -178,19 +178,19 @@
}
/* 表头 */
.note-to-mp thead th {
.note2any thead th {
background: #e8f5e9;
font-weight: 600;
color: #333;
}
/* 隔行条纹 */
.note-to-mp tbody tr:nth-child(even) {
.note2any tbody tr:nth-child(even) {
background: #fafafa;
}
/* 表格整体 */
.note-to-mp table {
.note2any table {
width: 100%;
border-collapse: collapse;
margin: 1.8em 0;
@@ -201,8 +201,8 @@
}
/* 单元格 */
.note-to-mp th,
.note-to-mp td {
.note2any th,
.note2any td {
border: 1px solid #e0e0e0;
padding: 8px 10px;
text-align: left;
@@ -211,31 +211,31 @@
}
/* 表头 */
.note-to-mp thead th {
.note2any thead th {
background: #e8f5e9;
font-weight: 600;
color: #333;
}
/* 隔行条纹 */
.note-to-mp tbody tr:nth-child(even) {
.note2any tbody tr:nth-child(even) {
background: #fafafa;
}
/* hover 效果 */
.note-to-mp tbody tr:hover {
.note2any tbody tr:hover {
background: #f1f8ff; /* 微蓝色高亮 */
}
/* 图片与图注 */
.note-to-mp img {
.note2any img {
max-width: 100%;
display: block;
margin: 1.5em auto;
border-radius: 4px;
}
.note-to-mp figcaption {
.note2any figcaption {
text-align: center;
font-size: 0.8em;
color: #888;
@@ -244,7 +244,7 @@
}
/* 分隔线 */
.note-to-mp hr {
.note2any hr {
border: 0;
height: 1px;
background: #e3e3e3;
@@ -252,7 +252,7 @@
}
/* 彩色标注块(预处理产生的 ||r/g/b/y */
.note-to-mp p[data-color-block] {
.note2any p[data-color-block] {
border-radius: 5px;
padding: 0.8em 1em;
margin: 1.5em 0;
@@ -260,59 +260,59 @@
line-height: 1.6;
}
.note-to-mp p[data-color-block="r"] {
.note2any p[data-color-block="r"] {
background: #ffebee;
border-left: 4px solid #ef5350;
}
.note-to-mp p[data-color-block="g"] {
.note2any p[data-color-block="g"] {
background: #e8f5e9;
border-left: 4px solid #4caf50;
}
.note-to-mp p[data-color-block="b"] {
.note2any p[data-color-block="b"] {
background: #e3f2fd;
border-left: 4px solid #2196f3;
}
.note-to-mp p[data-color-block="y"] {
.note2any p[data-color-block="y"] {
background: #fff8e1;
border-left: 4px solid #ffca28;
}
/* 专业标注提示 */
.note-to-mp p[data-note-type="tip"],
.note-to-mp p[data-note-type="info"],
.note-to-mp p[data-note-type="warning"],
.note-to-mp p[data-note-type="danger"] {
.note2any p[data-note-type="tip"],
.note2any p[data-note-type="info"],
.note2any p[data-note-type="warning"],
.note2any p[data-note-type="danger"] {
border-radius: 5px;
padding: 0.8em 1em;
margin: 1.5em 0;
font-size: 0.93em;
}
.note-to-mp p[data-note-type="tip"] {
.note2any p[data-note-type="tip"] {
background: #e8f5e9;
border-left: 4px solid #4caf50;
}
.note-to-mp p[data-note-type="info"] {
.note2any p[data-note-type="info"] {
background: #e3f2fd;
border-left: 4px solid #2196f3;
}
.note-to-mp p[data-note-type="warning"] {
.note2any p[data-note-type="warning"] {
background: #fff8e1;
border-left: 4px solid #ffca28;
}
.note-to-mp p[data-note-type="danger"] {
.note2any p[data-note-type="danger"] {
background: #ffebee;
border-left: 4px solid #ef5350;
}
/* 特殊标注:重要/注意/提示 */
.note-to-mp p:has(strong:first-child:contains("💡")) {
.note2any p:has(strong:first-child:contains("💡")) {
background: #e8f5e9;
border-left: 4px solid #4caf50;
border-radius: 5px;
@@ -320,7 +320,7 @@
margin: 1.5em 0;
}
.note-to-mp p:has(strong:first-child:contains("⚠️")) {
.note2any p:has(strong:first-child:contains("⚠️")) {
background: #fff8e1;
border-left: 4px solid #ffca28;
border-radius: 5px;
@@ -328,7 +328,7 @@
margin: 1.5em 0;
}
.note-to-mp p:has(strong:first-child:contains("✅")) {
.note2any p:has(strong:first-child:contains("✅")) {
background: #e3f2fd;
border-left: 4px solid #2196f3;
border-radius: 5px;
@@ -337,14 +337,14 @@
}
/* 首段紧贴标题 */
.note-to-mp h1 + p,
.note-to-mp h2 + p,
.note-to-mp h3 + p {
.note2any h1 + p,
.note2any h2 + p,
.note2any h3 + p {
margin-top: 0.7em;
}
/* 专业编程文章必备:行号提示标记 */
.note-to-mp .line-numbers {
.note2any .line-numbers {
font-size: 0.8em;
color: #999;
margin-right: 0.5em;
@@ -352,23 +352,23 @@
}
/* 确保兼容微信的富文本环境 */
.note-to-mp pre code * {
.note2any pre code * {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace !important;
}
/* 适配微信公众号的粗体强调 */
.note-to-mp strong {
.note2any strong {
font-weight: 600;
color: #1322c5;
}
/* 行内高亮 */
.note-to-mp mark {
.note2any mark {
background: #fff8dc;
padding: 0 2px;
}
/* 确保代码块内部的空格不会被压缩 */
.note-to-mp pre code {
.note2any pre code {
white-space: pre !important;
}

View File

@@ -2,8 +2,17 @@
set -e # 出错立即退出
# 1. 构建
echo "🏗️ 开始构建..."
if npm run build; then
MODE="$1"
BUILD_CMD=(npm run build)
if [[ "$MODE" == "obf" ]]; then
BUILD_CMD=(npm run build:obf)
echo "🏗️ 开始构建(启用混淆)..."
else
echo "🏗️ 开始构建(不启用混淆)..."
fi
if "${BUILD_CMD[@]}"; then
echo "✅ 构建成功"
echo
else
@@ -13,7 +22,7 @@ else
fi
# 2. 目标目录
PLUGIN_DIR=~/myweb/.obsidian/plugins/note-to-mp
PLUGIN_DIR=~/myweb/.obsidian/plugins/note2any
FILES=("main.js" "styles.css" "manifest.json")
# 3. 遍历文件,逐一备份并覆盖

View File

@@ -12,6 +12,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
### Changed
- README新增图片方向处理说明、Gallery 参数使用示例。
- 预览布局:微信与小红书界面改为统一的网格化布局(`wechat-board` / `xhs-board`),组件按区域栅格排列,便于维护与对齐。
### Notes
- 若遇到其他 EXIF 方向值(除 1/3/6/8当前保持原样可后续扩展。
@@ -35,4 +36,3 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- 发布新版本:更新 `package.json` / `manifest.json` 的版本号;追加 `versions.json`;将当前 Unreleased 条目移动为新的版本号,并添加日期;再创建新的 Unreleased 模板。
- 提交信息建议:`feat: ...`, `fix: ...`, `docs: ...`, `refactor: ...` 等 Conventional Commits 风格。

View File

@@ -0,0 +1,168 @@
# Note2Any v1.3.12 系统优化报告
## 概述
本次优化针对项目的架构、可维护性、错误处理和用户体验进行了全面提升,创建了模块化的核心系统架构。
## 核心优化内容
### 1. 核心架构模块化
#### 新增核心模块
- **错误处理模块** (`src/core/error-handler.ts`)
- 统一的错误处理机制
- 错误日志记录和分类
- 用户友好的错误提示
- **进度指示器** (`src/core/progress-indicator.ts`)
- 统一的进度反馈系统
- 支持开始、更新、完成、错误状态
- 提升用户体验
- **配置管理器** (`src/core/config-manager.ts`)
- 中心化的配置管理
- 运行时配置验证
- 配置热更新支持
- **发布平台接口** (`src/core/publisher-interface.ts`)
- 标准化的平台发布接口
- 支持微信、小红书等多平台
- 可扩展的发布架构
- **发布管理器** (`src/core/publisher-manager.ts`)
- 中心化的平台管理
- 统一的发布流程
- 平台无关的业务逻辑
- **内容处理器** (`src/core/content-processor.ts`)
- 模块化的内容处理流程
- 可配置的处理管道
- 支持自定义处理器扩展
### 2. 专业化处理模块
#### 图库处理器 (`src/core/gallery-processor.ts`)
- 专门处理图库短代码
- 支持目录式和块级图库
- 智能图片选择算法
- 本地图片扫描优化
#### 图像处理器 (`src/core/image-processor.ts`)
- 统一的图像处理接口
- WebP转JPG转换
- 批量图像处理
- 微信图像上传集成
- HTML转PNG功能
#### HTML处理器 (`src/core/html-processor.ts`)
- HTML内容生成和格式化
- CSS样式内联处理
- 响应式设计优化
- 移动端适配
- 打印样式支持
### 3. 主要代码文件优化
#### `src/main.ts`
- 集成新的核心模块
- 添加进度指示和错误处理
- 优化插件初始化流程
#### `src/preview-view.ts`
- 添加进度反馈
- 统一错误处理
- 优化视图生命周期管理
## 技术改进
### 错误处理
- **之前**: 分散的try-catch不一致的错误提示
- **现在**: 统一的ErrorHandler系统集中的错误处理和日志
### 用户反馈
- **之前**: 缺乏操作进度反馈
- **现在**: ProgressIndicator提供实时进度和状态提示
### 配置管理
- **之前**: 配置散布在各个文件
- **现在**: ConfigManager集中管理类型安全的配置访问
### 发布架构
- **之前**: 平台特定的紧耦合代码
- **现在**: IPlatformPublisher接口松耦合的可扩展架构
### 内容处理
- **之前**: 单一巨大文件处理所有内容
- **现在**: 模块化处理器,职责明确,易于测试和维护
## 性能优化
### 模块化加载
- 按需加载核心模块
- 减少初始化时间
- 优化内存使用
### 异步处理
- 非阻塞的图像处理
- 并行的资源加载
- 流式的内容处理
### 缓存优化
- 智能的配置缓存
- 图像处理结果缓存
- CSS样式缓存
## 可维护性提升
### 代码组织
- 明确的模块职责分离
- 统一的接口和约定
- 完善的类型定义
### 扩展性
- 插件化的处理器架构
- 标准化的平台接口
- 配置驱动的功能开关
### 测试友好
- 依赖注入设计
- 模块化的单元测试
- 清晰的接口边界
## 兼容性保证
### 向后兼容
- 保持现有API不变
- 渐进式架构升级
- 配置格式向下兼容
### 平滑升级
- 不影响现有功能
- 渐进式功能启用
- 可回滚的架构变更
## 未来扩展方向
### 新平台支持
- 基于IPlatformPublisher接口
- 标准化的平台接入流程
- 统一的认证和发布机制
### 处理器生态
- 自定义内容处理器
- 第三方处理器集成
- 处理器市场和分享
### 智能化功能
- AI内容优化
- 智能格式转换
- 自动化发布流程
## 总结
本次优化通过引入现代化的架构模式,显著提升了代码的:
- **可维护性**: 模块化设计,职责清晰
- **可扩展性**: 接口标准化,插件化架构
- **用户体验**: 进度反馈,错误处理优化
- **开发效率**: 统一的开发模式,完善的类型系统
这为Note2Any项目的长期发展奠定了坚实的技术基础。

View File

@@ -75,14 +75,17 @@ git checkout -b release/v1.3.0
### 4. 构建项目
构建项目生成生产版本文件
构建项目生成发布所需的产物
```bash
# 执行项目构建
# 执行未混淆构建(推荐用于验证与调试)
npm run build
# 检查构建输出
ls -la main.js manifest.json
# 如需生成混淆后的发布包,可执行:
npm run build:obf
```
### 5. 创建归档目录
@@ -587,4 +590,4 @@ update_package_version() {
- **脚本优化**:根据使用情况改进自动化工具
- **文档更新**:保持版本管理文档的时效性
通过遵循这个完整的流程和使用提供的自动化工具,可以建立起稳健的版本管理体系,为项目的长期发展和维护提供强有力的支撑。
通过遵循这个完整的流程和使用提供的自动化工具,可以建立起稳健的版本管理体系,为项目的长期发展和维护提供强有力的支撑。

View File

@@ -21,7 +21,7 @@
如n=2取出的图片为xx.jpg,yy.png那么把{{<gallery dir="/img/guanzhan/1" figcaption="毕业展"/>}}{{<load-photoswipe>}}替换为:
![[xx.jpg]]
![[yy.png]]
3.
对如下:
@@ -46,7 +46,7 @@ src可能使用link
4.
参考以下代码,渲染[fig content/],|| content,||r content,||g content,||b content等标签
参考以下代码,渲染[fig content/],|| content,||r content,||g content,||b content等标签
`\[fig([^>]*?)/\]` `<span style="font-style: italic; font-size: 14px; background-color: #f5f5f5; padding: 2px;">$1</span>`
`\|\| (.*)` `<p style="font-family:'Microsoft YaHei',sans-serif;background-color:#E5E4E2 ;padding:10px;border-radius:20px;line-height:30px;">$1</p>`
`\|\|r (.*)` `<p style="font-family:'Microsoft YaHei',sans-serif;color:white;background-color:#6F4E37;padding:10px;border-radius:20px;line-height:30px;">$1</p>`
@@ -105,7 +105,9 @@ views:
```
10. 默认选择“原创”“允许留言”。
10. 默认选择
- “允许留言” ✅
- “原创”
11. gallery短代码增加是否使用dir中的所有图片的开关。mppickall=1选取dir中的所有图片mppickall=0按“选取图片数”配置选取图片数量。
{{<gallery dir="/img/guanzhan/1" figcaption="毕业展" mppickall=1/>}}{{<load-photoswipe>}}
@@ -136,3 +138,7 @@ Orientation : 6 -- 图片左旋90度需右选90才正常。
为了规避这个问题图片不做旋转处理直接转为png上传公众号。解决。因为PNG不带orientation信息。
- 封面图片没有正确旋转。
公众号上传仍然有图片旋转问题同样需要取png图片避免旋转问题

View File

@@ -1,6 +1,7 @@
import esbuild from "esbuild";
import process from "process";
import builtins from "builtin-modules";
import javascriptObfuscatorPlugin from "./tools/esbuild-obfuscator-plugin.mjs";
const banner =
`/*
@@ -10,6 +11,25 @@ if you want to view the source, please visit the github repository of this plugi
`;
const prod = (process.argv[2] === "production");
const obfuscate = prod && process.env.OBFUSCATE === "1";
const plugins = [];
if (obfuscate) {
plugins.push(javascriptObfuscatorPlugin({
compact: false,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
disableConsoleOutput: true,
identifierNamesGenerator: "hexadecimal",
log: false,
renameGlobals: false,
simplify: true,
splitStrings: false,
transformObjectKeys: true,
}));
}
const context = await esbuild.context({
banner: {
@@ -38,6 +58,7 @@ const context = await esbuild.context({
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
plugins,
});
if (prod) {
@@ -45,4 +66,4 @@ if (prod) {
process.exit(0);
} else {
await context.watch();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,10 +1,11 @@
{
"id": "note-to-mp",
"name": "NoteToAny",
"version": "1.3.4",
"id": "note2any",
"name": "Note2Any",
"version": "1.4.0",
"minAppVersion": "1.4.5",
"description": "xiaohongshu/mp publisher ",
"author": "Gavin chan",
"authorUrl": "https://biboer.cn",
"isDesktopOnly": false
"isDesktopOnly": false,
"fundingUrl": "https://biboer.cn/gitea/gavin/note2any"
}

1020
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,21 @@
{
"name": "note-to-mp",
"version": "1.3.0",
"name": "note2any",
"version": "1.4.0",
"description": "This is a plugin for Obsidian (https://obsidian.md)",
"main": "main.js",
"repository": {
"type": "git",
"url": "https://biboer.cn/gitea/gavin/note2any.git"
},
"homepage": "https://biboer.cn/gitea/gavin/note2any",
"bugs": {
"url": "https://biboer.cn/gitea/gavin/note2any/issues"
},
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"build": "npm run build:bundle --",
"build:obf": "OBFUSCATE=1 npm run build:bundle --",
"build:bundle": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"download": "node tools/download.mjs",
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
@@ -18,6 +28,7 @@
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"esbuild": "0.17.3",
"javascript-obfuscator": "^4.1.1",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"

View File

@@ -1,5 +1,75 @@
# 版本信息(发布版本时填写,供脚本使用)
# 版本信息
‼️ 发布版本时填写,供脚本~/pubsh/release.sh使用
## v1.3.12
### 🚀 核心架构重构与优化
#### 新增核心模块系统
- **ErrorHandler**: 统一错误处理机制,提供集中化的错误管理和用户友好的提示
- **ProgressIndicator**: 全新的进度反馈系统,为长时间操作提供实时状态更新
- **ConfigManager**: 中心化配置管理,支持运行时配置验证和热更新
- **PublisherInterface**: 标准化平台发布接口,支持多平台扩展
- **PublisherManager**: 统一的发布平台管理器
- **ContentProcessor**: 模块化内容处理流水线
#### 专业化处理模块
- **GalleryProcessor**: 专门处理图库短代码,支持目录式和块级图库
- **ImageProcessor**: 统一图像处理接口支持WebP转换、批量处理、微信上传
- **HtmlProcessor**: HTML内容生成和格式化支持响应式设计和移动端优化
#### 架构改进
```
┌─────────────────────────────────────────────┐
│ Core System Layer (新增) │
│ - ErrorHandler (错误处理) │
│ - ProgressIndicator (进度反馈) │
│ - ConfigManager (配置管理) │
│ - PublisherManager (发布管理) │
└──────────────┬──────────────────────────────┘
│ 支撑
┌─────────────────────────────────────────────┐
│ Business Logic Layer │
│ preview-manager.ts (中央调度器) │
│ - 集成核心模块 │
│ - 增强错误处理 │
│ - 进度反馈集成 │
└──────────────┬──────────────────────────────┘
│ 管理
┌───────┼───────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│Platform │ │Wechat │ │Xiaohong- │
│Chooser │ │Preview │ │shu │
│(UI选择器)│ │(微信实现)│ │Preview │
└──────────┘ └──────────┘ │(小红书) │
└──────────┘
```
#### 性能优化
- 模块化加载,减少初始化时间
- 异步处理优化,提升响应性能
- 智能缓存机制,减少重复计算
#### 可维护性提升
- 明确的模块职责分离
- 统一的接口和约定
- 完善的类型定义
- 向后兼容的API设计
### 🔧 技术改进
- 重构项目名称从"note-to-mp"到"note2any"
- 更新仓库地址到 https://biboer.cn/gitea/gavin/note2any.git
- 批量更新66个CSS主题文件的类名
- 优化构建和部署流程
### 📚 文档更新
- 新增系统优化报告 (OPTIMIZATION_REPORT_v1.3.12.md)
- 更新README文档反映新的项目名称
- 完善架构文档
## v1.3.4
### 重构
#### 新的架构图
@@ -59,4 +129,65 @@
现在分页依据真实渲染高度,预览窗口内不会再丢失底部内容。建议在小红书预览里多翻几页、调整字号后重新分页验证结果。
## v1.3.10
重构xhs和wechat布局统一使用grid便于维护。
## v1.3.11
修改wechat封面旋转问题。对全局配置进行了重构分页显示更加清晰。
封面图片先转位png解决旋转问题。
## v1.3.12
本次更新主要为项目重命名,核心功能保持不变
### 重大更新
#### 项目名称变更 & 仓库迁移
- **新仓库地址**https://biboer.cn/gitea/gavin/note2any.git
- **问题反馈**https://biboer.cn/gitea/gavin/note2any/issues
- **发布页面**https://biboer.cn/gitea/gavin/note2any/releases
#### 样式系统更新
- CSS类名 & 主题资源统一
## v1.4.0
架构升级与代码质量提升
### 🏗️ 架构升级与代码质量提升
#### 核心架构现代化
- **模块化重构**: 建立了完整的核心模块系统包含错误处理、进度反馈、配置管理等9个专业模块
- **类型安全**: 全面的TypeScript类型定义零编译错误提升代码可靠性
- **接口标准化**: 统一的平台发布接口,支持更好的扩展性和维护性
#### 新增核心功能模块
- **统一错误处理**: ErrorHandler模块提供集中化的错误管理和用户友好提示
- **实时进度反馈**: ProgressIndicator为长时间操作提供状态更新
- **智能配置管理**: ConfigManager支持运行时验证和热更新
- **可扩展发布系统**: 标准化的平台接口,便于新平台接入
#### 专业化处理引擎
- **图库处理器**: 专门优化图库短代码处理,支持多种格式和智能选择
- **图像处理引擎**: 统一的图像处理接口,支持格式转换、批量处理、云端上传
- **HTML生成器**: 增强的HTML处理支持响应式设计和移动端优化
#### 开发体验改进
- **代码组织**: 清晰的模块职责分离1400+行新增代码
- **维护性**: 统一的接口约定和完善的文档
- **向后兼容**: 保持现有API稳定平滑升级路径
#### 性能与稳定性
- **启动优化**: 模块化加载减少初始化时间
- **响应性能**: 异步处理优化,提升用户体验
- **错误恢复**: 智能的错误处理和恢复机制
### 🔧 技术债务清理
- 重构大型文件,提升代码可读性
- 统一错误处理模式
- 优化资源加载策略
- 完善类型定义覆盖
### 📖 文档与工程化
- 新增详细的架构文档和优化报告
- 完善开发和部署流程
- 更新项目说明和使用指南

View File

@@ -1,195 +0,0 @@
#!/bin/bash
# create_milestone.sh - 自动创建项目里程碑版本
# 使用方法: ./create_milestone.sh v1.3.0 "里程碑版本描述"
set -e # 遇到错误立即退出
VERSION=$1
DESCRIPTION=${2:-"里程碑版本"}
if [ -z "$VERSION" ]; then
echo "❌ 错误: 请提供版本号"
echo "使用方法: $0 <version> [description]"
echo "示例: $0 v1.3.0 '批量发布系统完成'"
exit 1
fi
# 版本号格式验证
if [[ ! $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "❌ 版本号格式错误,应为 vX.X.X 格式 (如: v1.3.0)"
exit 1
fi
# 检查版本是否已存在
if git tag | grep -q "^$VERSION$"; then
echo "❌ 版本 $VERSION 已存在"
exit 1
fi
echo "🚀 开始创建里程碑版本: $VERSION"
# 1. 检查工作目录状态
echo "📋 检查Git状态..."
if ! git diff-index --quiet HEAD --; then
echo "⚠️ 发现未提交的更改,正在自动提交..."
git add .
git commit -m "feat: $DESCRIPTION
版本: $VERSION (里程碑版本)"
fi
# 2. 创建Git标签
echo "🏷️ 创建Git标签..."
git tag -a "$VERSION" -m "$DESCRIPTION
此版本为稳定的里程碑版本,用于后续大规模修改前的对比和回滚基准。
创建时间: $(date '+%Y-%m-%d %H:%M:%S')
Git提交: $(git rev-parse HEAD)"
# 3. 创建发布分支
echo "🌿 创建发布分支..."
git checkout -b "release/$VERSION"
# 4. 构建项目
echo "🔨 构建项目..."
if [ -f package.json ]; then
npm run build
else
echo "⚠️ 未找到package.json跳过构建步骤"
fi
# 5. 创建归档目录
echo "📁 创建归档目录..."
mkdir -p "archives/$VERSION"
# 6. 复制关键文件
echo "📋 复制构建文件..."
for file in main.js manifest.json styles.css package.json; do
if [ -f "$file" ]; then
cp "$file" "archives/$VERSION/"
echo " ✅ 复制 $file"
else
echo " ⚠️ $file 不存在,跳过"
fi
done
echo "📄 复制文档文件..."
for file in README.md CHANGELOG.md detaildesign.md diagrams.md; do
if [ -f "$file" ]; then
cp "$file" "archives/$VERSION/"
echo " ✅ 复制 $file"
else
echo " ⚠️ $file 不存在,跳过"
fi
done
# 7. 创建源码快照
echo "📦 创建源码快照..."
PROJECT_NAME=$(basename "$(pwd)")
cd .. && tar -czf "$PROJECT_NAME/archives/$VERSION/source-snapshot-$VERSION.tar.gz" \
--exclude='node_modules' \
--exclude='.git' \
--exclude='archives' \
"$PROJECT_NAME/"
cd "$PROJECT_NAME"
# 8. 创建版本信息文档
echo "📋 创建版本信息文档..."
cat > "archives/$VERSION/VERSION_INFO.md" << EOF
# 里程碑版本 $VERSION
## 版本信息
- **版本号**: $VERSION
- **发布日期**: $(date +%Y年%m月%d日)
- **Git Tag**: $VERSION
- **Git Branch**: release/$VERSION
- **Git Commit**: $(git rev-parse HEAD)
- **描述**: $DESCRIPTION
## 主要内容
$(if [ -f "archives/$VERSION/main.js" ]; then echo "- 构建文件: main.js ($(du -h "archives/$VERSION/main.js" | cut -f1))"; fi)
$(if [ -f "archives/$VERSION/manifest.json" ]; then echo "- 插件清单: manifest.json"; fi)
$(if [ -f "archives/$VERSION/styles.css" ]; then echo "- 样式文件: styles.css"; fi)
$(if [ -f "archives/$VERSION/README.md" ]; then echo "- 项目文档: README.md"; fi)
$(if [ -f "archives/$VERSION/CHANGELOG.md" ]; then echo "- 变更日志: CHANGELOG.md"; fi)
$(if [ -f "archives/$VERSION/detaildesign.md" ]; then echo "- 设计文档: detaildesign.md"; fi)
$(if [ -f "archives/$VERSION/diagrams.md" ]; then echo "- 架构图表: diagrams.md"; fi)
- 源码快照: source-snapshot-$VERSION.tar.gz ($(du -h "archives/$VERSION/source-snapshot-$VERSION.tar.gz" | cut -f1))
## 回滚说明
如需回滚到此版本:
### 方法1: 使用Git Tag回滚
\`\`\`bash
git checkout $VERSION
git checkout -b rollback-to-$VERSION
\`\`\`
### 方法2: 使用发布分支
\`\`\`bash
git checkout release/$VERSION
\`\`\`
### 方法3: 使用源代码快照
\`\`\`bash
tar -xzf archives/$VERSION/source-snapshot-$VERSION.tar.gz
\`\`\`
### 方法4: 使用构建文件
\`\`\`bash
$(if [ -f "archives/$VERSION/main.js" ]; then echo "cp archives/$VERSION/main.js ./"; fi)
$(if [ -f "archives/$VERSION/manifest.json" ]; then echo "cp archives/$VERSION/manifest.json ./"; fi)
$(if [ -f "archives/$VERSION/styles.css" ]; then echo "cp archives/$VERSION/styles.css ./"; fi)
\`\`\`
## 版本对比
此版本可作为后续重大修改的对比基准,主要用于:
- 功能回归测试
- 性能对比分析
- 代码架构变更评估
- 稳定性基准对比
---
*此版本为稳定的里程碑版本,建议在进行大规模代码修改前保存此状态。*
*创建脚本: scripts/create_milestone.sh*
EOF
# 9. 切换回主分支
echo "🔄 切换回主分支..."
git checkout main
# 10. 推送到远程
echo "☁️ 推送到远程仓库..."
if git remote | grep -q origin; then
echo " 推送主分支和标签..."
git push origin main --tags
echo " 推送发布分支..."
git push origin "release/$VERSION"
echo "✅ 已推送到远程仓库"
else
echo "⚠️ 无远程仓库配置,跳过推送"
fi
# 11. 验证创建结果
echo ""
echo "🔍 验证里程碑创建结果..."
echo "📁 归档目录内容:"
ls -la "archives/$VERSION/" | while read line; do echo " $line"; done
echo ""
echo "🎯 里程碑版本 $VERSION 创建完成!"
echo ""
echo "📋 创建内容:"
echo " - Git标签: $VERSION"
echo " - 发布分支: release/$VERSION"
echo " - 归档目录: archives/$VERSION/"
echo " - 源码快照: source-snapshot-$VERSION.tar.gz"
echo " - 版本文档: VERSION_INFO.md"
echo ""
echo "🔄 快速回滚命令:"
echo " git checkout $VERSION # 使用标签"
echo " git checkout release/$VERSION # 使用分支"
echo " tar -xzf archives/$VERSION/source-snapshot-$VERSION.tar.gz # 使用快照"
echo ""
echo "📖 详细信息请查看: archives/$VERSION/VERSION_INFO.md"

View File

@@ -9,7 +9,7 @@ import { UploadImageToWx } from './imagelib';
import { NMPSettings } from './settings';
import AssetsManager from './assets';
import InlineCSS from './inline-css';
import { wxGetToken, wxAddDraft, wxBatchGetMaterial, DraftArticle, DraftImageMediaId, DraftImages, wxAddDraftImages } from './weixin-api';
import { wxGetToken, wxAddDraft, wxBatchGetMaterial, DraftArticle, DraftImageMediaId, DraftImages, wxAddDraftImages } from './wechat/weixin-api';
import { MDRendererCallback } from './markdown/extension';
import { MarkedParser } from './markdown/parser';
import { LocalImageManager, LocalFile } from './markdown/local-file';
@@ -152,14 +152,14 @@ export class ArticleRender implements MDRendererCallback {
isOldTheme() {
const theme = this.assetsManager.getTheme(this.currentTheme);
if (theme) {
return theme.css.indexOf('.note-to-mp') < 0;
return theme.css.indexOf('.note2any') < 0;
}
return false;
}
setArticle(article: string) {
this.articleDiv.empty();
let className = 'note-to-mp';
let className = 'note2any';
// 兼容旧版本样式
if (this.isOldTheme()) {
className = this.currentTheme;
@@ -200,7 +200,7 @@ export class ArticleRender implements MDRendererCallback {
errorContent(error: any) {
return '<h1>渲染失败!</h1><br/>'
+ '如需帮助请前往&nbsp;&nbsp;<a href="https://github.com/sunbooshi/note-to-mp/issues">https://github.com/sunbooshi/note-to-mp/issues</a>&nbsp;&nbsp;反馈<br/><br/>'
+ '如需帮助请前往&nbsp;&nbsp;<a href="https://biboer.cn/gitea/gavin/note2any/issues">https://biboer.cn/gitea/gavin/note2any/issues</a>&nbsp;&nbsp;反馈<br/><br/>'
+ '如果方便请提供引发错误的完整Markdown内容。<br/><br/>'
+ '<br/>Obsidian版本' + apiVersion
+ '<br/>错误信息:<br/>'
@@ -289,7 +289,7 @@ export class ArticleRender implements MDRendererCallback {
const theme = this.assetsManager.getTheme(this.currentTheme);
const highlight = this.assetsManager.getHighlight(this.currentHighlight);
const customCSS = this.settings.customCSSNote.length > 0 || this.settings.useCustomCss ? this.assetsManager.customCSS : '';
const baseCSS = this.settings.baseCSS ? `.note-to-mp {${this.settings.baseCSS}}` : '';
const baseCSS = this.settings.baseCSS ? `.note2any {${this.settings.baseCSS}}` : '';
return `${InlineCSS}\n\n${highlight!.css}\n\n${theme!.css}\n\n${baseCSS}\n\n${customCSS}`;
} catch (error) {
console.error(error);
@@ -341,11 +341,11 @@ export class ArticleRender implements MDRendererCallback {
try {
const globalAny = window as any;
const now = Date.now();
if (!globalAny.__note2mp_lastPathLog ||
globalAny.__note2mp_lastPathLog.path !== file.path ||
now - globalAny.__note2mp_lastPathLog.time > 3000) {
console.log('[note2mp] active file path:', file.path);
globalAny.__note2mp_lastPathLog = { path: file.path, time: now };
if (!globalAny.__note2any_lastPathLog ||
globalAny.__note2any_lastPathLog.path !== file.path ||
now - globalAny.__note2any_lastPathLog.time > 3000) {
console.log('[note2any] active file path:', file.path);
globalAny.__note2any_lastPathLog = { path: file.path, time: now };
}
} catch {}
const metadata = this.app.metadataCache.getFileCache(file);
@@ -381,7 +381,9 @@ export class ArticleRender implements MDRendererCallback {
res.cover = undefined; // 忽略 frontmatter
}
res.thumb_media_id = this.getFrontmatterValue(frontmatter, keys.thumb_media_id);
res.need_open_comment = frontmatter[keys.need_open_comment] ? 1 : undefined;
if (frontmatter[keys.need_open_comment] !== undefined) {
res.need_open_comment = frontmatter[keys.need_open_comment] ? 1 : 0;
}
res.only_fans_can_comment = frontmatter[keys.only_fans_can_comment] ? 1 : undefined;
res.appid = this.getFrontmatterValue(frontmatter, keys.appid);
if (res.appid && !res.appid.startsWith('wx')) {
@@ -473,11 +475,14 @@ export class ArticleRender implements MDRendererCallback {
if (base) res.cover = `![[${base}]]`;
}
if (res.cover) {
try { console.log('[note2mp] use default cover:', def, '->', res.cover); } catch {}
try { console.log('[note2any] use default cover:', def, '->', res.cover); } catch {}
}
}
}
}
if (res.need_open_comment === undefined) {
res.need_open_comment = this.settings.needOpenComment ? 1 : 0;
}
return res;
}
@@ -717,7 +722,7 @@ export class ArticleRender implements MDRendererCallback {
article_type: 'newspic',
title: metadata.title || this.title,
content: content,
need_open_commnet: metadata.need_open_comment || 0,
need_open_commnet: metadata.need_open_comment ?? 0,
only_fans_can_comment: metadata.only_fans_can_comment || 0,
image_info: {
image_list: imageList,
@@ -855,4 +860,4 @@ export class ArticleRender implements MDRendererCallback {
const key = category + ':' + id;
this.cachedElements.set(key, data);
}
}
}

View File

@@ -297,7 +297,7 @@ export default class AssetsManager {
getThemeURL() {
const version = this.manifest.version;
return `https://github.com/sunbooshi/note-to-mp/releases/download/${version}/assets.zip`;
return `https://biboer.cn/gitea/gavin/note2any/releases/download/${version}/assets.zip`;
}
async getStyle() {

View File

@@ -8,7 +8,7 @@
import { App, Modal, Setting, TFile, Notice, ButtonComponent } from 'obsidian';
import { BatchArticleFilter, BatchFilterConfig } from './batch-filter';
import NoteToMpPlugin from './main';
import Note2AnyPlugin from './main';
// 小红书功能模块
import { XiaohongshuContentAdapter } from './xiaohongshu/adapter';
import { XiaohongshuAPIManager } from './xiaohongshu/api';
@@ -34,7 +34,7 @@ import { XiaohongshuAPIManager } from './xiaohongshu/api';
*/
export class BatchPublishModal extends Modal {
plugin: NoteToMpPlugin;
plugin: Note2AnyPlugin;
filter: BatchArticleFilter;
filteredFiles: TFile[] = [];
selectedFiles: Set<TFile> = new Set();
@@ -69,7 +69,7 @@ export class BatchPublishModal extends Modal {
orderDirection: 'asc'
};
constructor(app: App, plugin: NoteToMpPlugin) {
constructor(app: App, plugin: Note2AnyPlugin) {
super(app);
this.plugin = plugin;
this.filter = new BatchArticleFilter(app);

148
src/core/config-manager.ts Normal file
View File

@@ -0,0 +1,148 @@
/**
* 文件config-manager.ts
* 作用:集中的配置管理和验证
*/
import { ErrorHandler, ValidationError } from './error-handler';
import { NMPSettings } from '../settings';
export interface PlatformConfig {
name: string;
enabled: boolean;
validate(): boolean;
}
export interface WechatConfig extends PlatformConfig {
wxInfo: Array<{name: string, appid: string, secret: string}>;
authKey: string;
}
export interface XhsConfig extends PlatformConfig {
// 小红书相关配置待扩展
sliceImageSavePath: string;
sliceImageWidth: number;
sliceImageAspectRatio: string;
xhsPreviewWidth: number;
}
export interface GlobalConfig {
defaultTheme: string;
defaultHighlight: string;
baseCSS: string;
customCSSNote: string;
showStyleUI: boolean;
linkStyle: string;
embedStyle: string;
lineNumber: boolean;
math: string;
}
export class ConfigManager {
private static instance: ConfigManager;
private settings: NMPSettings;
private constructor(settings: NMPSettings) {
this.settings = settings;
}
static getInstance(settings?: NMPSettings): ConfigManager {
if (!this.instance && settings) {
this.instance = new ConfigManager(settings);
}
return this.instance;
}
static initialize(settings: NMPSettings): void {
this.instance = new ConfigManager(settings);
}
getWechatConfig(): WechatConfig {
return {
name: 'WeChat',
enabled: this.settings.wxInfo.length > 0,
wxInfo: this.settings.wxInfo,
authKey: this.settings.authKey,
validate: () => this.validateWechatConfig()
};
}
getXhsConfig(): XhsConfig {
return {
name: 'XiaoHongShu',
enabled: true, // 暂时默认启用
sliceImageSavePath: this.settings.sliceImageSavePath,
sliceImageWidth: this.settings.sliceImageWidth,
sliceImageAspectRatio: this.settings.sliceImageAspectRatio,
xhsPreviewWidth: this.settings.xhsPreviewWidth,
validate: () => this.validateXhsConfig()
};
}
getGlobalConfig(): GlobalConfig {
return {
defaultTheme: this.settings.defaultStyle,
defaultHighlight: this.settings.defaultHighlight,
baseCSS: this.settings.baseCSS,
customCSSNote: this.settings.customCSSNote,
showStyleUI: this.settings.showStyleUI,
linkStyle: this.settings.linkStyle,
embedStyle: this.settings.embedStyle,
lineNumber: this.settings.lineNumber,
math: this.settings.math
};
}
private validateWechatConfig(): boolean {
try {
ErrorHandler.validateRequired(this.settings.authKey, 'WeChat 授权密钥');
if (this.settings.wxInfo.length === 0) {
throw new ValidationError('WeChat 配置信息不能为空');
}
return true;
} catch (error) {
console.warn('WeChat配置验证失败:', error);
return false;
}
}
private validateXhsConfig(): boolean {
try {
ErrorHandler.validateRequired(this.settings.sliceImageSavePath, '小红书切图保存路径');
if (this.settings.sliceImageWidth <= 0) {
throw new ValidationError('切图宽度必须大于0');
}
return true;
} catch (error) {
console.warn('小红书配置验证失败:', error);
return false;
}
}
validatePlatformConfig(platform: 'wechat' | 'xhs'): boolean {
switch (platform) {
case 'wechat':
return this.validateWechatConfig();
case 'xhs':
return this.validateXhsConfig();
default:
return false;
}
}
isTokenValid(platform: 'wechat'): boolean {
if (platform === 'wechat') {
return this.settings.isAuthKeyVaild();
}
return false;
}
updateWechatToken(accessToken: string, expiresIn: number): void {
// 当前设置结构中使用 authKey 系统,这里可以扩展
console.log('WeChat token updated (using authKey system)');
}
clearWechatToken(): void {
// 当前设置结构中使用 authKey 系统,这里可以扩展
console.log('WeChat token cleared (using authKey system)');
}
}

View File

@@ -0,0 +1,209 @@
/**
* 文件content-processor.ts
* 作用内容处理器负责处理markdown内容的各种转换
*/
import { TFile, App } from 'obsidian';
import { ErrorHandler } from './error-handler';
export interface ProcessorOptions {
enableImageToBase64?: boolean;
enableLinkProcessing?: boolean;
enableCodeHighlight?: boolean;
enableMathProcessing?: boolean;
platform?: string;
}
export class ContentProcessor {
private app: App;
constructor(app: App) {
this.app = app;
}
/**
* 处理图片链接转换为base64或平台URL
*/
async processImages(
content: string,
file: TFile,
options: ProcessorOptions = {}
): Promise<string> {
return await ErrorHandler.withErrorHandling(async () => {
const { enableImageToBase64 = true } = options;
if (!enableImageToBase64) {
return content;
}
// WikiLink 图片处理: ![[image.png]]
content = await this.processWikiLinkImages(content, file);
// Markdown 图片处理: ![alt](image.png)
content = await this.processMarkdownImages(content, file);
return content;
}, 'ContentProcessor.processImages', content) || content;
}
/**
* 处理链接
*/
processLinks(content: string, linkStyle: 'inline' | 'footnote' = 'inline'): string {
return ErrorHandler.withErrorHandlingSync(() => {
if (linkStyle === 'footnote') {
return this.convertLinksToFootnotes(content);
}
return this.processInlineLinks(content);
}, 'ContentProcessor.processLinks', content) || content;
}
/**
* 处理代码块高亮
*/
processCodeBlocks(content: string, highlightTheme: string = 'default'): string {
return ErrorHandler.withErrorHandlingSync(() => {
// 为代码块添加语法高亮类
return content.replace(
/```(\w+)?\n([\s\S]*?)```/g,
(match, lang, code) => {
const language = lang || 'text';
return `<div class="code-section">
<pre><code class="language-${language}">${this.escapeHtml(code.trim())}</code></pre>
</div>`;
}
);
}, 'ContentProcessor.processCodeBlocks', content) || content;
}
/**
* 处理数学公式
*/
processMath(content: string, mathEngine: 'latex' | 'asciimath' = 'latex'): string {
return ErrorHandler.withErrorHandlingSync(() => {
// 行内公式: $...$
content = content.replace(/\$([^$]+)\$/g, (match, formula) => {
return `<span class="math-inline" data-engine="${mathEngine}">${formula}</span>`;
});
// 块级公式: $$...$$
content = content.replace(/\$\$([^$]+)\$\$/g, (match, formula) => {
return `<div class="math-block" data-engine="${mathEngine}">${formula}</div>`;
});
return content;
}, 'ContentProcessor.processMath', content) || content;
}
/**
* 处理Gallery短代码
*/
async processGalleryShortcode(content: string, galleryPath: string, numPics: number = 2): Promise<string> {
return await ErrorHandler.withErrorHandling(async () => {
const galleryRegex = /{{<gallery\s+dir="([^"]+)"(?:\s+figcaption="([^"]*)")?(?:\s+mppickall=(?:"(1|0)"|'(1|0)'|(1|0)))?\s*\/?>}}\s*{{<load-photoswipe>}}/g;
return content.replace(galleryRegex, (match, dir, figcaption, q1, q2, unquoted) => {
const pickAll = q1 === '1' || q2 === '1' || unquoted === '1';
const maxPics = pickAll ? 999 : numPics;
// 这里应该调用实际的图片列表获取逻辑
// 为了简化,返回占位符
return `<!-- Gallery: ${dir}, max: ${maxPics}, caption: ${figcaption || ''} -->`;
});
}, 'ContentProcessor.processGalleryShortcode', content) || content;
}
/**
* 清理HTML标签
*/
sanitizeHtml(content: string, allowedTags: string[] = []): string {
return ErrorHandler.withErrorHandlingSync(() => {
const allowedTagsSet = new Set(allowedTags);
return content.replace(/<[^>]*>/g, (tag) => {
const tagName = tag.match(/<\/?(\w+)/)?.[1]?.toLowerCase();
if (tagName && allowedTagsSet.has(tagName)) {
return tag;
}
return '';
});
}, 'ContentProcessor.sanitizeHtml', content) || content;
}
/**
* 处理自定义语法扩展
*/
processCustomSyntax(content: string): string {
return ErrorHandler.withErrorHandlingSync(() => {
// 斜体标注: [fig 一段说明 /]
content = content.replace(/\[fig\s+([^/]+)\s+\/\]/g,
'<span style="font-style:italic;color:#666;font-size:0.9em;">$1</span>');
// 彩色提示块
content = content.replace(/^\|\|([rgby]?)\s+(.+)$/gm, (match, color, text) => {
const colorMap: Record<string, string> = {
'r': 'background:#8B4513;color:white',
'g': 'background:#9ACD32;color:black',
'b': 'background:#D3D3D3;color:black',
'y': 'background:#FFFF99;color:black',
'': 'background:#F5F5F5;color:black'
};
const style = colorMap[color] || colorMap[''];
return `<div style="padding:8px;margin:4px 0;border-radius:4px;${style}">${text}</div>`;
});
return content;
}, 'ContentProcessor.processCustomSyntax', content) || content;
}
// 私有辅助方法
private async processWikiLinkImages(content: string, file: TFile): Promise<string> {
const wikiImageRegex = /!\[\[([^\]]+)\]\]/g;
return content.replace(wikiImageRegex, (match, imagePath) => {
// 这里应该实现实际的图片处理逻辑
return `<img src="data:image/png;base64,placeholder" alt="${imagePath}">`;
});
}
private async processMarkdownImages(content: string, file: TFile): Promise<string> {
const markdownImageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
return content.replace(markdownImageRegex, (match, alt, src) => {
// 这里应该实现实际的图片处理逻辑
return `<img src="data:image/png;base64,placeholder" alt="${alt}">`;
});
}
private convertLinksToFootnotes(content: string): string {
const links: string[] = [];
// 提取所有链接
content = content.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
links.push(url);
return `${text}[${links.length}]`;
});
// 添加脚注
if (links.length > 0) {
content += '\n\n---\n\n';
links.forEach((url, index) => {
content += `[${index + 1}]: ${url}\n`;
});
}
return content;
}
private processInlineLinks(content: string): string {
return content.replace(/\[([^\]]+)\]\(([^)]+)\)/g,
'<a href="$2" style="color:#1e6bb8;text-decoration:none;">$1</a>');
}
private escapeHtml(text: string): string {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}

96
src/core/error-handler.ts Normal file
View File

@@ -0,0 +1,96 @@
/**
* 文件error-handler.ts
* 作用:统一的错误处理和用户反馈系统
*/
import { Notice } from 'obsidian';
export class NetworkError extends Error {
constructor(message: string) {
super(message);
this.name = 'NetworkError';
}
}
export class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = 'ValidationError';
}
}
export class PlatformError extends Error {
constructor(message: string, public platform: string) {
super(message);
this.name = 'PlatformError';
}
}
export class ErrorHandler {
private static readonly ERROR_MESSAGES = {
NETWORK_ERROR: '网络连接异常,请检查网络设置',
VALIDATION_ERROR: '配置验证失败',
PLATFORM_ERROR: '发布平台异常',
UNKNOWN_ERROR: '操作失败,请查看控制台了解详情'
};
static handle(error: Error, context: string): void {
console.error(`[Note2Any] ${context}:`, error);
let userMessage: string;
let duration = 5000;
if (error instanceof NetworkError) {
userMessage = this.ERROR_MESSAGES.NETWORK_ERROR;
} else if (error instanceof ValidationError) {
userMessage = `${this.ERROR_MESSAGES.VALIDATION_ERROR}: ${error.message}`;
} else if (error instanceof PlatformError) {
userMessage = `${error.platform} ${this.ERROR_MESSAGES.PLATFORM_ERROR}: ${error.message}`;
} else {
userMessage = this.ERROR_MESSAGES.UNKNOWN_ERROR;
duration = 8000;
}
new Notice(userMessage, duration);
}
static async withErrorHandling<T>(
operation: () => Promise<T>,
context: string,
fallback?: T
): Promise<T | undefined> {
try {
return await operation();
} catch (error) {
this.handle(error as Error, context);
return fallback;
}
}
static withErrorHandlingSync<T>(
operation: () => T,
context: string,
fallback?: T
): T | undefined {
try {
return operation();
} catch (error) {
this.handle(error as Error, context);
return fallback;
}
}
static validateRequired(value: any, fieldName: string): void {
if (!value || (typeof value === 'string' && value.trim() === '')) {
throw new ValidationError(`${fieldName} 是必填项`);
}
}
static validateUrl(url: string, fieldName: string): void {
try {
new URL(url);
} catch {
throw new ValidationError(`${fieldName} 必须是有效的URL`);
}
}
}

View File

@@ -0,0 +1,150 @@
/**
* 文件gallery-processor.ts
* 作用:处理文章中的图库短代码
*
* 职责:
* 1. 解析和转换 gallery 短代码
* 2. 处理本地图片目录扫描
* 3. 生成 wikilink 格式的图片引用
*/
import { stat, readdir } from 'fs/promises';
import * as path from 'path';
import { NMPSettings } from '../settings';
// gallery 配置迁移到 NMPSettingsgalleryPrePath, galleryNumPic
// 匹配示例:{{<gallery dir="/img/guanzhan/1" figcaption="毕业展" mppickall=1/>}}{{<load-photoswipe>}}
// 支持可选 figcaption 以及 mppickall=1/0无引号数字或布尔若 mppickall=1 则选取目录内全部图片
const GALLERY_SHORTCODE_REGEX = /{{<gallery\s+dir="([^"]+)"(?:\s+figcaption="([^"]*)")?(?:\s+mppickall=(?:"(1|0)"|'(1|0)'|(1|0)))?\s*\/?>}}\s*{{<load-photoswipe>}}/g;
// 块级 gallery
// {{<gallery>}}\n{{<figure src="/img/a.png" caption=".." >}}\n...\n{{</gallery>}}
// 需要提取所有 figure 的 src basename 生成多行 wikilink
const GALLERY_BLOCK_REGEX = /{{<gallery>}}([\s\S]*?){{<\/gallery>}}/g;
// figure 支持 src 或 link 属性,两者取其一
const FIGURE_IN_GALLERY_REGEX = /{{<figure\s+(?:src|link)="([^"]+)"[^>]*>}}/g;
/**
* 列出本地图片目录中的图片文件
*/
async function listLocalImages(dirAbs: string): Promise<string[]> {
try {
const stats = await stat(dirAbs);
if (!stats.isDirectory()) return [];
} catch {
return [];
}
try {
const files = await readdir(dirAbs);
return files.filter(f => /(png|jpe?g|gif|bmp|webp|svg)$/i.test(f)).sort();
} catch {
return [];
}
}
/**
* 从图片列表中选择指定数量的图片
*/
function pickImages(all: string[], limit: number): string[] {
if (all.length <= limit) return all;
// 均匀采样
const step = all.length / limit;
const picked: string[] = [];
for (let i = 0; i < limit; i++) {
const index = Math.floor(i * step);
picked.push(all[index]);
}
return picked;
}
/**
* 图库处理器类
*/
export class GalleryProcessor {
private settings: NMPSettings;
constructor(settings: NMPSettings) {
this.settings = settings;
}
/**
* 处理文章中的图库短代码
*/
async processGalleryShortcodes(content: string): Promise<string> {
// 处理目录式 gallery
content = await this.processDirectoryGalleries(content);
// 处理块级 gallery
content = await this.processBlockGalleries(content);
return content;
}
/**
* 处理目录式图库短代码
*/
private async processDirectoryGalleries(content: string): Promise<string> {
const matches = Array.from(content.matchAll(GALLERY_SHORTCODE_REGEX));
for (const match of matches) {
const [fullMatch, dir, figcaption = '', pickall1, pickall2, pickall3] = match;
const pickall = pickall1 || pickall2 || pickall3;
const shouldPickAll = pickall === '1';
try {
const galleryPrePath = this.settings.galleryPrePath;
const dirAbs = path.join(galleryPrePath, dir);
const allImages = await listLocalImages(dirAbs);
if (allImages.length === 0) {
console.warn(`[GalleryProcessor] 目录 ${dirAbs} 中没有找到图片`);
continue;
}
const selectedImages = shouldPickAll
? allImages
: pickImages(allImages, this.settings.galleryNumPic);
// 生成 wikilink 格式的图片引用
const wikilinks = selectedImages.map(img => {
const imgPath = path.join(dir, img).replace(/\\/g, '/');
return `![[${imgPath}]]`;
});
let replacement = wikilinks.join('\n');
if (figcaption) {
replacement = `> ${figcaption}\n\n${replacement}`;
}
content = content.replace(fullMatch, replacement);
} catch (error) {
console.error(`[GalleryProcessor] 处理图库失败: ${dir}`, error);
}
}
return content;
}
/**
* 处理块级图库短代码
*/
private processBlockGalleries(content: string): Promise<string> {
return Promise.resolve(content.replace(GALLERY_BLOCK_REGEX, (match, blockContent) => {
const figureMatches = Array.from(blockContent.matchAll(FIGURE_IN_GALLERY_REGEX));
if (figureMatches.length === 0) {
return match; // 保持原样
}
const wikilinks = figureMatches.map(([, src]) => {
const basename = path.basename(src);
return `![[${basename}]]`;
});
return wikilinks.join('\n');
}));
}
}

263
src/core/html-processor.ts Normal file
View File

@@ -0,0 +1,263 @@
/**
* 文件html-processor.ts
* 作用处理HTML内容的生成和格式化
*
* 职责:
* 1. HTML内容清理和格式化
* 2. CSS样式内联处理
* 3. HTML结构生成
* 4. 代码高亮处理
*/
import { sanitizeHTMLToDom } from 'obsidian';
import { applyCSS } from '../utils';
import InlineCSS from '../inline-css';
import { NMPSettings } from '../settings';
import AssetsManager from '../assets';
import { ErrorHandler } from './error-handler';
export interface HtmlProcessOptions {
enableCodeHighlight?: boolean;
enableInlineCSS?: boolean;
theme?: string;
highlight?: string;
customCSS?: string;
}
/**
* HTML处理器类
*/
export class HtmlProcessor {
private settings: NMPSettings;
private assetsManager: AssetsManager;
constructor() {
this.settings = NMPSettings.getInstance();
this.assetsManager = AssetsManager.getInstance();
}
/**
* 生成完整的HTML文档
*/
generateFullHtml(content: string, options: HtmlProcessOptions = {}): string {
try {
const theme = options.theme || this.settings.defaultStyle;
const highlight = options.highlight || this.settings.defaultHighlight;
// 获取基础样式
const baseCSS = this.getBaseCSS(theme, highlight);
// 处理自定义CSS
let customCSS = options.customCSS || '';
if (this.settings.useCustomCss && this.settings.customCSSNote) {
customCSS += '\n' + this.settings.customCSSNote;
}
// 构建完整HTML
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Note2Any Export</title>
<style>
${baseCSS}
${customCSS}
</style>
</head>
<body>
<div class="note2any">
${content}
</div>
</body>
</html>`;
return html;
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.generateFullHtml');
throw error;
}
}
/**
* 处理HTML内容的内联CSS
*/
async processInlineCSS(html: string): Promise<string> {
// 简化版内联CSS处理使用原生方法
try {
// 这里可以实现一个简单的CSS内联功能
// 或者集成第三方库如 juice
return html;
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.processInlineCSS');
console.warn('[HtmlProcessor] 内联CSS处理失败使用原始HTML', error);
return html;
}
}
/**
* 清理和格式化HTML内容
*/
sanitizeHtml(html: string): DocumentFragment {
try {
return sanitizeHTMLToDom(html);
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.sanitizeHtml');
throw error;
}
}
/**
* 应用CSS样式到元素
*/
applyStylesToElement(html: string, css: string): string {
try {
return applyCSS(html, css);
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.applyStylesToElement');
throw error;
}
}
/**
* 获取基础CSS样式
*/
private getBaseCSS(theme: string, highlight: string): string {
try {
let css = '';
// 主题样式
const themeCSS = this.assetsManager.getTheme(theme);
if (themeCSS) {
css += themeCSS + '\n';
}
// 代码高亮样式
const highlightCSS = this.assetsManager.getHighlight(highlight);
if (highlightCSS) {
css += highlightCSS + '\n';
}
return css;
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.getBaseCSS');
return '';
}
}
/**
* 生成响应式HTML包装器
*/
wrapWithResponsive(content: string, maxWidth = '800px'): string {
return `
<div style="max-width: ${maxWidth}; margin: 0 auto; padding: 20px; box-sizing: border-box;">
${content}
</div>`;
}
/**
* 添加打印样式
*/
addPrintStyles(): string {
return `
<style media="print">
@page {
margin: 2cm;
size: A4;
}
.note2any {
max-width: none !important;
margin: 0 !important;
padding: 0 !important;
}
.no-print {
display: none !important;
}
pre {
white-space: pre-wrap !important;
word-break: break-word !important;
}
img {
max-width: 100% !important;
height: auto !important;
page-break-inside: avoid;
}
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid;
}
p, li {
orphans: 3;
widows: 3;
}
</style>`;
}
/**
* 处理代码块高亮
*/
processCodeHighlight(html: string, highlight: string): string {
try {
// 这里可以添加更复杂的代码高亮处理逻辑
// 目前主要依赖 AssetsManager 提供的高亮样式
return html;
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.processCodeHighlight');
return html;
}
}
/**
* 优化HTML结构用于移动端显示
*/
optimizeForMobile(html: string): string {
try {
// 添加移动端优化的meta标签和样式
const mobileOptimizations = `
<meta name="format-detection" content="telephone=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<style>
/* 移动端优化样式 */
@media screen and (max-width: 768px) {
.note2any {
padding: 15px 10px !important;
font-size: 16px !important;
line-height: 1.6 !important;
}
pre, code {
font-size: 14px !important;
overflow-x: auto !important;
white-space: pre-wrap !important;
}
table {
font-size: 14px !important;
display: block !important;
overflow-x: auto !important;
white-space: nowrap !important;
}
img {
max-width: 100% !important;
height: auto !important;
}
}
</style>`;
// 在head标签中插入移动端优化
return html.replace('</head>', mobileOptimizations + '</head>');
} catch (error) {
ErrorHandler.handle(error as Error, 'HtmlProcessor.optimizeForMobile');
return html;
}
}
}

225
src/core/image-processor.ts Normal file
View File

@@ -0,0 +1,225 @@
/**
* 文件image-processor.ts
* 作用:处理文章中的图片相关操作
*
* 职责:
* 1. 图片上传和转换
* 2. 图片格式处理WebP转JPG等
* 3. 图片EXIF处理
* 4. 图片截图功能
*/
import { Notice } from 'obsidian';
import { toPng } from 'html-to-image';
import { PrepareImageLib, IsImageLibReady, WebpToJPG } from '../imagelib';
import { UploadImageToWx } from '../imagelib';
import { ErrorHandler } from './error-handler';
import { ProgressIndicator } from './progress-indicator';
export interface ImageProcessOptions {
enableWebpConversion?: boolean;
enableExifProcessing?: boolean;
quality?: number;
}
/**
* 图像处理器类
*/
export class ImageProcessor {
private isInitialized = false;
/**
* 初始化图像处理库
*/
async initialize(): Promise<void> {
if (this.isInitialized) return;
const progress = new ProgressIndicator();
progress.start('初始化图像处理库');
try {
await PrepareImageLib();
// 等待图像库准备就绪
let attempts = 0;
const maxAttempts = 50;
while (!IsImageLibReady() && attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 100));
attempts++;
}
if (!IsImageLibReady()) {
throw new Error('图像处理库初始化超时');
}
this.isInitialized = true;
progress.finish('图像处理库初始化完成');
} catch (error) {
progress.error('图像处理库初始化失败');
ErrorHandler.handle(error as Error, 'ImageProcessor.initialize');
throw error;
}
}
/**
* 确保图像处理库已初始化
*/
private async ensureInitialized(): Promise<void> {
if (!this.isInitialized) {
await this.initialize();
}
}
/**
* 将WebP格式转换为JPG
*/
async convertWebpToJpg(webpData: ArrayBuffer): Promise<ArrayBuffer> {
await this.ensureInitialized();
try {
const result = await WebpToJPG(webpData);
if (!result) {
throw new Error('WebP转JPG失败');
}
// 将 Uint8Array 转换为 ArrayBuffer
const buffer = result.buffer as ArrayBuffer;
return buffer.slice(result.byteOffset, result.byteOffset + result.byteLength);
} catch (error) {
ErrorHandler.handle(error as Error, 'ImageProcessor.convertWebpToJpg');
throw error;
}
}
/**
* 上传图片到微信
*/
async uploadToWechat(imageData: ArrayBuffer, filename: string, token: string, type?: string): Promise<string> {
await this.ensureInitialized();
const progress = new ProgressIndicator();
progress.start(`上传图片: ${filename}`);
try {
// 将 ArrayBuffer 转换为 Blob
const blob = new Blob([imageData]);
const result = await UploadImageToWx(blob, filename, token, type);
if (result.errcode !== 0) {
throw new Error(`上传失败: ${result.errmsg}`);
}
progress.finish('图片上传成功');
return result.media_id;
} catch (error) {
progress.error('图片上传失败');
ErrorHandler.handle(error as Error, 'ImageProcessor.uploadToWechat');
throw error;
}
}
/**
* 将HTML元素转换为PNG图片
*/
async htmlToPng(element: HTMLElement, options?: {
width?: number;
height?: number;
backgroundColor?: string;
pixelRatio?: number;
}): Promise<Blob> {
const progress = new ProgressIndicator();
progress.start('生成图片');
try {
const defaultOptions = {
width: options?.width || element.offsetWidth,
height: options?.height || element.offsetHeight,
backgroundColor: options?.backgroundColor || '#ffffff',
pixelRatio: options?.pixelRatio || 2,
cacheBust: true,
skipFonts: false,
style: {
transform: 'scale(1)',
transformOrigin: 'top left'
}
};
const dataUrl = await toPng(element, defaultOptions);
// 将 data URL 转换为 Blob
const response = await fetch(dataUrl);
const blob = await response.blob();
progress.finish('图片生成完成');
return blob;
} catch (error) {
progress.error('图片生成失败');
ErrorHandler.handle(error as Error, 'ImageProcessor.htmlToPng');
throw error;
}
}
/**
* 处理图片数据
*/
async processImage(
imageData: ArrayBuffer,
filename: string,
options: ImageProcessOptions = {}
): Promise<ArrayBuffer> {
await this.ensureInitialized();
let processedData = imageData;
try {
// WebP转JPG处理
if (options.enableWebpConversion && filename.toLowerCase().endsWith('.webp')) {
processedData = await this.convertWebpToJpg(processedData);
}
// 这里可以添加更多图片处理逻辑
// 如压缩、EXIF处理等
return processedData;
} catch (error) {
ErrorHandler.handle(error as Error, 'ImageProcessor.processImage');
throw error;
}
}
/**
* 批量处理图片
*/
async processImages(
images: Array<{ data: ArrayBuffer; filename: string }>,
options: ImageProcessOptions = {}
): Promise<Array<{ data: ArrayBuffer; filename: string }>> {
const progress = new ProgressIndicator();
progress.start(`批量处理图片 (${images.length}张)`);
try {
const results = [];
for (let i = 0; i < images.length; i++) {
const { data, filename } = images[i];
progress.update(`处理图片 ${i + 1}/${images.length}: ${filename}`);
const processedData = await this.processImage(data, filename, options);
results.push({ data: processedData, filename });
}
progress.finish('批量图片处理完成');
return results;
} catch (error) {
progress.error('批量图片处理失败');
ErrorHandler.handle(error as Error, 'ImageProcessor.processImages');
throw error;
}
}
/**
* 获取图像处理库状态
*/
isReady(): boolean {
return this.isInitialized && IsImageLibReady();
}
}

View File

@@ -0,0 +1,106 @@
/**
* 文件progress-indicator.ts
* 作用:进度指示和用户反馈管理
*/
import { Notice } from 'obsidian';
export interface ProgressOptions {
showProgress?: boolean;
duration?: number;
autoHide?: boolean;
}
export class ProgressIndicator {
private notice: Notice | null = null;
private startTime: number = 0;
start(message: string, options: ProgressOptions = {}): void {
this.startTime = Date.now();
const { duration = 0 } = options;
this.notice = new Notice(`🔄 ${message}...`, duration);
}
update(message: string, progress?: number): void {
if (!this.notice) return;
const progressText = progress ? ` (${Math.round(progress)}%)` : '';
this.notice.setMessage(`🔄 ${message}${progressText}...`);
}
finish(message: string, success: boolean = true): void {
if (this.notice) {
this.notice.hide();
this.notice = null;
}
const duration = Date.now() - this.startTime;
const durationText = duration > 1000 ? ` (${(duration / 1000).toFixed(1)}s)` : '';
const icon = success ? '✅' : '❌';
new Notice(`${icon} ${message}${durationText}`, success ? 3000 : 5000);
}
error(message: string): void {
this.finish(message, false);
}
hide(): void {
if (this.notice) {
this.notice.hide();
this.notice = null;
}
}
}
export class BatchProgressIndicator {
private currentProgress: ProgressIndicator | null = null;
private totalItems: number = 0;
private completedItems: number = 0;
private failedItems: number = 0;
start(totalItems: number, operation: string): void {
this.totalItems = totalItems;
this.completedItems = 0;
this.failedItems = 0;
this.currentProgress = new ProgressIndicator();
this.currentProgress.start(`${operation} (0/${totalItems})`);
}
updateItem(itemName: string, success: boolean = true): void {
if (success) {
this.completedItems++;
} else {
this.failedItems++;
}
const completed = this.completedItems + this.failedItems;
const progress = (completed / this.totalItems) * 100;
if (this.currentProgress) {
this.currentProgress.update(
`处理中: ${itemName} (${completed}/${this.totalItems})`,
progress
);
}
}
finish(operation: string): void {
const successCount = this.completedItems;
const failCount = this.failedItems;
const total = this.totalItems;
let message = `${operation}完成`;
if (failCount === 0) {
message += ` - 全部成功 (${successCount}/${total})`;
} else {
message += ` - 成功: ${successCount}, 失败: ${failCount}`;
}
if (this.currentProgress) {
this.currentProgress.finish(message, failCount === 0);
}
}
}

View File

@@ -0,0 +1,87 @@
/**
* 文件publisher-interface.ts
* 作用:统一的发布平台接口定义
*/
export interface PublishResult {
success: boolean;
message: string;
url?: string;
data?: any;
error?: Error;
}
export interface PublishOptions {
title?: string;
cover?: string;
excerpt?: string;
tags?: string[];
openComment?: boolean;
onlyFansComment?: boolean;
}
export interface IPlatformPublisher {
readonly id: string;
readonly name: string;
readonly displayName: string;
/**
* 验证平台配置是否有效
*/
validateConfig(): Promise<boolean>;
/**
* 生成预览内容
*/
generatePreview(content: string, options?: PublishOptions): Promise<string>;
/**
* 发布内容到平台
*/
publish(content: string, options?: PublishOptions): Promise<PublishResult>;
/**
* 上传图片到平台
*/
uploadImage?(imageData: ArrayBuffer, filename: string): Promise<string>;
/**
* 获取平台特定的设置组件
*/
getSettingsComponent?(): HTMLElement | undefined;
}
export abstract class BasePlatformPublisher implements IPlatformPublisher {
abstract readonly id: string;
abstract readonly name: string;
abstract readonly displayName: string;
abstract validateConfig(): Promise<boolean>;
abstract generatePreview(content: string, options?: PublishOptions): Promise<string>;
abstract publish(content: string, options?: PublishOptions): Promise<PublishResult>;
async uploadImage(imageData: ArrayBuffer, filename: string): Promise<string> {
throw new Error('Image upload not implemented for this platform');
}
getSettingsComponent(): HTMLElement | undefined {
return undefined;
}
protected createSuccessResult(message: string, url?: string, data?: any): PublishResult {
return {
success: true,
message,
url,
data
};
}
protected createErrorResult(message: string, error?: Error): PublishResult {
return {
success: false,
message,
error
};
}
}

View File

@@ -0,0 +1,192 @@
/**
* 文件publisher-manager.ts
* 作用:发布平台管理器,统一管理所有发布平台
*/
import { IPlatformPublisher, PublishResult, PublishOptions } from './publisher-interface';
import { ErrorHandler, PlatformError } from './error-handler';
import { ProgressIndicator } from './progress-indicator';
export class PublisherManager {
private publishers = new Map<string, IPlatformPublisher>();
private static instance: PublisherManager;
private constructor() {}
static getInstance(): PublisherManager {
if (!this.instance) {
this.instance = new PublisherManager();
}
return this.instance;
}
/**
* 注册发布平台
*/
register(publisher: IPlatformPublisher): void {
this.publishers.set(publisher.id, publisher);
console.log(`[PublisherManager] 注册发布平台: ${publisher.displayName}`);
}
/**
* 注销发布平台
*/
unregister(publisherId: string): void {
if (this.publishers.delete(publisherId)) {
console.log(`[PublisherManager] 注销发布平台: ${publisherId}`);
}
}
/**
* 获取所有已注册的发布平台
*/
getPublishers(): IPlatformPublisher[] {
return Array.from(this.publishers.values());
}
/**
* 获取指定的发布平台
*/
getPublisher(publisherId: string): IPlatformPublisher | undefined {
return this.publishers.get(publisherId);
}
/**
* 检查平台是否可用
*/
async isPlatformAvailable(publisherId: string): Promise<boolean> {
const publisher = this.getPublisher(publisherId);
if (!publisher) {
return false;
}
try {
return await publisher.validateConfig();
} catch (error) {
console.warn(`[PublisherManager] 平台 ${publisherId} 验证失败:`, error);
return false;
}
}
/**
* 发布内容到指定平台
*/
async publish(
platformId: string,
content: string,
options?: PublishOptions
): Promise<PublishResult> {
const progress = new ProgressIndicator();
try {
progress.start(`准备发布到 ${platformId}`);
const publisher = this.getPublisher(platformId);
if (!publisher) {
throw new PlatformError(`发布平台 ${platformId} 未找到`, platformId);
}
progress.update('验证平台配置');
const isValid = await publisher.validateConfig();
if (!isValid) {
throw new PlatformError(`发布平台 ${platformId} 配置无效`, platformId);
}
progress.update('发布内容');
const result = await publisher.publish(content, options);
if (result.success) {
progress.finish(`发布成功到 ${publisher.displayName}`);
} else {
progress.error(`发布失败到 ${publisher.displayName}: ${result.message}`);
}
return result;
} catch (error) {
const errorMsg = `发布到 ${platformId} 失败`;
progress.error(errorMsg);
ErrorHandler.handle(error as Error, 'PublisherManager.publish');
return {
success: false,
message: errorMsg,
error: error as Error
};
}
}
/**
* 批量发布到多个平台
*/
async batchPublish(
platformIds: string[],
content: string,
options?: PublishOptions
): Promise<Map<string, PublishResult>> {
const results = new Map<string, PublishResult>();
console.log(`[PublisherManager] 开始批量发布到 ${platformIds.length} 个平台`);
for (const platformId of platformIds) {
try {
const result = await this.publish(platformId, content, options);
results.set(platformId, result);
// 添加延迟以避免频率限制
if (platformIds.length > 1) {
await new Promise(resolve => setTimeout(resolve, 2000));
}
} catch (error) {
results.set(platformId, {
success: false,
message: `批量发布失败: ${error}`,
error: error as Error
});
}
}
const successCount = Array.from(results.values()).filter(r => r.success).length;
const totalCount = platformIds.length;
console.log(`[PublisherManager] 批量发布完成: ${successCount}/${totalCount} 成功`);
return results;
}
/**
* 生成预览内容
*/
async generatePreview(
platformId: string,
content: string,
options?: PublishOptions
): Promise<string> {
return await ErrorHandler.withErrorHandling(async () => {
const publisher = this.getPublisher(platformId);
if (!publisher) {
throw new PlatformError(`发布平台 ${platformId} 未找到`, platformId);
}
return await publisher.generatePreview(content, options);
}, 'PublisherManager.generatePreview', '') || '';
}
/**
* 获取平台状态信息
*/
async getPlatformStatus(): Promise<Map<string, boolean>> {
const status = new Map<string, boolean>();
for (const [id, publisher] of this.publishers) {
try {
const isAvailable = await publisher.validateConfig();
status.set(id, isAvailable);
} catch {
status.set(id, false);
}
}
return status;
}
}

View File

@@ -7,7 +7,7 @@ const css = `
/* =========================================================== */
/* Obsidian的默认样式 */
/* =========================================================== */
.note-to-mp {
.note2any {
padding: 0;
user-select: text;
-webkit-user-select: text;
@@ -15,15 +15,15 @@ const css = `
font-size: 16px;
}
.note-to-mp:last-child {
.note2any:last-child {
margin-bottom: 0;
}
.note-to-mp .fancybox-img {
.note2any .fancybox-img {
border: none;
}
.note-to-mp .fancybox-img:hover {
.note2any .fancybox-img:hover {
opacity: none;
border: none;
}
@@ -33,7 +33,7 @@ const css = `
Heading
==================================
*/
.note-to-mp h1 {
.note2any h1 {
color: #222;
font-weight: 700;
font-size: 1.802em;
@@ -42,7 +42,7 @@ Heading
margin-block-end: 0;
}
.note-to-mp h2 {
.note2any h2 {
color: #222;
font-weight: 600;
font-size: 1.602em;
@@ -51,7 +51,7 @@ Heading
margin-block-end: 0;
}
.note-to-mp h3 {
.note2any h3 {
color: #222;
font-weight: 600;
font-size: 1.424em;
@@ -60,7 +60,7 @@ Heading
margin-block-end: 0;
}
.note-to-mp h4 {
.note2any h4 {
color: #222;
font-weight: 600;
font-size: 1.266em;
@@ -69,13 +69,13 @@ Heading
margin-block-end: 0;
}
.note-to-mp h5 {
.note2any h5 {
color: #222;
margin-block-start: 1em;
margin-block-end: 0;
}
.note-to-mp h6 {
.note2any h6 {
color: #222;
margin-block-start: 1em;
margin-block-end: 0;
@@ -86,7 +86,7 @@ Heading
Horizontal Rules
==================================
*/
.note-to-mp hr {
.note2any hr {
border-color: #e0e0e0;
margin-top: 3em;
margin-bottom: 3em;
@@ -97,7 +97,7 @@ Horizontal Rules
Paragraphs
==================================
*/
.note-to-mp p {
.note2any p {
line-height: 1.6em;
margin: 1em 0;
}
@@ -107,17 +107,17 @@ Paragraphs
Emphasis
==================================
*/
.note-to-mp strong {
.note2any strong {
color: #222222;
font-weight: 600;
}
.note-to-mp em {
.note2any em {
color: inherit;
font-style: italic;
}
.note-to-mp s {
.note2any s {
color: inherit;
}
@@ -126,7 +126,7 @@ Emphasis
Blockquotes
==================================
*/
.note-to-mp blockquote {
.note2any blockquote {
font-size: 1rem;
display: block;
margin: 2em 0;
@@ -136,15 +136,15 @@ Emphasis
border-left: 0.15rem solid #7852ee;
}
.note-to-mp blockquote blockquote {
.note2any blockquote blockquote {
margin: 0 0;
}
.note-to-mp blockquote p {
.note2any blockquote p {
margin: 0;
}
.note-to-mp blockquote footer strong {
.note2any blockquote footer strong {
margin-right: 0.5em;
}
@@ -153,23 +153,23 @@ Emphasis
List
==================================
*/
.note-to-mp ul {
.note2any ul {
margin: 0;
margin-top: 1.25em;
margin-bottom: 1.25em;
line-height: 1.6em;
}
.note-to-mp ul>li::marker {
.note2any ul>li::marker {
color: #ababab;
/* font-size: 1.5em; */
}
.note-to-mp li>p {
.note2any li>p {
margin: 0;
}
.note-to-mp ol {
.note2any ol {
margin: 0;
padding: 0;
margin-top: 1.25em;
@@ -178,7 +178,7 @@ List
line-height: 1.6em;
}
.note-to-mp ol>li {
.note2any ol>li {
position: relative;
padding-left: 0.1em;
margin-left: 2em;
@@ -189,7 +189,7 @@ List
Link
==================================
*/
.note-to-mp a {
.note2any a {
color: #7852ee;
text-decoration: none;
font-weight: 500;
@@ -198,7 +198,7 @@ Link
transition: border 0.3s ease-in-out;
}
.note-to-mp a:hover {
.note2any a:hover {
color: #7952eebb;
border-bottom: 1px solid #7952eebb;
}
@@ -208,7 +208,7 @@ Link
Table
==================================
*/
.note-to-mp table {
.note2any table {
width: 100%;
table-layout: auto;
text-align: left;
@@ -221,13 +221,13 @@ Table
text-indent: 0;
}
.note-to-mp table thead {
.note2any table thead {
color: #000;
font-weight: 600;
border: #e0e0e0 1px solid;
}
.note-to-mp table thead th {
.note2any table thead th {
vertical-align: bottom;
padding-right: 0.5714286em;
padding-bottom: 0.5714286em;
@@ -235,24 +235,24 @@ Table
border: #e0e0e0 1px solid;
}
.note-to-mp table thead th:first-child {
.note2any table thead th:first-child {
padding-left: 0.5em;
}
.note-to-mp table thead th:last-child {
.note2any table thead th:last-child {
padding-right: 0.5em;
}
.note-to-mp table tbody tr {
.note2any table tbody tr {
border-style: solid;
border: #e0e0e0 1px solid;
}
.note-to-mp table tbody tr:last-child {
.note2any table tbody tr:last-child {
border-bottom-width: 0;
}
.note-to-mp table tbody td {
.note2any table tbody td {
vertical-align: top;
padding-top: 0.5714286em;
padding-right: 0.5714286em;
@@ -261,11 +261,11 @@ Table
border: #e0e0e0 1px solid;
}
.note-to-mp table tbody td:first-child {
.note2any table tbody td:first-child {
padding-left: 0;
}
.note-to-mp table tbody td:last-child {
.note2any table tbody td:last-child {
padding-right: 0;
}
@@ -274,11 +274,11 @@ Table
Images
==================================
*/
.note-to-mp img {
.note2any img {
margin: 2em auto;
}
.note-to-mp .footnotes hr {
.note2any .footnotes hr {
margin-top: 4em;
margin-bottom: 0.5em;
}
@@ -288,7 +288,7 @@ Images
Code
==================================
*/
.note-to-mp .code-section {
.note2any .code-section {
display: flex;
border: rgb(240, 240, 240) 1px solid;
line-height: 26px;
@@ -298,7 +298,7 @@ Code
box-sizing: border-box;
}
.note-to-mp .code-section ul {
.note2any .code-section ul {
width: fit-content;
margin-block-start: 0;
margin-block-end: 0;
@@ -310,11 +310,11 @@ Code
backgroud: transparent !important;
}
.note-to-mp .code-section ul>li {
.note2any .code-section ul>li {
text-align: right;
}
.note-to-mp .code-section pre {
.note2any .code-section pre {
margin-block-start: 0;
margin-block-end: 0;
white-space: normal;
@@ -322,7 +322,7 @@ Code
padding: 0 0 0 0.875em;
}
.note-to-mp .code-section code {
.note2any .code-section code {
display: flex;
text-wrap: nowrap;
font-family: Consolas,Courier,monospace;

View File

@@ -4,10 +4,11 @@
*/
import { getBlobArrayBuffer } from "obsidian";
import { wxUploadImage } from "./weixin-api";
import { wxUploadImage } from "./wechat/weixin-api";
import { NMPSettings } from "./settings";
import { IsWasmReady, LoadWasm } from "./wasm/wasm";
import AssetsManager from "./assets";
import AssetsManager from "./assets";
import { convertJpegIfNeeded } from "./exif-orientation";
declare function GoWebpToJPG(data: Uint8Array): Uint8Array; // wasm 返回 Uint8Array
declare function GoWebpToPNG(data: Uint8Array): Uint8Array;
@@ -37,6 +38,18 @@ export async function UploadImageToWx(data: Blob, filename: string, token: strin
if (!IsImageLibReady()) {
await PrepareImageLib();
}
try {
// 公众号端仍然存在基于 EXIF 的旋转问题:
// 统一将待上传的 JPEG 转为 PNG 并忽略 Orientation避免出现倒置/倾斜。
const converted = await convertJpegIfNeeded(data, filename);
if (converted.changed) {
data = converted.blob;
filename = converted.filename;
}
} catch (error) {
console.warn('[UploadImageToWx] convert to PNG failed, fallback to original', error);
}
const watermark = NMPSettings.getInstance().watermark;
if (watermark != null && watermark != '') {
@@ -44,11 +57,11 @@ export async function UploadImageToWx(data: Blob, filename: string, token: strin
if (watermarkData == null) {
throw new Error('水印图片不存在: ' + watermark);
}
const watermarkImg = AddWatermark(await data.arrayBuffer(), watermarkData);
// AddWatermark 返回 Uint8ArrayBlob 的类型签名对某些 TS 配置可能对 ArrayBufferLike 有严格区分
// 此处使用其底层 ArrayBuffer 来构造 Blob避免类型不兼容错误
const bufferPart = watermarkImg.buffer as ArrayBuffer;
data = new Blob([bufferPart], { type: data.type });
const watermarkImg = AddWatermark(await data.arrayBuffer(), watermarkData);
// AddWatermark 返回 Uint8ArrayBlob 的类型签名对某些 TS 配置可能对 ArrayBufferLike 有严格区分
// 此处使用其底层 ArrayBuffer 来构造 Blob避免类型不兼容错误
const bufferPart = watermarkImg.buffer as ArrayBuffer;
data = new Blob([bufferPart], { type: data.type });
}
return await wxUploadImage(data, filename, token, type);
}
}

View File

@@ -10,7 +10,7 @@
import { Plugin, WorkspaceLeaf, App, PluginManifest, Menu, Notice, TAbstractFile, TFile, TFolder } from 'obsidian';
import { PreviewView, VIEW_TYPE_NOTE_PREVIEW } from './preview-view';
import { NMPSettings } from './settings';
import { NoteToMpSettingTab } from './setting-tab';
import { Note2AnySettingTab } from './setting-tab';
import AssetsManager from './assets';
import { setVersion, uevent } from './utils';
import { WidgetsModal } from './widgets-modal';
@@ -19,8 +19,14 @@ import { XiaohongshuLoginModal } from './xiaohongshu/login-modal';
import { XiaohongshuContentAdapter } from './xiaohongshu/adapter';
import { XiaohongshuAPIManager } from './xiaohongshu/api';
// Core modules
import { ErrorHandler } from './core/error-handler';
import { ConfigManager } from './core/config-manager';
import { PublisherManager } from './core/publisher-manager';
import { ProgressIndicator } from './core/progress-indicator';
/**
* NoteToMpPlugin
* Note2AnyPlugin
*
* 中文说明:
* 这是插件的入口类,负责:
@@ -30,56 +36,79 @@ import { XiaohongshuAPIManager } from './xiaohongshu/api';
* - 提供文件右键菜单扩展,支持对单文件或文件夹进行发布操作
*
* 设计决策(简要):
* - 将批量发布的 UI 放在 `BatchPublishModal` 中,命令 `note-to-mp-batch-publish` 会打开该模态框
* - 将批量发布的 UI 放在 `BatchPublishModal` 中,命令 `note2any-batch-publish` 会打开该模态框
* - 单篇发布/文件夹批量发布仍复用 `NotePreview` 的发布逻辑,避免重复实现上传流程
*/
export default class NoteToMpPlugin extends Plugin {
export default class Note2AnyPlugin extends Plugin {
settings: NMPSettings;
assetsManager: AssetsManager;
ribbonIconEl: HTMLElement | null = null;
// Core managers
private configManager: ConfigManager;
private publisherManager: PublisherManager;
constructor(app: App, manifest: PluginManifest) {
super(app, manifest);
AssetsManager.setup(app, manifest);
this.assetsManager = AssetsManager.getInstance();
this.publisherManager = PublisherManager.getInstance();
}
async loadResource() {
await this.loadSettings();
await this.assetsManager.loadAssets();
const progress = new ProgressIndicator();
progress.start('加载插件资源');
try {
await this.loadSettings();
// 初始化配置管理器
ConfigManager.initialize(this.settings);
this.configManager = ConfigManager.getInstance();
progress.update('加载主题资源');
await this.assetsManager.loadAssets();
progress.finish('插件资源加载完成');
} catch (error) {
progress.error('插件资源加载失败');
ErrorHandler.handle(error as Error, 'loadResource');
throw error;
}
}
async onload() {
console.log('Loading NoteToMP (plugin onload start)');
console.log('Loading Note2Any (plugin onload start)');
setVersion(this.manifest.version);
uevent('load');
console.log('[NoteToMpPlugin] workspace.layoutReady at onload =', this.app.workspace.layoutReady);
console.log('[Note2AnyPlugin] workspace.layoutReady at onload =', this.app.workspace.layoutReady);
// 先注册 view 之前,防止旧 snapshot 立即恢复创建大量视图:先临时卸载残留叶子(如果类型匹配)
try {
const legacyLeaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_NOTE_PREVIEW);
if (legacyLeaves.length > 0) {
console.log('[NoteToMpPlugin] detach legacy leaves early count=', legacyLeaves.length);
console.log('[Note2AnyPlugin] detach legacy leaves early count=', legacyLeaves.length);
this.app.workspace.detachLeavesOfType(VIEW_TYPE_NOTE_PREVIEW);
}
} catch (e) {
console.warn('[NoteToMpPlugin] early detach failed', e);
console.warn('[Note2AnyPlugin] early detach failed', e);
}
this.app.workspace.onLayoutReady(async () => {
console.log('[NoteToMpPlugin] onLayoutReady callback entered');
console.time('[NoteToMpPlugin] startup:onLayoutReady→loadResource');
console.log('[Note2AnyPlugin] onLayoutReady callback entered');
console.time('[Note2AnyPlugin] startup:onLayoutReady→loadResource');
try {
await this.loadResource(); // 确保资源完全加载完再继续,避免后续视图初始化反复等待
} catch (e) {
console.error('[NoteToMpPlugin] loadResource 失败', e);
console.error('[Note2AnyPlugin] loadResource 失败', e);
} finally {
console.timeEnd('[NoteToMpPlugin] startup:onLayoutReady→loadResource');
console.timeEnd('[Note2AnyPlugin] startup:onLayoutReady→loadResource');
}
// 清理旧视图
this.cleanupLegacyViews();
// 取消自动打开预览视图(用于排查启动卡顿)。用户可通过图标或命令手动打开。
// console.log('[NoteToMpPlugin] 已跳过自动打开预览视图调试模式');
// console.log('[Note2AnyPlugin] 已跳过自动打开预览视图调试模式');
});
this.registerView(
@@ -90,28 +119,28 @@ export default class NoteToMpPlugin extends Plugin {
this.ribbonIconEl = this.addRibbonIcon('clipboard-paste', '复制到公众号', (evt: MouseEvent) => {
this.activateView();
});
this.ribbonIconEl.addClass('note-to-mp-plugin-ribbon-class');
this.ribbonIconEl.addClass('note2any-plugin-ribbon-class');
this.addCommand({
id: 'note-to-mp-preview',
id: 'note2any-preview',
name: '复制到公众号',
callback: () => {
this.activateView();
}
});
this.addSettingTab(new NoteToMpSettingTab(this.app, this));
this.addSettingTab(new Note2AnySettingTab(this.app, this));
this.addCommand({
id: 'note-to-mp-widget',
name: '插入样式小部件',
id: 'note2any-widget',
name: '插入样式件',
callback: () => {
new WidgetsModal(this.app).open();
}
});
this.addCommand({
id: 'note-to-mp-batch-publish',
id: 'note2any-batch-publish',
name: '批量发布文章',
callback: () => {
new BatchPublishModal(this.app, this).open();
@@ -120,7 +149,7 @@ export default class NoteToMpPlugin extends Plugin {
// TODO: 重构后需要重新实现批量发布功能
// this.addCommand({
// id: 'note-to-mp-pub',
// id: 'note2any-pub',
// name: '发布公众号文章',
// callback: async () => {
// await this.activateView();
@@ -130,7 +159,7 @@ export default class NoteToMpPlugin extends Plugin {
// 命令:当前文件发布到微信草稿
this.addCommand({
id: 'note-to-mp-post-current',
id: 'note2any-post-current',
name: '发布当前文件到公众号草稿',
callback: async () => {
const file = this.app.workspace.getActiveFile();
@@ -181,7 +210,7 @@ export default class NoteToMpPlugin extends Plugin {
}
onunload() {
console.log('Unloading NoteToMP');
console.log('Unloading Note2Any');
// 移除 ribbon icon避免重载插件时重复创建
if (this.ribbonIconEl) {
this.ribbonIconEl.remove();
@@ -208,7 +237,7 @@ export default class NoteToMpPlugin extends Plugin {
}
});
} catch (e) {
console.warn('[NoteToMp] cleanupLegacyViews 失败', e);
console.warn('[Note2Any] cleanupLegacyViews 失败', e);
}
}

View File

@@ -3,7 +3,7 @@
import { Tokens, MarkedExtension} from "marked";
import { Extension } from "./extension";
import AssetsManager from "src/assets";
import { wxWidget } from "src/weixin-api";
import { wxWidget } from 'src/wechat/weixin-api';
const icon_note = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-pencil"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"></path><path d="m15 5 4 4"></path></svg>`
const icon_abstract = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-clipboard-list"><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><path d="M12 11h4"></path><path d="M12 16h4"></path><path d="M8 11h.01"></path><path d="M8 16h.01"></path></svg>`

View File

@@ -7,7 +7,7 @@ import { MathRendererQueue } from "./math";
import { Extension } from "./extension";
import { UploadImageToWx } from "../imagelib";
import AssetsManager from "src/assets";
import { wxWidget } from "src/weixin-api";
import { wxWidget } from 'src/wechat/weixin-api';
export class CardDataManager {
private cardData: Map<string, string>;

View File

@@ -4,7 +4,7 @@ import { Tokens, MarkedExtension } from "marked";
import { Extension } from "./extension";
import AssetsManager from "src/assets";
import { ExpertSettings } from "src/expert-settings";
import { wxWidget } from "src/weixin-api";
import { wxWidget } from 'src/wechat/weixin-api';
export class HeadingRenderer extends Extension {
index = [0, 0, 0, 0];

View File

@@ -4,7 +4,7 @@ import { Tokens, MarkedExtension } from "marked";
import { Extension } from "./extension";
import { NMPSettings } from "src/settings";
import { uevent } from "src/utils";
import { wxWidget } from "src/weixin-api";
import { wxWidget } from 'src/wechat/weixin-api';
const widgetCache = new Map<string, string>();

View File

@@ -19,6 +19,17 @@ export interface PlatformChooserOptions {
onPlatformChange?: (platform: PlatformType) => Promise<void>;
}
export interface PlatformActionLabels {
refresh: string;
publish: string;
}
export interface PlatformChooserActions {
onRefresh?: () => void | Promise<void>;
onPublish?: () => void | Promise<void>;
getLabels?: (platform: PlatformType) => PlatformActionLabels;
}
/**
* 平台信息接口
*/
@@ -32,7 +43,7 @@ interface PlatformInfo {
* 支持的平台列表
*/
const SUPPORTED_PLATFORMS: PlatformInfo[] = [
{ value: 'wechat', label: '微信公众号', icon: '📱' },
{ value: 'wechat', label: '公众号', icon: '📱' },
{ value: 'xiaohongshu', label: '小红书', icon: '📔' }
];
@@ -48,8 +59,11 @@ const SUPPORTED_PLATFORMS: PlatformInfo[] = [
export class PlatformChooser {
private container: HTMLElement;
private selectElement: HTMLSelectElement | null = null;
private refreshButton: HTMLButtonElement | null = null;
private publishButton: HTMLButtonElement | null = null;
private currentPlatform: PlatformType;
private onChange?: (platform: PlatformType) => void;
private actions: PlatformChooserActions | null = null;
constructor(container: HTMLElement, options: PlatformChooserOptions = {}) {
this.container = container;
@@ -101,6 +115,16 @@ export class PlatformChooser {
const newPlatform = platformSelect.value as PlatformType;
this.switchPlatformInternal(newPlatform);
};
// 刷新按钮
this.refreshButton = this.container.createEl('button', { cls: 'toolbar-button purple-gradient' });
this.refreshButton.onclick = () => this.handleRefreshClick();
// 发布按钮
this.publishButton = this.container.createEl('button', { cls: 'toolbar-button' });
this.publishButton.onclick = () => this.handlePublishClick();
this.updateActionLabels();
}
/**
@@ -123,6 +147,8 @@ export class PlatformChooser {
console.error('[PlatformChooser] 平台切换失败:', error);
}
}
this.updateActionLabels();
}
/**
@@ -133,6 +159,7 @@ export class PlatformChooser {
if (this.selectElement) {
this.selectElement.value = platform;
}
this.updateActionLabels();
}
/**
@@ -160,5 +187,45 @@ export class PlatformChooser {
this.selectElement.onchange = null;
this.selectElement = null;
}
if (this.refreshButton) {
this.refreshButton.onclick = null;
this.refreshButton = null;
}
if (this.publishButton) {
this.publishButton.onclick = null;
this.publishButton = null;
}
}
/**
* 设置通用操作按钮
*/
setActions(actions: PlatformChooserActions): void {
this.actions = actions;
this.updateActionLabels();
}
private handleRefreshClick(): void {
if (!this.actions?.onRefresh) return;
Promise.resolve(this.actions.onRefresh()).catch((error) => {
console.error('[PlatformChooser] 刷新操作失败:', error);
});
}
private handlePublishClick(): void {
if (!this.actions?.onPublish) return;
Promise.resolve(this.actions.onPublish()).catch((error) => {
console.error('[PlatformChooser] 发布操作失败:', error);
});
}
private updateActionLabels(): void {
if (!this.refreshButton || !this.publishButton) return;
const labels = this.actions?.getLabels?.(this.currentPlatform) ?? {
refresh: '🔄 刷新',
publish: '📤 发布',
};
this.refreshButton.innerText = labels.refresh;
this.publishButton.innerText = labels.publish;
}
}

View File

@@ -93,6 +93,18 @@ export class PreviewManager {
// 构建 UI
this.platformChooser.render();
// 共享操作按钮
this.platformChooser.setActions({
onRefresh: () => this.refresh(),
onPublish: () => this.publishCurrentPlatform(),
getLabels: (platform) => {
if (platform === 'wechat') {
return { refresh: '🔄 刷新', publish: '📝 发布' };
}
return { refresh: '🔄 刷新', publish: '📤 发布' };
},
});
}
/**
@@ -125,6 +137,22 @@ export class PreviewManager {
this.wechatPreview.build();
}
private async publishCurrentPlatform(): Promise<void> {
if (this.currentPlatform === 'wechat') {
if (!this.wechatPreview) {
new Notice('微信预览未初始化');
return;
}
await this.wechatPreview.publish();
} else if (this.currentPlatform === 'xiaohongshu') {
if (!this.xhsPreview) {
new Notice('小红书预览未初始化');
return;
}
await this.xhsPreview.publish();
}
}
/**
* 创建小红书预览组件
*/

View File

@@ -1,895 +0,0 @@
/**
* 文件note-preview.ts
* 功能:侧边预览视图;支持多平台预览(公众号/小红书)与发布触发。
* - 渲染 Markdown
* - 平台切换下拉
* - 单篇发布入口
* - 与批量发布/图片处理集成预留
*/
import { EventRef, ItemView, Workspace, WorkspaceLeaf, Notice, Platform, TFile, TFolder, TAbstractFile, Plugin } from 'obsidian';
import { uevent, debounce, waitForLayoutReady } from './utils';
import { NMPSettings } from './settings';
import AssetsManager from './assets';
import { MarkedParser } from './markdown/parser';
import { LocalImageManager, LocalFile } from './markdown/local-file';
import { CardDataManager } from './markdown/code';
import { ArticleRender } from './article-render';
// 平台选择组件
import { PlatformChooser, PlatformType } from './platform-chooser';
// 微信公众号功能模块
import { WechatPreview } from './wechat/wechat-preview';
// 小红书功能模块
import { XiaohongshuContentAdapter } from './xiaohongshu/adapter';
import { XiaohongshuImageManager } from './xiaohongshu/image';
import { XiaohongshuAPIManager } from './xiaohongshu/api';
import { XiaohongshuPost } from './xiaohongshu/types';
import { XiaohongshuPreview } from './xiaohongshu/xhs-preview';
// 切图功能
import { sliceArticleImage } from './slice-image';
export const VIEW_TYPE_NOTE_PREVIEW = 'note-preview';
export class NotePreview extends ItemView {
workspace: Workspace;
plugin: Plugin;
mainDiv: HTMLDivElement;
toolbar: HTMLDivElement;
renderDiv: HTMLDivElement;
articleDiv: HTMLDivElement;
styleEl: HTMLElement;
coverEl: HTMLInputElement;
useDefaultCover: HTMLInputElement;
useLocalCover: HTMLInputElement;
msgView: HTMLDivElement;
wechatSelect: HTMLSelectElement;
platformSelect: HTMLSelectElement; // 新增:平台选择器
themeSelect: HTMLSelectElement;
highlightSelect: HTMLSelectElement;
listeners?: EventRef[];
container: Element;
settings: NMPSettings;
assetsManager: AssetsManager;
articleHTML: string;
title: string;
currentFile?: TFile;
currentTheme: string;
currentHighlight: string;
currentAppId: string;
currentPlatform: string = 'wechat'; // 新增:当前选择的平台,默认微信
markedParser: MarkedParser;
cachedElements: Map<string, string> = new Map();
_articleRender: ArticleRender | null = null;
_xiaohongshuPreview: XiaohongshuPreview | null = null;
_wechatPreview: WechatPreview | null = null;
_platformChooser: PlatformChooser | null = null;
isCancelUpload: boolean = false;
isBatchRuning: boolean = false;
constructor(leaf: WorkspaceLeaf, plugin: Plugin) {
super(leaf);
this.workspace = this.app.workspace;
this.plugin = plugin;
this.settings = NMPSettings.getInstance();
this.assetsManager = AssetsManager.getInstance();
this.currentTheme = this.settings.defaultStyle;
this.currentHighlight = this.settings.defaultHighlight;
}
getViewType() {
return VIEW_TYPE_NOTE_PREVIEW;
}
getIcon() {
return 'clipboard-paste';
}
getDisplayText() {
return '笔记预览';
}
get render() {
if (!this._articleRender) {
this._articleRender = new ArticleRender(this.app, this, this.styleEl, this.articleDiv);
this._articleRender.currentTheme = this.currentTheme;
this._articleRender.currentHighlight = this.currentHighlight;
}
return this._articleRender;
}
async onOpen() {
this.viewLoading();
this.setup();
uevent('open');
}
async setup() {
await waitForLayoutReady(this.app);
if (!this.settings.isLoaded) {
const data = await this.plugin.loadData();
NMPSettings.loadSettings(data);
}
if (!this.assetsManager.isLoaded) {
await this.assetsManager.loadAssets();
}
this.buildUI();
this.listeners = [
this.workspace.on('file-open', () => {
this.update();
}),
this.app.vault.on("modify", (file) => {
if (this.currentFile?.path == file.path) {
this.renderMarkdown();
}
} )
];
this.renderMarkdown();
}
async onClose() {
this.listeners?.forEach(listener => this.workspace.offref(listener));
LocalFile.fileCache.clear();
uevent('close');
}
onAppIdChanged() {
// 清理上传过的图片
this.cleanArticleData();
}
async update() {
if (this.isBatchRuning) {
return;
}
this.cleanArticleData();
this.renderMarkdown();
}
cleanArticleData() {
LocalImageManager.getInstance().cleanup();
CardDataManager.getInstance().cleanup();
}
buildMsgView(parent: HTMLDivElement) {
this.msgView = parent.createDiv({ cls: 'msg-view' });
const title = this.msgView.createDiv({ cls: 'msg-title' });
title.id = 'msg-title';
title.innerText = '加载中...';
const okBtn = this.msgView.createEl('button', { cls: 'msg-ok-btn' }, async (button) => {
});
okBtn.id = 'msg-ok-btn';
okBtn.innerText = '确定';
okBtn.onclick = async () => {
this.msgView.setAttr('style', 'display: none;');
}
const cancelBtn = this.msgView.createEl('button', { cls: 'msg-ok-btn' }, async (button) => {
});
cancelBtn.id = 'msg-cancel-btn';
cancelBtn.innerText = '取消';
cancelBtn.onclick = async () => {
this.isCancelUpload = true;
this.msgView.setAttr('style', 'display: none;');
}
}
showLoading(msg: string, cancelable: boolean = false) {
const title = this.msgView.querySelector('#msg-title') as HTMLElement;
title!.innerText = msg;
const btn = this.msgView.querySelector('#msg-ok-btn') as HTMLElement;
btn.setAttr('style', 'display: none;');
this.msgView.setAttr('style', 'display: flex;');
const cancelBtn = this.msgView.querySelector('#msg-cancel-btn') as HTMLElement;
cancelBtn.setAttr('style', cancelable ? 'display: block;': 'display: none;');
this.msgView.setAttr('style', 'display: flex;');
}
showMsg(msg: string) {
const title = this.msgView.querySelector('#msg-title') as HTMLElement;
title!.innerText = msg;
const btn = this.msgView.querySelector('#msg-ok-btn') as HTMLElement;
btn.setAttr('style', 'display: block;');
this.msgView.setAttr('style', 'display: flex;');
const cancelBtn = this.msgView.querySelector('#msg-cancel-btn') as HTMLElement;
cancelBtn.setAttr('style', 'display: none;');
this.msgView.setAttr('style', 'display: flex;');
}
buildToolbar(parent: HTMLDivElement) {
this.toolbar = parent.createDiv({ cls: 'preview-toolbar' });
let lineDiv;
// 平台选择器(新增)- 始终显示
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line platform-selector-line' });
const platformLabel = lineDiv.createDiv({ cls: 'style-label' });
platformLabel.innerText = '发布平台';
const platformSelect = lineDiv.createEl('select', { cls: 'platform-select' });
// 添加平台选项
const wechatOption = platformSelect.createEl('option');
wechatOption.value = 'wechat';
wechatOption.text = '微信公众号';
wechatOption.selected = true;
const xiaohongshuOption = platformSelect.createEl('option');
xiaohongshuOption.value = 'xiaohongshu';
xiaohongshuOption.text = '小红书';
platformSelect.onchange = async () => {
this.currentPlatform = platformSelect.value;
await this.onPlatformChanged();
};
this.platformSelect = platformSelect;
// 公众号
if (this.settings.wxInfo.length > 1 || Platform.isDesktop) {
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
const wxLabel = lineDiv.createDiv({ cls: 'style-label' });
wxLabel.innerText = '公众号';
const wxSelect = lineDiv.createEl('select', { cls: 'wechat-select' });
wxSelect.onchange = async () => {
this.currentAppId = wxSelect.value;
this.onAppIdChanged();
}
const defautlOp =wxSelect.createEl('option');
defautlOp.value = '';
defautlOp.text = '请在设置里配置公众号';
for (let i = 0; i < this.settings.wxInfo.length; i++) {
const op = wxSelect.createEl('option');
const wx = this.settings.wxInfo[i];
op.value = wx.appid;
op.text = wx.name;
if (i== 0) {
op.selected = true
this.currentAppId = wx.appid;
}
}
this.wechatSelect = wxSelect;
if (Platform.isDesktop) {
// 分隔线
const separator = lineDiv.createDiv({ cls: 'toolbar-separator' });
const openBtn = lineDiv.createEl('button', { text: '🌐 去公众号后台', cls: 'toolbar-button purple-gradient' });
openBtn.onclick = async () => {
const { shell } = require('electron');
shell.openExternal('https://mp.weixin.qq.com')
uevent('open-mp');
}
}
}
else if (this.settings.wxInfo.length > 0) {
this.currentAppId = this.settings.wxInfo[0].appid;
}
// 复制,刷新,带图片复制,发草稿箱
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only flex-wrap' });
const refreshBtn = lineDiv.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' });
refreshBtn.onclick = async () => {
await this.assetsManager.loadCustomCSS();
await this.assetsManager.loadExpertSettings();
this.render.reloadStyle();
await this.renderMarkdown();
uevent('refresh');
}
if (Platform.isDesktop) {
const copyBtn = lineDiv.createEl('button', { text: '📋 复制', cls: 'toolbar-button' });
copyBtn.onclick = async() => {
try {
await this.render.copyArticle();
new Notice('复制成功,请到公众号编辑器粘贴。');
uevent('copy');
} catch (error) {
console.error(error);
new Notice('复制失败: ' + error);
}
}
}
const uploadImgBtn = lineDiv.createEl('button', { text: '📤 上传图片', cls: 'toolbar-button' });
uploadImgBtn.onclick = async() => {
await this.uploadImages();
uevent('upload');
}
const postBtn = lineDiv.createEl('button', { text: '📝 发草稿', cls: 'toolbar-button' });
postBtn.onclick = async() => {
await this.postArticle();
uevent('pub');
}
const imagesBtn = lineDiv.createEl('button', { text: '🖼️ 图片/文字', cls: 'toolbar-button' });
imagesBtn.onclick = async() => {
await this.postImages();
uevent('pub-images');
}
if (Platform.isDesktop && this.settings.isAuthKeyVaild()) {
const htmlBtn = lineDiv.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' });
htmlBtn.onclick = async() => {
await this.exportHTML();
uevent('export-html');
}
}
// 封面
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
const coverTitle = lineDiv.createDiv({ cls: 'style-label' });
coverTitle.innerText = '封面';
this.useDefaultCover = lineDiv.createEl('input', { cls: 'input-style' });
this.useDefaultCover.setAttr('type', 'radio');
this.useDefaultCover.setAttr('name', 'cover');
this.useDefaultCover.setAttr('value', 'default');
this.useDefaultCover.setAttr('checked', true);
this.useDefaultCover.id = 'default-cover';
this.useDefaultCover.onchange = async () => {
if (this.useDefaultCover.checked) {
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
}
else {
this.coverEl.setAttr('style', 'visibility:visible;width:180px;');
}
}
const defaultLable = lineDiv.createEl('label');
defaultLable.innerText = '默认';
defaultLable.setAttr('for', 'default-cover');
this.useLocalCover = lineDiv.createEl('input', { cls: 'input-style' });
this.useLocalCover.setAttr('type', 'radio');
this.useLocalCover.setAttr('name', 'cover');
this.useLocalCover.setAttr('value', 'local');
this.useLocalCover.id = 'local-cover';
this.useLocalCover.setAttr('style', 'margin-left:20px;');
this.useLocalCover.onchange = async () => {
if (this.useLocalCover.checked) {
this.coverEl.setAttr('style', 'visibility:visible;width:180px;');
}
else {
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
}
}
const localLabel = lineDiv.createEl('label');
localLabel.setAttr('for', 'local-cover');
localLabel.innerText = '上传';
this.coverEl = lineDiv.createEl('input', { cls: 'upload-input' });
this.coverEl.setAttr('type', 'file');
this.coverEl.setAttr('placeholder', '封面图片');
this.coverEl.setAttr('accept', '.png, .jpg, .jpeg');
this.coverEl.setAttr('name', 'cover');
this.coverEl.id = 'cover-input';
// 样式
if (this.settings.showStyleUI) {
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only flex-wrap' });
const cssStyle = lineDiv.createDiv({ cls: 'style-label' });
cssStyle.innerText = '样式';
const selectBtn = lineDiv.createEl('select', { cls: 'style-select' });
selectBtn.onchange = async () => {
this.currentTheme = selectBtn.value;
this.render.updateStyle(selectBtn.value);
}
for (let s of this.assetsManager.themes) {
const op = selectBtn.createEl('option');
op.value = s.className;
op.text = s.name;
op.selected = s.className == this.settings.defaultStyle;
}
this.themeSelect = selectBtn;
// 分隔线
const separator = lineDiv.createDiv({ cls: 'toolbar-separator' });
const highlightStyle = lineDiv.createDiv({ cls: 'style-label' });
highlightStyle.innerText = '代码高亮';
const highlightStyleBtn = lineDiv.createEl('select', { cls: 'style-select' });
highlightStyleBtn.onchange = async () => {
this.currentHighlight = highlightStyleBtn.value;
this.render.updateHighLight(highlightStyleBtn.value);
}
for (let s of this.assetsManager.highlights) {
const op = highlightStyleBtn.createEl('option');
op.value = s.name;
op.text = s.name;
op.selected = s.name == this.settings.defaultHighlight;
}
this.highlightSelect = highlightStyleBtn;
}
this.buildMsgView(this.toolbar);
}
async buildUI() {
this.container = this.containerEl.children[1];
this.container.empty();
this.mainDiv = this.container.createDiv({ cls: 'note-preview' });
this.buildToolbar(this.mainDiv);
this.renderDiv = this.mainDiv.createDiv({cls: 'render-div'});
this.renderDiv.id = 'render-div';
this.styleEl = this.renderDiv.createEl('style');
this.styleEl.setAttr('title', 'note-to-mp-style');
this.articleDiv = this.renderDiv.createEl('div');
}
async viewLoading() {
const container = this.containerEl.children[1]
container.empty();
const loading = container.createDiv({cls: 'loading-wrapper'})
loading.createDiv({cls: 'loading-spinner'})
}
async renderMarkdown(af: TFile | null = null) {
if (!af) {
af = this.app.workspace.getActiveFile();
}
if (!af || af.extension.toLocaleLowerCase() !== 'md') {
return;
}
this.currentFile = af;
// 如果关闭了样式 UI则在渲染前强制使用全局默认样式/高亮(忽略 frontmatter 中的 theme/highlight
if (!this.settings.showStyleUI) {
const globalStyle = this.settings.defaultStyle;
const globalHighlight = this.settings.defaultHighlight;
// 仅当变更时更新当前与 articleRender 中的值,避免不必要的刷新
if (this.currentTheme !== globalStyle) {
this.currentTheme = globalStyle;
if (this._articleRender) {
this._articleRender.currentTheme = globalStyle;
}
}
if (this.currentHighlight !== globalHighlight) {
this.currentHighlight = globalHighlight;
if (this._articleRender) {
this._articleRender.currentHighlight = globalHighlight;
}
}
}
await this.render.renderMarkdown(af);
const metadata = this.render.getMetadata();
if (metadata.appid) {
this.wechatSelect.value = metadata.appid;
}
else {
this.wechatSelect.value = this.currentAppId;
}
// 仅当 UI 开启时才允许 frontmatter 覆盖与下拉同步;关闭时忽略 frontmatter 的 theme/highlight
if (this.settings.showStyleUI) {
if (metadata.theme) {
this.assetsManager.themes.forEach(theme => {
if (theme.name === metadata.theme) {
this.currentTheme = theme.className;
if (this.themeSelect) this.themeSelect.value = theme.className;
if (this._articleRender) this._articleRender.currentTheme = theme.className;
}
});
} else if (this.themeSelect) {
this.themeSelect.value = this.currentTheme;
}
if (metadata.highlight) {
this.currentHighlight = metadata.highlight;
if (this.highlightSelect) this.highlightSelect.value = metadata.highlight;
if (this._articleRender) this._articleRender.currentHighlight = metadata.highlight;
} else if (this.highlightSelect) {
this.highlightSelect.value = this.currentHighlight;
}
}
// 如果当前是小红书平台,更新小红书预览
if (this.currentPlatform === 'xiaohongshu' && this._xiaohongshuPreview) {
this.articleHTML = this.render.articleHTML;
await this._xiaohongshuPreview.renderArticle(this.articleHTML, af);
}
}
/**
* 平台切换处理
* 当用户切换发布平台时调用
*/
async onPlatformChanged() {
console.log(`[NotePreview] 平台切换至: ${this.currentPlatform}`);
if (this.currentPlatform === 'xiaohongshu') {
// 切换到小红书预览模式
await this.switchToXiaohongshuMode();
} else {
// 切换到微信公众号模式
this.switchToWechatMode();
}
}
/**
* 切换到小红书预览模式
*/
private async switchToXiaohongshuMode() {
// 隐藏微信相关的工具栏行和平台选择器
if (this.toolbar) {
const wechatLines = this.toolbar.querySelectorAll('.wechat-only');
wechatLines.forEach((line: HTMLElement) => {
line.style.display = 'none';
});
// 也隐藏平台选择器行
// const platformLine = this.toolbar.querySelector('.platform-selector-line') as HTMLElement;
// if (platformLine) {
// platformLine.style.display = 'none';
// }
}
// 隐藏渲染区域
if (this.renderDiv) this.renderDiv.style.display = 'none';
// 创建或显示小红书预览视图
if (!this._xiaohongshuPreview) {
const xhsContainer = this.mainDiv.createDiv({ cls: 'xiaohongshu-preview-container' });
this._xiaohongshuPreview = new XiaohongshuPreview(xhsContainer, this.app);
// 设置回调函数
this._xiaohongshuPreview.onRefreshCallback = async () => {
await this.onXiaohongshuRefresh();
};
this._xiaohongshuPreview.onPublishCallback = async () => {
await this.onXiaohongshuPublish();
};
this._xiaohongshuPreview.onPlatformChangeCallback = async (platform: string) => {
this.currentPlatform = platform;
if (platform === 'wechat') {
await this.onPlatformChanged();
}
};
this._xiaohongshuPreview.build();
} else {
const xhsContainer = this.mainDiv.querySelector('.xiaohongshu-preview-container') as HTMLElement;
if (xhsContainer) xhsContainer.style.display = 'flex';
}
// 如果有当前文件,渲染小红书预览
if (this.currentFile) {
// 如果还没有生成 articleHTML先生成它
if (!this.articleHTML) {
await this.render.renderMarkdown(this.currentFile);
this.articleHTML = this.render.articleHTML;
}
// 渲染到小红书预览
if (this.articleHTML) {
await this._xiaohongshuPreview.renderArticle(this.articleHTML, this.currentFile);
}
}
}
/**
* 切换到微信公众号模式
*/
private switchToWechatMode() {
// 显示微信相关的工具栏行和平台选择器
if (this.toolbar) {
const wechatLines = this.toolbar.querySelectorAll('.wechat-only');
wechatLines.forEach((line: HTMLElement) => {
line.style.display = 'flex';
});
// 也显示平台选择器行
const platformLine = this.toolbar.querySelector('.platform-selector-line') as HTMLElement;
if (platformLine) {
platformLine.style.display = 'flex';
}
}
// 显示渲染区域
if (this.renderDiv) this.renderDiv.style.display = 'block';
// 隐藏小红书预览视图
const xhsContainer = this.mainDiv.querySelector('.xiaohongshu-preview-container') as HTMLElement;
if (xhsContainer) xhsContainer.style.display = 'none';
}
/**
* 更新按钮文本为微信公众号相关
*/
private updateButtonsForWechat() {
const buttons = this.toolbar.querySelectorAll('button');
buttons.forEach(button => {
const text = button.textContent;
if (text === '发布到小红书') {
button.textContent = '发草稿';
} else if (text === '上传图片(小红书)') {
button.textContent = '上传图片';
}
});
}
/**
* 更新按钮文本为小红书相关
*/
private updateButtonsForXiaohongshu() {
const buttons = this.toolbar.querySelectorAll('button');
buttons.forEach(button => {
const text = button.textContent;
if (text === '发草稿') {
button.textContent = '发布到小红书';
} else if (text === '上传图片') {
button.textContent = '上传图片(小红书)';
}
});
}
async uploadImages() {
if (this.currentPlatform === 'wechat') {
await this.uploadImagesToWechat();
} else if (this.currentPlatform === 'xiaohongshu') {
await this.uploadImagesToXiaohongshu();
}
}
/**
* 上传图片到微信公众号
*/
async uploadImagesToWechat() {
this.showLoading('图片上传中...');
try {
await this.render.uploadImages(this.currentAppId);
this.showMsg('图片上传成功,并且文章内容已复制,请到公众号编辑器粘贴。');
} catch (error) {
this.showMsg('图片上传失败: ' + error.message);
}
}
/**
* 上传图片到小红书
*/
async uploadImagesToXiaohongshu() {
this.showLoading('处理图片中...');
try {
// 获取小红书适配器和图片处理器
const adapter = new XiaohongshuContentAdapter();
const imageHandler = XiaohongshuImageManager.getInstance();
// 获取当前文档的图片
const imageManager = LocalImageManager.getInstance();
const images = imageManager.getImageInfos(this.articleDiv);
if (images.length === 0) {
this.showMsg('当前文档没有图片需要处理');
return;
}
// 处理图片转换为PNG格式
const imageBlobs: { name: string; blob: Blob }[] = [];
for (const img of images) {
// 从filePath获取文件
const file = this.app.vault.getAbstractFileByPath(img.filePath);
if (file && file instanceof TFile) {
const fileData = await this.app.vault.readBinary(file);
imageBlobs.push({
name: file.name,
blob: new Blob([fileData])
});
}
}
const processedImages = await imageHandler.processImages(imageBlobs);
this.showMsg(`成功处理 ${processedImages.length} 张图片已转换为PNG格式`);
} catch (error) {
this.showMsg('图片处理失败: ' + error.message);
}
}
async postArticle() {
if (this.currentPlatform === 'wechat') {
await this.postToWechat();
} else if (this.currentPlatform === 'xiaohongshu') {
await this.postToXiaohongshu();
}
}
/**
* 发布到微信公众号草稿
*/
async postToWechat() {
let localCover = null;
if (this.useLocalCover.checked) {
const fileInput = this.coverEl;
if (!fileInput.files || fileInput.files.length === 0) {
this.showMsg('请选择封面文件');
return;
}
localCover = fileInput.files[0];
if (!localCover) {
this.showMsg('请选择封面文件');
return;
}
}
this.showLoading('发布中...');
try {
await this.render.postArticle(this.currentAppId, localCover);
this.showMsg('发布成功');
}
catch (error) {
this.showMsg('发布失败: ' + error.message);
}
}
/**
* 发布到小红书
*/
async postToXiaohongshu() {
this.showLoading('发布到小红书中...');
try {
if (!this.currentFile) {
this.showMsg('没有可发布的文件');
return;
}
// 读取文件内容
const fileContent = await this.app.vault.read(this.currentFile);
// 使用小红书适配器转换内容
const adapter = new XiaohongshuContentAdapter();
const xiaohongshuPost = adapter.adaptMarkdownToXiaohongshu(fileContent, {
addStyle: true,
generateTitle: true
});
// 验证内容
const validation = adapter.validatePost(xiaohongshuPost);
if (!validation.valid) {
this.showMsg('内容验证失败: ' + validation.errors.join('; '));
return;
}
// 获取小红书API实例
const api = XiaohongshuAPIManager.getInstance(false); // 暂时使用false
// 检查登录状态
const isLoggedIn = await api.checkLoginStatus();
if (!isLoggedIn) {
this.showMsg('请先登录小红书,或检查登录状态');
return;
}
// 发布内容
const result = await api.createPost(xiaohongshuPost);
if (result.success) {
this.showMsg('发布到小红书成功!');
} else {
this.showMsg('发布失败: ' + result.message);
}
}
catch (error) {
this.showMsg('发布失败: ' + error.message);
}
}
/**
* 小红书预览的刷新回调
*/
async onXiaohongshuRefresh() {
await this.assetsManager.loadCustomCSS();
await this.assetsManager.loadExpertSettings();
// 更新小红书预览的样式
if (this._xiaohongshuPreview) {
this._xiaohongshuPreview.assetsManager = this.assetsManager;
}
await this.renderMarkdown();
new Notice('刷新成功');
}
/**
* 小红书预览的发布回调
*/
async onXiaohongshuPublish() {
await this.postToXiaohongshu();
}
async postImages() {
this.showLoading('发布图片中...');
try {
await this.render.postImages(this.currentAppId);
this.showMsg('图片发布成功');
} catch (error) {
this.showMsg('图片发布失败: ' + error.message);
}
}
async exportHTML() {
this.showLoading('导出HTML中...');
try {
await this.render.exportHTML();
this.showMsg('HTML导出成功');
} catch (error) {
this.showMsg('HTML导出失败: ' + error.message);
}
}
async sliceArticleImage() {
if (!this.currentFile) {
new Notice('请先打开一个笔记文件');
return;
}
this.showLoading('切图处理中...');
try {
const articleSection = this.render.getArticleSection();
if (!articleSection) {
throw new Error('未找到预览区域');
}
await sliceArticleImage(articleSection, this.currentFile, this.app);
this.showMsg('切图完成');
} catch (error) {
console.error('切图失败:', error);
this.showMsg('切图失败: ' + error.message);
}
}
async batchPost(folder: TFolder) {
const files = folder.children.filter((child: TAbstractFile) => child.path.toLocaleLowerCase().endsWith('.md'));
if (!files) {
new Notice('没有可渲染的笔记或文件不支持渲染');
return;
}
this.isCancelUpload = false;
this.isBatchRuning = true;
try {
for (let file of files) {
this.showLoading(`即将发布: ${file.name}`, true);
await sleep(5000);
if (this.isCancelUpload) {
break;
}
this.cleanArticleData();
await this.renderMarkdown(file as TFile);
await this.postArticle();
}
if (!this.isCancelUpload) {
this.showMsg(`批量发布完成:成功发布 ${files.length} 篇笔记`);
}
}
catch (e) {
console.error(e);
new Notice('批量发布失败: ' + e.message);
}
finally {
this.isBatchRuning = false;
this.isCancelUpload = false;
}
}
}

View File

@@ -21,6 +21,10 @@ import { NMPSettings } from './settings';
import AssetsManager from './assets';
import { waitForLayoutReady, uevent } from './utils';
import { LocalFile } from './markdown/local-file';
import { ErrorHandler } from './core/error-handler';
import { ProgressIndicator } from './core/progress-indicator';
import { ConfigManager } from './core/config-manager';
import { ContentProcessor } from './core/content-processor';
export const VIEW_TYPE_NOTE_PREVIEW = 'note-preview';
@@ -101,31 +105,47 @@ export class PreviewView extends ItemView {
*/
async onOpen(): Promise<void> {
console.log('[PreviewView] 视图打开 layoutReady=', this.app.workspace.layoutReady);
// 不在未完成 layoutReady 时做重初始化,改为延迟
if (!this.app.workspace.layoutReady) {
this.showLoading();
console.log('[PreviewView] defer initialization until layoutReady');
this.app.workspace.onLayoutReady(() => {
// 使用微任务再推进,确保其它插件也完成
setTimeout(() => this.performInitialization(), 0);
});
return;
const progress = new ProgressIndicator();
progress.start('初始化预览视图');
try {
// 不在未完成 layoutReady 时做重初始化,改为延迟
if (!this.app.workspace.layoutReady) {
this.showLoading();
console.log('[PreviewView] defer initialization until layoutReady');
this.app.workspace.onLayoutReady(() => {
// 使用微任务再推进,确保其它插件也完成
setTimeout(() => this.performInitialization(), 0);
});
return;
}
await this.performInitialization();
progress.finish('预览视图初始化完成');
} catch (error) {
progress.error('预览视图初始化失败');
ErrorHandler.handle(error as Error, 'PreviewView.onOpen');
}
await this.performInitialization();
}
private async performInitialization(): Promise<void> {
const progress = new ProgressIndicator();
try {
const start = performance.now();
this.showLoading();
progress.update('初始化设置');
console.time('[PreviewView] initializeSettings');
await this.initializeSettings();
console.timeEnd('[PreviewView] initializeSettings');
progress.update('创建管理器');
console.time('[PreviewView] createManager');
await this.createManager();
console.timeEnd('[PreviewView] createManager');
progress.update('注册事件监听器');
console.time('[PreviewView] registerEventListeners');
this.registerEventListeners();
console.timeEnd('[PreviewView] registerEventListeners');
@@ -142,16 +162,13 @@ export class PreviewView extends ItemView {
}
console.log('[PreviewView] 初始化耗时(ms):', (performance.now() - start).toFixed(1));
progress.finish('视图初始化完成');
uevent('open');
} catch (error) {
console.error('[PreviewView] 初始化失败:', error);
new Notice('预览视图初始化失败: ' + (error instanceof Error ? error.message : String(error)));
const container = this.containerEl.children[1] as HTMLElement;
container.empty();
const errorDiv = container.createDiv({ cls: 'preview-error' });
errorDiv.createEl('h3', { text: '预览视图初始化失败' });
errorDiv.createEl('p', { text: error instanceof Error ? error.message : String(error) });
errorDiv.createEl('p', { text: '请尝试重新加载插件或查看控制台获取更多信息' });
progress.error('视图初始化失败');
ErrorHandler.handle(error as Error, 'PreviewView.performInitialization');
console.error('[PreviewView] 初始化失败', error);
this.showError('预览视图初始化失败,请检查插件设置');
}
}
@@ -331,6 +348,18 @@ export class PreviewView extends ItemView {
}
}
/**
* 显示错误信息
*/
private showError(message: string): void {
const container = this.containerEl.children[1] as HTMLElement;
container.empty();
const errorDiv = container.createDiv({ cls: 'preview-error' });
errorDiv.createEl('h3', { text: '预览视图错误' });
errorDiv.createEl('p', { text: message });
errorDiv.createEl('p', { text: '请尝试重新加载插件或查看控制台获取更多信息' });
}
/** 外部接口:切换平台 */
async changePlatform(platform: 'wechat' | 'xiaohongshu') {
await this.manager?.switchPlatform(platform as any);

View File

@@ -4,19 +4,19 @@
*/
import { App, TextAreaComponent, PluginSettingTab, Setting, Notice, sanitizeHTMLToDom } from 'obsidian';
import NoteToMpPlugin from './main';
import { wxGetToken,wxEncrypt } from './weixin-api';
import Note2AnyPlugin from './main';
import { wxGetToken, wxEncrypt } from './wechat/weixin-api';
import { cleanMathCache } from './markdown/math';
import { NMPSettings } from './settings';
import { DocModal } from './doc-modal';
export class NoteToMpSettingTab extends PluginSettingTab {
plugin: NoteToMpPlugin;
export class Note2AnySettingTab extends PluginSettingTab {
plugin: Note2AnyPlugin;
wxInfo: string;
wxTextArea: TextAreaComponent|null;
settings: NMPSettings;
constructor(app: App, plugin: NoteToMpPlugin) {
constructor(app: App, plugin: Note2AnyPlugin) {
super(app, plugin);
this.plugin = plugin;
this.settings = NMPSettings.getInstance();
@@ -160,99 +160,141 @@ export class NoteToMpSettingTab extends PluginSettingTab {
this.wxInfo = this.parseWXInfo();
const helpEl = containerEl.createEl('div', { cls: 'setting-help-section' });
helpEl.createEl('h2', {text: '帮助文档', cls: 'setting-help-title'});
helpEl.createEl('a', {text: 'https://sunboshi.tech/doc', attr: {href: 'https://sunboshi.tech/doc'}});
const tabs = [
{ id: 'style', label: '样式', render: (panel: HTMLElement) => this.renderStyleTab(panel) },
{ id: 'shortcode', label: '短代码', render: (panel: HTMLElement) => this.renderShortcodeTab(panel) },
{ id: 'theme', label: '主题', render: (panel: HTMLElement) => this.renderThemeTab(panel) },
{ id: 'image', label: '图片', render: (panel: HTMLElement) => this.renderImageTab(panel) },
{ id: 'user', label: '用户信息', render: (panel: HTMLElement) => this.renderUserTab(panel) },
];
containerEl.createEl('h2', {text: '插件设置'});
const tabBar = containerEl.createDiv({ cls: 'nmp-settings-tabs' });
const panelsWrapper = containerEl.createDiv({ cls: 'nmp-settings-panels' });
new Setting(containerEl)
const panelMap = new Map<string, HTMLElement>();
const buttonMap = new Map<string, HTMLButtonElement>();
const activate = (id: string) => {
buttonMap.forEach((btn, key) => btn.toggleClass('is-active', key === id));
panelMap.forEach((panel, key) => panel.toggleClass('is-active', key === id));
};
tabs.forEach((tab) => {
const button = tabBar.createEl('button', { text: tab.label, cls: 'nmp-settings-tab-button' });
button.onclick = () => activate(tab.id);
buttonMap.set(tab.id, button);
const panel = panelsWrapper.createDiv({ cls: 'nmp-settings-panel', attr: { 'data-tab': tab.id } });
panelMap.set(tab.id, panel);
tab.render(panel);
});
if (tabs.length > 0) {
activate(tabs[0].id);
}
}
private renderStyleTab(panel: HTMLElement): void {
new Setting(panel)
.setName('默认样式')
.addDropdown(dropdown => {
const styles = this.plugin.assetsManager.themes;
for (let s of styles) {
dropdown.addOption(s.className, s.name);
}
const styles = this.plugin.assetsManager.themes;
for (const s of styles) {
dropdown.addOption(s.className, s.name);
}
dropdown.setValue(this.settings.defaultStyle);
dropdown.onChange(async (value) => {
dropdown.onChange(async (value) => {
this.settings.defaultStyle = value;
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
.setName('代码高亮')
.addDropdown(dropdown => {
const styles = this.plugin.assetsManager.highlights;
for (let s of styles) {
dropdown.addOption(s.name, s.name);
}
dropdown.setValue(this.settings.defaultHighlight);
dropdown.onChange(async (value) => {
this.settings.defaultHighlight = value;
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
.setName('在工具栏展示样式选择')
.setDesc('建议在移动端关闭,可以增大文章预览区域')
.addToggle(toggle => {
toggle.setValue(this.settings.showStyleUI);
toggle.onChange(async (value) => {
this.settings.showStyleUI = value;
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
new Setting(panel)
.setName('代码高亮')
.addDropdown(dropdown => {
const styles = this.plugin.assetsManager.highlights;
for (const s of styles) {
dropdown.addOption(s.name, s.name);
}
dropdown.setValue(this.settings.defaultHighlight);
dropdown.onChange(async (value) => {
this.settings.defaultHighlight = value;
await this.plugin.saveSettings();
});
});
new Setting(panel)
.setName('链接展示样式')
.addDropdown(dropdown => {
dropdown.addOption('inline', '内嵌');
dropdown.addOption('footnote', '脚注');
dropdown.addOption('footnote', '脚注');
dropdown.setValue(this.settings.linkStyle);
dropdown.onChange(async (value) => {
this.settings.linkStyle = value;
this.settings.linkStyle = value;
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
new Setting(panel)
.setName('文件嵌入展示样式')
.addDropdown(dropdown => {
dropdown.addOption('quote', '引用');
dropdown.addOption('content', '正文');
dropdown.addOption('content', '正文');
dropdown.setValue(this.settings.embedStyle);
dropdown.onChange(async (value) => {
this.settings.embedStyle = value;
this.settings.embedStyle = value;
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
new Setting(panel)
.setName('数学公式语法')
.addDropdown(dropdown => {
dropdown.addOption('latex', 'latex');
dropdown.addOption('asciimath', 'asciimath');
dropdown.addOption('asciimath', 'asciimath');
dropdown.setValue(this.settings.math);
dropdown.onChange(async (value) => {
this.settings.math = value;
this.settings.math = value;
cleanMathCache();
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
new Setting(panel)
.setName('显示代码行号')
.addToggle(toggle => {
toggle.setValue(this.settings.lineNumber);
toggle.setValue(this.settings.lineNumber);
toggle.onChange(async (value) => {
this.settings.lineNumber = value;
this.settings.lineNumber = value;
await this.plugin.saveSettings();
});
})
});
new Setting(containerEl)
new Setting(panel)
.setName('启用空行渲染')
.addToggle(toggle => {
toggle.setValue(this.settings.enableEmptyLine);
toggle.onChange(async (value) => {
this.settings.enableEmptyLine = value;
await this.plugin.saveSettings();
});
});
new Setting(panel)
.setName('默认开启评论')
.setDesc('发布到公众号时默认开启评论,可在 frontmatter 使用 need_open_comment 关闭')
.addToggle(toggle => {
toggle.setValue(this.settings.needOpenComment);
toggle.onChange(async (value) => {
this.settings.needOpenComment = value;
await this.plugin.saveSettings();
});
});
}
private renderShortcodeTab(panel: HTMLElement): void {
new Setting(panel)
.setName('Gallery 根路径')
.setDesc('用于 {{<gallery dir="..."/>}} 短代码解析;需指向本地图片根目录')
.addText(text => {
@@ -265,7 +307,7 @@ export class NoteToMpSettingTab extends PluginSettingTab {
text.inputEl.setAttr('style', 'width: 360px;');
});
new Setting(containerEl)
new Setting(panel)
.setName('Gallery 选取图片数')
.setDesc('每个 gallery 短代码最多替换为前 N 张图片')
.addText(text => {
@@ -281,7 +323,18 @@ export class NoteToMpSettingTab extends PluginSettingTab {
text.inputEl.setAttr('style', 'width: 120px;');
});
new Setting(containerEl)
new Setting(panel)
.setName('忽略 frontmatter 封面')
.setDesc('开启后不使用 frontmatter 中 cover/image 字段封面将按正文首图→gallery→默认封面回退')
.addToggle(toggle => {
toggle.setValue(this.settings.ignoreFrontmatterImage);
toggle.onChange(async (value) => {
this.settings.ignoreFrontmatterImage = value;
await this.plugin.saveSettings();
});
});
new Setting(panel)
.setName('默认封面图片')
.setDesc('当文章无任何图片/短代码时使用;可填 wikilink 文件名或 http(s) URL')
.addText(text => {
@@ -293,35 +346,86 @@ export class NoteToMpSettingTab extends PluginSettingTab {
});
text.inputEl.setAttr('style', 'width: 360px;');
});
}
new Setting(containerEl)
.setName('忽略 frontmatter 封面')
.setDesc('开启后不使用 frontmatter 中 cover/image 字段封面将按正文首图→gallery→默认封面回退')
.addToggle(toggle => {
toggle.setValue(this.settings.ignoreFrontmatterImage);
toggle.onChange(async (value) => {
this.settings.ignoreFrontmatterImage = value;
private renderThemeTab(panel: HTMLElement): void {
new Setting(panel)
.setName('获取更多主题')
.addButton(button => {
button.setButtonText('下载');
button.onClick(async () => {
button.setButtonText('下载中...');
await this.plugin.assetsManager.downloadThemes();
button.setButtonText('下载完成');
});
})
.addButton(button => {
button.setIcon('folder-open');
button.onClick(async () => {
await this.plugin.assetsManager.openAssets();
});
});
new Setting(panel)
.setName('清空主题')
.addButton(button => {
button.setButtonText('清空');
button.onClick(async () => {
await this.plugin.assetsManager.removeThemes();
this.settings.resetStyelAndHighlight();
await this.plugin.saveSettings();
});
});
new Setting(panel)
.setName('全局CSS属性')
.setDesc('只能填写CSS属性不能写选择器')
.addTextArea(text => {
this.wxTextArea = text;
text.setPlaceholder('请输入CSS属性background: #fff;padding: 10px;')
.setValue(this.settings.baseCSS)
.onChange(async (value) => {
this.settings.baseCSS = value;
await this.plugin.saveSettings();
})
.inputEl.setAttr('style', 'width: 520px; height: 60px;');
});
new Setting(containerEl)
.setName('启用空行渲染')
.addToggle(toggle => {
toggle.setValue(this.settings.enableEmptyLine);
toggle.onChange(async (value) => {
this.settings.enableEmptyLine = value;
await this.plugin.saveSettings();
});
})
const customCSSDoc = '使用指南:<a href="https://sunboshi.tech/customcss">https://sunboshi.tech/customcss</a>';
new Setting(panel)
.setName('自定义CSS笔记')
.setDesc(sanitizeHTMLToDom(customCSSDoc))
.addText(text => {
text.setPlaceholder('请输入自定义CSS笔记标题')
.setValue(this.settings.customCSSNote)
.onChange(async (value) => {
this.settings.customCSSNote = value.trim();
await this.plugin.saveSettings();
await this.plugin.assetsManager.loadCustomCSS();
})
.inputEl.setAttr('style', 'width: 320px;');
});
// 切图配置区块
containerEl.createEl('h2', {text: '切图配置'});
const expertDoc = '使用指南:<a href="https://sunboshi.tech/expert">https://sunboshi.tech/expert</a>';
new Setting(panel)
.setName('专家设置笔记')
.setDesc(sanitizeHTMLToDom(expertDoc))
.addText(text => {
text.setPlaceholder('请输入专家设置笔记标题')
.setValue(this.settings.expertSettingsNote)
.onChange(async (value) => {
this.settings.expertSettingsNote = value.trim();
await this.plugin.saveSettings();
await this.plugin.assetsManager.loadExpertSettings();
})
.inputEl.setAttr('style', 'width: 320px;');
});
}
new Setting(containerEl)
private renderImageTab(panel: HTMLElement): void {
new Setting(panel)
.setName('切图保存路径')
.setDesc('切图文件的保存目录,默认:/Users/gavin/note2mp/images/xhs')
.setDesc('切图文件的保存目录,默认:/Users/gavin/note2any/images/xhs')
.addText(text => {
text.setPlaceholder('例如 /Users/xxx/images/xhs')
.setValue(this.settings.sliceImageSavePath || '')
@@ -332,7 +436,7 @@ export class NoteToMpSettingTab extends PluginSettingTab {
text.inputEl.setAttr('style', 'width: 360px;');
});
new Setting(containerEl)
new Setting(panel)
.setName('切图宽度')
.setDesc('长图及切图的宽度像素默认1080')
.addText(text => {
@@ -348,7 +452,7 @@ export class NoteToMpSettingTab extends PluginSettingTab {
text.inputEl.setAttr('style', 'width: 120px;');
});
new Setting(containerEl)
new Setting(panel)
.setName('切图横竖比例')
.setDesc('格式:宽:高,例如 3:4 表示竖图16:9 表示横图')
.addText(text => {
@@ -360,182 +464,119 @@ export class NoteToMpSettingTab extends PluginSettingTab {
});
text.inputEl.setAttr('style', 'width: 120px;');
});
new Setting(containerEl)
.setName('渲染图片标题')
.addToggle(toggle => {
toggle.setValue(this.settings.useFigcaption);
toggle.onChange(async (value) => {
this.settings.useFigcaption = value;
await this.plugin.saveSettings();
});
})
new Setting(containerEl)
.setName('Excalidraw 渲染为 PNG 图片')
.setDesc('开启:将 Excalidraw 笔记/嵌入转换为位图 PNG 插入;关闭:保持原始 SVG/矢量渲染(更清晰,体积更小)。')
.addToggle(toggle => {
toggle.setValue(this.settings.excalidrawToPNG);
toggle.onChange(async (value) => {
this.settings.excalidrawToPNG = value;
await this.plugin.saveSettings();
new Setting(panel)
.setName('渲染图片标题')
.addToggle(toggle => {
toggle.setValue(this.settings.useFigcaption);
toggle.onChange(async (value) => {
this.settings.useFigcaption = value;
await this.plugin.saveSettings();
});
});
})
new Setting(containerEl)
new Setting(panel)
.setName('Excalidraw 渲染为 PNG 图片')
.setDesc('开启:将 Excalidraw 笔记/嵌入转换为位图 PNG 插入;关闭:保持原始 SVG/矢量渲染。')
.addToggle(toggle => {
toggle.setValue(this.settings.excalidrawToPNG);
toggle.onChange(async (value) => {
this.settings.excalidrawToPNG = value;
await this.plugin.saveSettings();
});
});
new Setting(panel)
.setName('水印图片')
.setDesc('可填写文件名或 URL')
.addText(text => {
text.setPlaceholder('请输入图片名称')
text.setPlaceholder('例如 watermark.png')
.setValue(this.settings.watermark)
.onChange(async (value) => {
this.settings.watermark = value.trim();
this.settings.watermark = value.trim();
await this.plugin.saveSettings();
})
.inputEl.setAttr('style', 'width: 320px;')
})
new Setting(containerEl)
.setName('获取更多主题')
.addButton(button => {
button.setButtonText('下载');
button.onClick(async () => {
button.setButtonText('下载中...');
await this.plugin.assetsManager.downloadThemes();
button.setButtonText('下载完成');
});
})
.addButton(button => {
button.setIcon('folder-open');
button.onClick(async () => {
await this.plugin.assetsManager.openAssets();
});
.inputEl.setAttr('style', 'width: 320px;');
});
}
new Setting(containerEl)
.setName('清空主题')
.addButton(button => {
button.setButtonText('清空');
button.onClick(async () => {
await this.plugin.assetsManager.removeThemes();
this.settings.resetStyelAndHighlight();
await this.plugin.saveSettings();
});
})
new Setting(containerEl)
.setName('全局CSS属性')
.setDesc('只能填写CSS属性不能写选择器')
.addTextArea(text => {
this.wxTextArea = text;
text.setPlaceholder('请输入CSS属性background: #fff;padding: 10px;')
.setValue(this.settings.baseCSS)
.onChange(async (value) => {
this.settings.baseCSS = value;
await this.plugin.saveSettings();
})
.inputEl.setAttr('style', 'width: 520px; height: 60px;');
})
const customCSSDoc = '使用指南:<a href="https://sunboshi.tech/customcss">https://sunboshi.tech/customcss</a>';
new Setting(containerEl)
.setName('自定义CSS笔记')
.setDesc(sanitizeHTMLToDom(customCSSDoc))
.addText(text => {
text.setPlaceholder('请输入自定义CSS笔记标题')
.setValue(this.settings.customCSSNote)
.onChange(async (value) => {
this.settings.customCSSNote = value.trim();
await this.plugin.saveSettings();
await this.plugin.assetsManager.loadCustomCSS();
})
.inputEl.setAttr('style', 'width: 320px;')
});
const expertDoc = '使用指南:<a href="https://sunboshi.tech/expert">https://sunboshi.tech/expert</a>';
new Setting(containerEl)
.setName('专家设置笔记')
.setDesc(sanitizeHTMLToDom(expertDoc))
.addText(text => {
text.setPlaceholder('请输入专家设置笔记标题')
.setValue(this.settings.expertSettingsNote)
.onChange(async (value) => {
this.settings.expertSettingsNote = value.trim();
await this.plugin.saveSettings();
await this.plugin.assetsManager.loadExpertSettings();
})
.inputEl.setAttr('style', 'width: 320px;')
});
private renderUserTab(panel: HTMLElement): void {
let descHtml = '详情说明:<a href="https://sunboshi.tech/subscribe">https://sunboshi.tech/subscribe</a>';
if (this.settings.isVip) {
descHtml = '<span style="color:rgb(245, 70, 85);font-weight: bold;">👑永久会员</span><br/>' + descHtml;
}
else if (this.settings.expireat) {
const timestr = this.settings.expireat.toLocaleString();
descHtml = `有效期至:${timestr} <br/>${descHtml}`
descHtml = `有效期至:${timestr} <br/>${descHtml}`;
}
new Setting(containerEl)
new Setting(panel)
.setName('注册码AuthKey')
.setDesc(sanitizeHTMLToDom(descHtml))
.addText(text => {
text.setPlaceholder('请输入注册码')
.setValue(this.settings.authKey)
.onChange(async (value) => {
.setValue(this.settings.authKey)
.onChange(async (value) => {
this.settings.authKey = value.trim();
this.settings.getExpiredDate();
await this.plugin.saveSettings();
})
.inputEl.setAttr('style', 'width: 320px;')
}).descEl.setAttr('style', '-webkit-user-select: text; user-select: text;')
this.settings.getExpiredDate();
await this.plugin.saveSettings();
})
.inputEl.setAttr('style', 'width: 320px;');
}).descEl.setAttr('style', '-webkit-user-select: text; user-select: text;');
let isClear = this.settings.wxInfo.length > 0;
let isRealClear = false;
const buttonText = isClear ? '清空公众号信息' : '保存公众号信息';
new Setting(containerEl)
new Setting(panel)
.setName('公众号信息')
.addTextArea(text => {
this.wxTextArea = text;
text.setPlaceholder('请输入公众号信息\n格式公众号名称|公众号AppID|公众号AppSecret\n多个公众号请换行输入\n输入完成后点击加密按钮')
.setValue(this.wxInfo)
text.setPlaceholder('请输入公众号信息\n格式公众号名称|公众号AppID|公众号AppSecret\n多个公众号请换行输入\n输入完成后点击加密按钮')
.setValue(this.wxInfo)
.onChange(value => {
this.wxInfo = value;
this.wxInfo = value;
})
.inputEl.setAttr('style', 'width: 520px; height: 120px;');
.inputEl.setAttr('style', 'width: 520px; height: 120px;');
})
new Setting(containerEl).addButton(button => {
button.setButtonText(buttonText);
button.onClick(async () => {
if (isClear) {
isRealClear = true;
isClear = false;
button.setButtonText('确认清空?');
}
else if (isRealClear) {
isRealClear = false;
isClear = false;
this.clear();
button.setButtonText('保存公众号信息');
}
else {
button.setButtonText('保存中...');
if (await this.encrypt()) {
isClear = true;
isRealClear = false;
button.setButtonText('清空公众号信息');
.addButton(button => {
button.setButtonText(buttonText);
button.onClick(async () => {
if (isClear) {
isRealClear = true;
isClear = false;
button.setButtonText('确认清空?');
}
else {
else if (isRealClear) {
isRealClear = false;
isClear = false;
this.clear();
button.setButtonText('保存公众号信息');
}
}
});
})
.addButton(button => {
button.setButtonText('测试公众号');
button.onClick(async () => {
button.setButtonText('测试中...');
await this.testWXInfo();
button.setButtonText('测试公众号');
else {
button.setButtonText('保存中...');
if (await this.encrypt()) {
isClear = true;
isRealClear = false;
button.setButtonText('清空公众号信息');
}
else {
button.setButtonText('保存公众号信息');
}
}
});
})
})
.addButton(button => {
button.setButtonText('测试公众号');
button.onClick(async () => {
button.setButtonText('测试中...');
await this.testWXInfo();
button.setButtonText('测试公众号');
});
});
//
const helpEl = panel.createEl('div', { cls: 'setting-help-section' });
helpEl.createEl('h2', { text: '帮助文档', cls: 'setting-help-title' });
helpEl.createEl('a', { text: 'https://sunboshi.tech/doc', attr: { href: 'https://sunboshi.tech/doc' } });
}
}

View File

@@ -9,7 +9,7 @@
* - 批量发布预设 / 图片处理 / 样式控制等选项
*/
import { wxKeyInfo } from './weixin-api';
import { wxKeyInfo } from './wechat/weixin-api';
export class NMPSettings {
defaultStyle: string;
@@ -32,6 +32,7 @@ export class NMPSettings {
excalidrawToPNG: boolean;
isLoaded: boolean = false;
enableEmptyLine: boolean = false;
needOpenComment: boolean = true;
enableMarkdownImageToWikilink: boolean = true; // 自动将 ![alt](path/file.ext) 转为 ![[file.ext]]
// gallery 相关配置:根目录前缀 & 选取图片数量
galleryPrePath: string;
@@ -81,6 +82,7 @@ export class NMPSettings {
this.excalidrawToPNG = false;
this.expertSettingsNote = '';
this.enableEmptyLine = false;
this.needOpenComment = true;
this.enableMarkdownImageToWikilink = true;
// 默认值:用户原先硬编码路径 & 前 2 张
this.galleryPrePath = '/Users/gavin/myweb/static';
@@ -98,7 +100,7 @@ export class NMPSettings {
}
];
// 切图配置默认值
this.sliceImageSavePath = '/Users/gavin/note2mp/images/xhs';
this.sliceImageSavePath = '/Users/gavin/note2any/images/xhs';
this.sliceImageWidth = 1080;
this.sliceImageAspectRatio = '3:4';
this.xhsPreviewWidth = 540;
@@ -131,6 +133,7 @@ export class NMPSettings {
expertSettingsNote,
ignoreEmptyLine,
enableMarkdownImageToWikilink,
needOpenComment,
galleryPrePath,
galleryNumPic,
defaultCoverPic,
@@ -160,6 +163,7 @@ export class NMPSettings {
if (excalidrawToPNG !== undefined) settings.excalidrawToPNG = excalidrawToPNG;
if (expertSettingsNote) settings.expertSettingsNote = expertSettingsNote;
if (ignoreEmptyLine !== undefined) settings.enableEmptyLine = !!ignoreEmptyLine;
if (needOpenComment !== undefined) settings.needOpenComment = !!needOpenComment;
if (enableMarkdownImageToWikilink !== undefined) settings.enableMarkdownImageToWikilink = !!enableMarkdownImageToWikilink;
if (galleryPrePath) settings.galleryPrePath = galleryPrePath;
if (galleryNumPic !== undefined && Number.isFinite(galleryNumPic)) settings.galleryNumPic = Math.max(1, parseInt(galleryNumPic));
@@ -197,6 +201,7 @@ export class NMPSettings {
'excalidrawToPNG': settings.excalidrawToPNG,
'expertSettingsNote': settings.expertSettingsNote,
'ignoreEmptyLine': settings.enableEmptyLine,
'needOpenComment': settings.needOpenComment,
'enableMarkdownImageToWikilink': settings.enableMarkdownImageToWikilink,
'galleryPrePath': settings.galleryPrePath,
'galleryNumPic': settings.galleryNumPic,

View File

@@ -1,161 +0,0 @@
/* 文件slice-image.ts — 预览页面切图功能:将渲染完的 HTML 页面转为长图,再按比例裁剪为多张 PNG 图片。 */
import { toPng } from 'html-to-image';
import { Notice, TFile } from 'obsidian';
import { NMPSettings } from './settings';
import * as fs from 'fs';
import * as path from 'path';
/**
* 解析横竖比例字符串(如 "3:4")为数值
*/
function parseAspectRatio(ratio: string): { width: number; height: number } {
const parts = ratio.split(':').map(p => parseFloat(p.trim()));
if (parts.length === 2 && parts[0] > 0 && parts[1] > 0) {
return { width: parts[0], height: parts[1] };
}
// 默认 3:4
return { width: 3, height: 4 };
}
/**
* 从 frontmatter 获取 slug若不存在则使用文件名去除扩展名
*/
function getSlugFromFile(file: TFile, app: any): string {
const cache = app.metadataCache.getFileCache(file);
if (cache?.frontmatter?.slug) {
return String(cache.frontmatter.slug).trim();
}
return file.basename;
}
/**
* 确保目录存在
*/
function ensureDir(dirPath: string) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
}
/**
* 将 base64 dataURL 转为 Buffer
*/
function dataURLToBuffer(dataURL: string): Buffer {
const base64 = dataURL.split(',')[1];
return Buffer.from(base64, 'base64');
}
/**
* 切图主函数
* @param articleElement 预览文章的 HTML 元素(#article-section
* @param file 当前文件
* @param app Obsidian App 实例
*/
export async function sliceArticleImage(articleElement: HTMLElement, file: TFile, app: any) {
const settings = NMPSettings.getInstance();
const { sliceImageSavePath, sliceImageWidth, sliceImageAspectRatio } = settings;
// 解析比例
const ratio = parseAspectRatio(sliceImageAspectRatio);
const sliceHeight = Math.round((sliceImageWidth * ratio.height) / ratio.width);
// 获取 slug
const slug = getSlugFromFile(file, app);
new Notice(`开始切图:${slug},宽度=${sliceImageWidth},比例=${sliceImageAspectRatio}`);
try {
// 1. 保存原始样式
const originalWidth = articleElement.style.width;
const originalMaxWidth = articleElement.style.maxWidth;
const originalMinWidth = articleElement.style.minWidth;
// 2. 临时设置为目标宽度进行渲染
articleElement.style.width = `${sliceImageWidth}px`;
articleElement.style.maxWidth = `${sliceImageWidth}px`;
articleElement.style.minWidth = `${sliceImageWidth}px`;
// 等待样式生效和重排
await new Promise(resolve => setTimeout(resolve, 100));
new Notice(`设置渲染宽度: ${sliceImageWidth}px`);
// 3. 生成长图 - 使用实际渲染宽度
new Notice('正在生成长图...');
const longImageDataURL = await toPng(articleElement, {
width: sliceImageWidth,
pixelRatio: 1,
cacheBust: true,
});
// 4. 恢复原始样式
articleElement.style.width = originalWidth;
articleElement.style.maxWidth = originalMaxWidth;
articleElement.style.minWidth = originalMinWidth;
// 5. 创建临时 Image 对象以获取长图实际高度
const img = new Image();
await new Promise<void>((resolve, reject) => {
img.onload = () => resolve();
img.onerror = reject;
img.src = longImageDataURL;
});
const fullHeight = img.height;
const fullWidth = img.width;
new Notice(`长图生成完成:${fullWidth}x${fullHeight}px`);
// 3. 保存完整长图
ensureDir(sliceImageSavePath);
const longImagePath = path.join(sliceImageSavePath, `${slug}.png`);
const longImageBuffer = dataURLToBuffer(longImageDataURL);
fs.writeFileSync(longImagePath, new Uint8Array(longImageBuffer));
new Notice(`长图已保存:${longImagePath}`);
// 4. 计算需要切多少片
const sliceCount = Math.ceil(fullHeight / sliceHeight);
new Notice(`开始切图:共 ${sliceCount} 张,每张 ${sliceImageWidth}x${sliceHeight}px`);
// 5. 使用 Canvas 裁剪
const canvas = document.createElement('canvas');
canvas.width = sliceImageWidth;
canvas.height = sliceHeight;
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('无法创建 Canvas 上下文');
}
for (let i = 0; i < sliceCount; i++) {
const yOffset = i * sliceHeight;
const actualHeight = Math.min(sliceHeight, fullHeight - yOffset);
// 清空画布(处理最后一张可能不足高度的情况,用白色填充)
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, sliceImageWidth, sliceHeight);
// 绘制裁剪区域
ctx.drawImage(
img,
0, yOffset, fullWidth, actualHeight, // 源区域
0, 0, sliceImageWidth, actualHeight // 目标区域
);
// 导出为 PNG
const sliceDataURL = canvas.toDataURL('image/png');
const sliceBuffer = dataURLToBuffer(sliceDataURL);
const sliceFilename = `${slug}_${i + 1}.png`;
const slicePath = path.join(sliceImageSavePath, sliceFilename);
fs.writeFileSync(slicePath, new Uint8Array(sliceBuffer));
new Notice(`已保存:${sliceFilename}`);
}
new Notice(`✅ 切图完成!共 ${sliceCount} 张图片,保存在:${sliceImageSavePath}`);
} catch (error) {
console.error('切图失败:', error);
new Notice(`❌ 切图失败:${error.message}`);
}
}

View File

@@ -3,8 +3,8 @@
* 作用:通用工具函数集合(事件、版本、字符串处理等)。
*/
import { App, sanitizeHTMLToDom, requestUrl, Platform } from "obsidian";
import * as postcss from "./postcss/postcss";
import { App, sanitizeHTMLToDom, Platform } from "obsidian";
import * as postcss from "./postcss/postcss"; // 内置 PostCSS runtime解析主题 CSS 用于内联样式
let PluginVersion = "0.0.0";
let PlugPlatform = "obsidian";
@@ -31,7 +31,7 @@ export function setVersion(version: string) {
function getStyleSheet() {
for (var i = 0; i < document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
if (sheet.title == 'note-to-mp-style') {
if (sheet.title == 'note2any-style') {
return sheet;
}
}
@@ -185,10 +185,7 @@ export function applyCSS(html: string, css: string) {
}
export function uevent(name: string) {
const url = `https://u.sunboshi.tech/event?name=${name}&platform=${PlugPlatform}&v=${PluginVersion}`;
requestUrl(url).then().catch(error => {
console.error("Failed to send event: " + url, error);
});
console.debug(`[uevent] ${name} @${PlugPlatform} v${PluginVersion}`);
}
/**

View File

@@ -9,7 +9,7 @@
* 4. 提供文章导出HTML功能
*/
import { Notice, Platform, TFile, TFolder } from 'obsidian';
import { Notice, Platform, TFile } from 'obsidian';
import { NMPSettings } from '../settings';
import AssetsManager from '../assets';
import { ArticleRender } from '../article-render';
@@ -32,8 +32,9 @@ export class WechatPreview {
currentHighlight: string;
// UI 元素
toolbar: HTMLDivElement | null = null;
renderDiv: HTMLDivElement | null = null;
board: HTMLDivElement | null = null;
contentCell: HTMLElement | null = null;
contentEl: HTMLElement | null = null;
wechatSelect: HTMLSelectElement | null = null;
themeSelect: HTMLSelectElement | null = null;
highlightSelect: HTMLSelectElement | null = null;
@@ -65,103 +66,95 @@ export class WechatPreview {
*/
build(): void {
this.container.empty();
// 创建工具栏
this.toolbar = this.container.createDiv({ cls: 'preview-toolbar' });
this.buildToolbar(this.toolbar);
// 创建渲染区域
this.renderDiv = this.container.createDiv({ cls: 'render-div' });
this.renderDiv.id = 'render-div';
this.container.addClass('wechat-preview-container');
// 将 ArticleRender 的 style 与内容节点挂载
try {
if (this.render && this.render.styleEl && !this.renderDiv.contains(this.render.styleEl)) {
this.renderDiv.appendChild(this.render.styleEl);
}
if (this.render && this.render.articleDiv && !this.renderDiv.contains(this.render.articleDiv)) {
// 容器样式:模拟公众号编辑器宽度,更好的排版显示
this.render.articleDiv.addClass('wechat-article-wrapper');
this.renderDiv.appendChild(this.render.articleDiv);
}
} catch (e) {
console.warn('[WechatPreview] 挂载文章容器失败', e);
}
this.board = this.container.createDiv({ cls: 'wechat-board' });
this.buildAccountRow();
//this.buildCoverRow();
//this.buildStyleRow();
this.contentCell = this.createCell('content');
this.contentCell.addClass('wechat-cell-content');
this.mountArticle(this.board);
}
/**
* 构建工具栏
*/
private buildToolbar(parent: HTMLDivElement): void {
// 单层 Grid所有控件直接挂到 parent.preview-toolbar
private createCell(area: string, tag: keyof HTMLElementTagNameMap = 'div', extraClasses: string[] = []): HTMLElement {
if (!this.board) {
throw new Error('Wechat board not initialized');
}
const cell = this.board.createEl(tag, { attr: { 'data-area': area } });
cell.addClass('wechat-cell');
for (const cls of extraClasses) {
cell.addClass(cls);
}
return cell;
}
// 公众号选择
if (this.settings.wxInfo.length > 1 || Platform.isDesktop) {
const wxLabel = parent.createDiv({ cls: 'style-label' });
wxLabel.innerText = '公众号';
private buildAccountRow(): void {
const selectCell = this.createCell('account-select');
const selectLabel = selectCell.createEl('label', {
cls: 'style-label',
attr: { for: 'wechat-account-select' },
text: '公众号'
});
selectLabel.addClass('wechat-account-label');
const wxSelect = parent.createEl('select', { cls: 'wechat-select' });
wxSelect.onchange = async () => {
this.currentAppId = wxSelect.value;
this.onAppIdChanged();
};
const wxSelect = selectCell.createEl('select', {
cls: 'wechat-select',
attr: { id: 'wechat-account-select' }
}) as HTMLSelectElement;
wxSelect.onchange = async () => {
this.currentAppId = wxSelect.value;
this.onAppIdChanged();
};
const defaultOp = wxSelect.createEl('option');
defaultOp.value = '';
defaultOp.text = '请在设置里配置公众号';
const defaultOp = wxSelect.createEl('option');
defaultOp.value = '';
defaultOp.text = '请在设置里配置公众号';
for (let i = 0; i < this.settings.wxInfo.length; i++) {
const op = wxSelect.createEl('option');
const wx = this.settings.wxInfo[i];
op.value = wx.appid;
op.text = wx.name;
if (i === 0) {
op.selected = true;
this.currentAppId = wx.appid;
}
}
this.wechatSelect = wxSelect;
if (Platform.isDesktop) {
//parent.createDiv({ cls: 'toolbar-separator' });
const openBtn = parent.createEl('button', { text: '🌐 去公众号后台', cls: 'toolbar-button purple-gradient' });
openBtn.onclick = async () => {
const { shell } = require('electron');
shell.openExternal('https://mp.weixin.qq.com');
uevent('open-mp');
};
for (let i = 0; i < this.settings.wxInfo.length; i++) {
const op = wxSelect.createEl('option');
const wx = this.settings.wxInfo[i];
op.value = wx.appid;
op.text = wx.name;
if (i === 0) {
op.selected = true;
this.currentAppId = wx.appid;
}
}
this.wechatSelect = wxSelect;
// 操作按钮(直接平铺在 Grid 中)
const refreshBtn = parent.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' });
refreshBtn.onclick = async () => { if (this.onRefreshCallback) await this.onRefreshCallback(); };
const postBtn = parent.createEl('button', { text: '📝 发布', cls: 'toolbar-button' });
postBtn.onclick = async () => await this.postArticle();
const actionsCell = this.createCell('account-back-export');
if (Platform.isDesktop) {
const openBtn = actionsCell.createEl('button', {
text: '访问后台',
cls: 'toolbar-button purple-gradient wechat-action-button'
});
openBtn.onclick = async () => {
const { shell } = require('electron');
shell.openExternal('https://mp.weixin.qq.com');
uevent('open-mp');
};
}
if (Platform.isDesktop && this.settings.isAuthKeyVaild()) {
const htmlBtn = parent.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' });
htmlBtn.onclick = async () => await this.exportHTML();
const exportBtn = actionsCell.createEl('button', { text: '导出页面', cls: 'toolbar-button wechat-action-button' });
exportBtn.onclick = async () => await this.exportHTML();
}
// 封面选择
this.buildCoverSelector(parent);
// 样式选择(如果启用)
if (this.settings.showStyleUI) {
this.buildStyleSelector(parent);
if (actionsCell.childElementCount === 0) {
actionsCell.addClass('wechat-cell-placeholder');
}
}
/**
* 构建封面选择器
*/
private buildCoverSelector(parent: HTMLDivElement): void {
const coverTitle = parent.createDiv({ cls: 'style-label' });
coverTitle.innerText = '封面';
private buildCoverRow(): void {
const selectCell = this.createCell('cover-select');
selectCell.createDiv({ cls: 'style-label', text: '封面' });
this.useDefaultCover = parent.createEl('input', { cls: 'input-style' });
this.useDefaultCover = selectCell.createEl('input', { cls: 'input-style' }) as HTMLInputElement;
this.useDefaultCover.setAttr('type', 'radio');
this.useDefaultCover.setAttr('name', 'cover');
this.useDefaultCover.setAttr('value', 'default');
@@ -172,43 +165,42 @@ export class WechatPreview {
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
}
};
selectCell.createEl('label', { text: '默认', attr: { for: 'default-cover' } });
const defaultLabel = parent.createEl('label');
defaultLabel.innerText = '默认';
defaultLabel.setAttr('for', 'default-cover');
this.useLocalCover = parent.createEl('input', { cls: 'input-style' });
this.useLocalCover = selectCell.createEl('input', { cls: 'input-style' }) as HTMLInputElement;
this.useLocalCover.setAttr('type', 'radio');
this.useLocalCover.setAttr('name', 'cover');
this.useLocalCover.setAttr('value', 'local');
this.useLocalCover.id = 'local-cover';
this.useLocalCover.setAttr('style', 'margin-left:20px;');
this.useLocalCover.onchange = async () => {
if (this.useLocalCover?.checked && this.coverEl) {
this.coverEl.setAttr('style', 'visibility:visible;width:180px;');
}
};
selectCell.createEl('label', { text: '上传', attr: { for: 'local-cover' } });
const localLabel = parent.createEl('label');
localLabel.setAttr('for', 'local-cover');
localLabel.innerText = '上传';
this.coverEl = parent.createEl('input', { cls: 'upload-input' });
this.coverEl.setAttr('type', 'file');
this.coverEl.setAttr('placeholder', '封面图片');
this.coverEl.setAttr('accept', '.png, .jpg, .jpeg');
this.coverEl.setAttr('name', 'cover');
this.coverEl.id = 'cover-input';
const inputCell = this.createCell('cover-input');
this.coverEl = inputCell.createEl('input', {
cls: 'upload-input',
attr: {
type: 'file',
placeholder: '封面图片',
accept: '.png, .jpg, .jpeg',
name: 'cover',
id: 'cover-input'
}
}) as HTMLInputElement;
if (this.useDefaultCover?.checked) {
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
}
}
/**
* 构建样式选择器
*/
private buildStyleSelector(parent: HTMLDivElement): void {
const cssStyle = parent.createDiv({ cls: 'style-label' });
cssStyle.innerText = '样式';
private buildStyleRow(): void {
const styleLabelCell = this.createCell('style-label', 'div', ['style-label']);
styleLabelCell.setText('样式');
const selectBtn = parent.createEl('select', { cls: 'style-select' });
const styleSelectCell = this.createCell('style-select');
const selectBtn = styleSelectCell.createEl('select', { cls: 'style-select wechat-style-select' }) as HTMLSelectElement;
selectBtn.onchange = async () => {
this.currentTheme = selectBtn.value;
this.render.updateStyle(selectBtn.value);
@@ -222,12 +214,11 @@ export class WechatPreview {
}
this.themeSelect = selectBtn;
parent.createDiv({ cls: 'toolbar-separator' });
const highlightLabelCell = this.createCell('highlight-label', 'div', ['style-label']);
highlightLabelCell.setText('代码高亮');
const highlightStyle = parent.createDiv({ cls: 'style-label' });
highlightStyle.innerText = '代码高亮';
const highlightStyleBtn = parent.createEl('select', { cls: 'style-select' });
const highlightSelectCell = this.createCell('highlight-select');
const highlightStyleBtn = highlightSelectCell.createEl('select', { cls: 'style-select wechat-style-select' }) as HTMLSelectElement;
highlightStyleBtn.onchange = async () => {
this.currentHighlight = highlightStyleBtn.value;
this.render.updateHighLight(highlightStyleBtn.value);
@@ -243,6 +234,29 @@ export class WechatPreview {
this.highlightSelect = highlightStyleBtn;
}
private mountArticle(_parent: HTMLElement): void {
if (!this.contentCell) {
return;
}
try {
if (this.render?.styleEl && !this.contentCell.contains(this.render.styleEl)) {
this.contentCell.appendChild(this.render.styleEl);
}
if (this.render?.articleDiv) {
this.render.articleDiv.addClass('wechat-article-wrapper');
if (this.render.articleDiv.parentElement !== this.contentCell) {
this.contentCell.appendChild(this.render.articleDiv);
}
this.contentEl = this.render.articleDiv;
}
} catch (error) {
console.warn('[WechatPreview] 挂载文章容器失败', error);
}
}
/**
* 构建封面选择器
*/
/**
* 显示微信预览视图
*/
@@ -366,8 +380,9 @@ export class WechatPreview {
* 清理资源
*/
destroy(): void {
this.toolbar = null;
this.renderDiv = null;
this.board = null;
this.contentCell = null;
this.contentEl = null;
this.wechatSelect = null;
this.themeSelect = null;
this.highlightSelect = null;
@@ -387,6 +402,16 @@ export class WechatPreview {
/** 对外:发布草稿(供外层菜单调用) */
async postDraft() { await this.postArticle(); }
async publish(): Promise<void> {
await this.postDraft();
}
async refresh(): Promise<void> {
if (this.onRefreshCallback) {
await this.onRefreshCallback();
}
}
/** 由上层在切换/渲染时注入当前文件 */
setFile(file: TFile | null) { this.currentFile = file; }
}

View File

@@ -18,6 +18,11 @@ import { sliceCurrentPage, sliceAllPages } from './slice';
const XHS_PREVIEW_DEFAULT_WIDTH = 540;
const XHS_PREVIEW_WIDTH_OPTIONS = [1080, 720, 540, 360];
// 字号控制常量:一处修改即可同步 UI 显示、输入校验和渲染逻辑
const XHS_FONT_SIZE_MIN = 18;
const XHS_FONT_SIZE_MAX = 45;
const XHS_FONT_SIZE_DEFAULT = 36;
/**
* 小红书预览视图类
*/
@@ -29,14 +34,11 @@ export class XiaohongshuPreview {
currentFile: TFile | null = null;
// UI 元素
topToolbar!: HTMLDivElement;
templateSelect!: HTMLSelectElement;
fontSizeInput!: HTMLInputElement;
previewWidthSelect!: HTMLSelectElement;
pageContainer!: HTMLDivElement;
bottomToolbar!: HTMLDivElement;
pageNavigation!: HTMLDivElement;
pageNumberInput!: HTMLInputElement;
pageTotalLabel!: HTMLSpanElement;
styleEl: HTMLStyleElement | null = null; // 主题样式注入节点
@@ -45,7 +47,7 @@ export class XiaohongshuPreview {
// 分页数据
pages: PageInfo[] = [];
currentPageIndex: number = 0;
currentFontSize: number = 16;
currentFontSize: number = XHS_FONT_SIZE_DEFAULT;
articleHTML: string = '';
// 回调函数
@@ -75,49 +77,20 @@ export class XiaohongshuPreview {
this.container.appendChild(this.styleEl);
}
// 顶部工具栏
this.buildTopToolbar();
// 页面容器
this.pageContainer = this.container.createDiv({ cls: 'xhs-page-container' });
// 分页导航
this.buildPageNavigation();
// 底部操作栏
this.buildBottomToolbar();
}
/**
* 构建顶部工具栏
*/
private buildTopToolbar(): void {
this.topToolbar = this.container.createDiv({ cls: 'xhs-top-toolbar' });
// 刷新按钮
const refreshBtn = this.topToolbar.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' });
refreshBtn.onclick = () => this.onRefresh();
// 发布按钮
const publishBtn = this.topToolbar.createEl('button', { text: '📤 发布', cls: 'toolbar-button' });
publishBtn.onclick = () => this.onPublish();
// 分隔线
const separator2 = this.topToolbar.createDiv({ cls: 'toolbar-separator' });
// 模板选择
const templateLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
templateLabel.innerText = '模板';
this.templateSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' });
const board = this.container.createDiv({ cls: 'xhs-board' });
const templateCard = this.createGridCard(board, 'xhs-area-template');
const templateLabel = templateCard.createDiv({ cls: 'xhs-label', text: '模板' });
this.templateSelect = templateCard.createEl('select', { cls: 'xhs-select' });
['默认模板', '简约模板', '杂志模板'].forEach(name => {
const option = this.templateSelect.createEl('option');
option.value = name;
option.text = name;
});
const previewWidthLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
previewWidthLabel.innerText = '预览宽度';
this.previewWidthSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' });
const previewCard = this.createGridCard(board, 'xhs-area-preview');
const previewLabel = previewCard.createDiv({ cls: 'xhs-label', text: '宽度' });
this.previewWidthSelect = previewCard.createEl('select', { cls: 'xhs-select' });
const currentPreviewWidth = this.settings.xhsPreviewWidth || XHS_PREVIEW_DEFAULT_WIDTH;
XHS_PREVIEW_WIDTH_OPTIONS.forEach(value => {
const option = this.previewWidthSelect.createEl('option');
@@ -138,37 +111,35 @@ export class XiaohongshuPreview {
this.previewWidthSelect.value = String(this.settings.xhsPreviewWidth || XHS_PREVIEW_DEFAULT_WIDTH);
}
};
// 字号控制(可直接编辑)
const fontSizeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
fontSizeLabel.innerText = '字号';
const fontSizeGroup = this.topToolbar.createDiv({ cls: 'font-size-group' });
const fontCard = this.createGridCard(board, 'xhs-area-font');
//fontCard.createDiv({ cls: 'xhs-label', text: '字号' });
const fontSizeGroup = fontCard.createDiv({ cls: 'font-size-group' });
const decreaseBtn = fontSizeGroup.createEl('button', { text: '', cls: 'font-size-btn' });
decreaseBtn.onclick = () => this.changeFontSize(-1);
this.fontSizeInput = fontSizeGroup.createEl('input', {
this.fontSizeInput = fontSizeGroup.createEl('input', {
cls: 'font-size-input',
attr: { type: 'number', min: '12', max: '36', value: '16' }
attr: {
type: 'number',
min: String(XHS_FONT_SIZE_MIN),
max: String(XHS_FONT_SIZE_MAX),
value: String(XHS_FONT_SIZE_DEFAULT)
}
});
this.fontSizeInput.style.width = '50px';
this.fontSizeInput.style.textAlign = 'center';
this.fontSizeInput.onchange = () => this.onFontSizeInputChanged();
const increaseBtn = fontSizeGroup.createEl('button', { text: '', cls: 'font-size-btn' });
increaseBtn.onclick = () => this.changeFontSize(1);
}
/**
* 构建分页导航
*/
private buildPageNavigation(): void {
this.pageNavigation = this.container.createDiv({ cls: 'xhs-page-navigation' });
const prevBtn = this.pageNavigation.createEl('button', { text: '', cls: 'xhs-nav-btn' });
const contentWrapper = board.createDiv({ cls: 'xhs-area-content' });
this.pageContainer = contentWrapper.createDiv({ cls: 'xhs-page-container' });
const paginationCard = this.createGridCard(board, 'xhs-area-pagination xhs-pagination');
const prevBtn = paginationCard.createEl('button', { text: '', cls: 'xhs-nav-btn' });
prevBtn.onclick = () => this.previousPage();
const indicator = this.pageNavigation.createDiv({ cls: 'xhs-page-indicator' });
const indicator = paginationCard.createDiv({ cls: 'xhs-page-indicator' });
this.pageNumberInput = indicator.createEl('input', {
cls: 'xhs-page-number-input',
attr: { type: 'text', value: '1', inputmode: 'numeric', 'aria-label': '当前页码' }
@@ -189,22 +160,20 @@ export class XiaohongshuPreview {
this.pageNumberInput.onblur = () => this.handlePageNumberInput();
this.pageTotalLabel = indicator.createEl('span', { cls: 'xhs-page-number-total', text: '/1' });
const nextBtn = this.pageNavigation.createEl('button', { text: '', cls: 'xhs-nav-btn' });
const nextBtn = paginationCard.createEl('button', { text: '', cls: 'xhs-nav-btn' });
nextBtn.onclick = () => this.nextPage();
const sliceCard = this.createGridCard(board, 'xhs-area-slice');
const sliceCurrentBtn = sliceCard.createEl('button', { text: '当前页切图', cls: 'xhs-slice-btn' });
sliceCurrentBtn.onclick = () => this.sliceCurrentPage();
const sliceAllBtn = sliceCard.createEl('button', { text: '全部页切图', cls: 'xhs-slice-btn secondary' });
sliceAllBtn.onclick = () => this.sliceAllPages();
}
/**
* 构建底部操作栏
*/
private buildBottomToolbar(): void {
this.bottomToolbar = this.container.createDiv({ cls: 'xhs-bottom-toolbar' });
const currentPageBtn = this.bottomToolbar.createEl('button', { text: '⬇ 当前页切图', cls: 'xhs-slice-btn' });
currentPageBtn.onclick = () => this.sliceCurrentPage();
const allPagesBtn = this.bottomToolbar.createEl('button', { text: '⇓ 全部页切图', cls: 'xhs-slice-btn secondary' });
allPagesBtn.onclick = () => this.sliceAllPages();
private createGridCard(parent: HTMLElement, areaClass: string): HTMLDivElement {
return parent.createDiv({ cls: `xhs-card ${areaClass}` });
}
/**
@@ -214,13 +183,13 @@ export class XiaohongshuPreview {
this.articleHTML = articleHTML;
this.currentFile = file;
new Notice('正在分页...');
//new Notice('正在分页...');
// 创建临时容器用于分页
const tempContainer = document.createElement('div');
tempContainer.innerHTML = articleHTML;
tempContainer.style.width = `${this.settings.sliceImageWidth}px`;
tempContainer.classList.add('note-to-mp');
tempContainer.classList.add('note2any');
if (this.currentThemeClass) {
tempContainer.classList.add(this.currentThemeClass);
}
@@ -231,7 +200,7 @@ export class XiaohongshuPreview {
// 在分页前先应用主题与高亮,确保测量使用正确样式
this.applyThemeCSS();
this.pages = await paginateArticle(tempContainer, this.settings);
new Notice(`分页完成:共 ${this.pages.length}`);
//new Notice(`分页完成:共 ${this.pages.length} 页`);
this.currentPageIndex = 0;
// 初次渲染时应用当前主题
@@ -257,7 +226,7 @@ export class XiaohongshuPreview {
const wrapper = this.pageContainer.createDiv({ cls: 'xhs-page-wrapper' });
const classes = ['xhs-page'];
if (this.currentThemeClass) classes.push('note-to-mp');
if (this.currentThemeClass) classes.push('note2any');
const pageElement = wrapper.createDiv({ cls: classes.join(' ') });
renderPage(pageElement, page.content, this.settings);
this.applyPreviewSizing(wrapper, pageElement);
@@ -328,6 +297,7 @@ export class XiaohongshuPreview {
pageElement.style.width = `${actualWidth}px`;
pageElement.style.height = `${actualHeight}px`;
pageElement.style.transform = `scale(${scale})`;
pageElement.style.transformOrigin = 'top left';
pageElement.style.position = 'absolute';
pageElement.style.top = '0';
pageElement.style.left = '0';
@@ -363,7 +333,7 @@ export class XiaohongshuPreview {
* 切换字号(± 按钮)
*/
private async changeFontSize(delta: number): Promise<void> {
this.currentFontSize = Math.max(12, Math.min(36, this.currentFontSize + delta));
this.currentFontSize = Math.max(XHS_FONT_SIZE_MIN, Math.min(XHS_FONT_SIZE_MAX, this.currentFontSize + delta));
this.fontSizeInput.value = String(this.currentFontSize);
await this.repaginateAndRender();
}
@@ -373,9 +343,9 @@ export class XiaohongshuPreview {
*/
private async onFontSizeInputChanged(): Promise<void> {
const val = parseInt(this.fontSizeInput.value, 10);
if (isNaN(val) || val < 12 || val > 36) {
if (isNaN(val) || val < XHS_FONT_SIZE_MIN || val > XHS_FONT_SIZE_MAX) {
this.fontSizeInput.value = String(this.currentFontSize);
new Notice('字号范围: 12-36');
new Notice(`字号范围: ${XHS_FONT_SIZE_MIN}-${XHS_FONT_SIZE_MAX}`);
return;
}
this.currentFontSize = val;
@@ -444,6 +414,14 @@ export class XiaohongshuPreview {
await this.onPublishCallback();
}
}
async refresh(): Promise<void> {
await this.onRefresh();
}
async publish(): Promise<void> {
await this.onPublish();
}
/**
* 全部页切图
@@ -482,7 +460,7 @@ export class XiaohongshuPreview {
private async persistSettings(): Promise<void> {
try {
const plugin = (this.app as any)?.plugins?.getPlugin?.('note-to-mp');
const plugin = (this.app as any)?.plugins?.getPlugin?.('note2any');
if (plugin?.saveSettings) {
await plugin.saveSettings();
}
@@ -513,13 +491,10 @@ export class XiaohongshuPreview {
* 清理资源
*/
destroy(): void {
this.topToolbar = null as any;
this.templateSelect = null as any;
this.previewWidthSelect = null as any;
this.fontSizeInput = null as any;
this.pageContainer = null as any;
this.bottomToolbar = null as any;
this.pageNavigation = null as any;
this.pageNumberInput = null as any;
this.pageTotalLabel = null as any;
this.pages = [];
@@ -535,7 +510,7 @@ export class XiaohongshuPreview {
const theme = this.assetsManager.getTheme(themeName);
const highlight = this.assetsManager.getHighlight(highlightName);
const customCSS = (this.settings.useCustomCss || this.settings.customCSSNote.length>0) ? this.assetsManager.customCSS : '';
const baseCSS = this.settings.baseCSS ? `.note-to-mp {${this.settings.baseCSS}}` : '';
const baseCSS = this.settings.baseCSS ? `.note2any {${this.settings.baseCSS}}` : '';
const css = `${highlight?.css || ''}\n\n${theme?.css || ''}\n\n${baseCSS}\n\n${customCSS}`;
this.styleEl.textContent = css;
this.currentThemeClass = theme?.className || '';
@@ -545,15 +520,15 @@ export class XiaohongshuPreview {
if (!this.articleHTML) return;
const totalBefore = this.pages.length || 1;
const posRatio = (this.currentPageIndex + 0.5) / totalBefore; // 以当前页中心作为相对位置
new Notice('重新分页中...');
//new Notice('重新分页中...');
const tempContainer = document.createElement('div');
tempContainer.innerHTML = this.articleHTML;
tempContainer.style.width = `${this.settings.sliceImageWidth}px`;
tempContainer.style.fontSize = `${this.currentFontSize}px`;
// 字体从全局主题中继承,无需手动指定
tempContainer.classList.add('note-to-mp');
tempContainer.className = this.currentThemeClass ? `note-to-mp ${this.currentThemeClass}` : 'note-to-mp';
tempContainer.classList.add('note2any');
tempContainer.className = this.currentThemeClass ? `note2any ${this.currentThemeClass}` : 'note2any';
document.body.appendChild(tempContainer);
try {
this.pages = await paginateArticle(tempContainer, this.settings);
@@ -564,7 +539,7 @@ export class XiaohongshuPreview {
this.currentPageIndex = 0;
}
this.renderCurrentPage();
new Notice(`重新分页完成:共 ${this.pages.length}`);
//new Notice(`重新分页完成:共 ${this.pages.length} 页`);
} catch (e) {
console.error('重新分页失败', e);
new Notice('重新分页失败');

View File

@@ -84,22 +84,14 @@
.wechat-preview-container:not([style*="display: none"]),
.xiaohongshu-preview-container:not([style*="display: none"]) {
flex: 1;
display: grid !important;
grid-template-rows: auto 1fr;
display: flex !important;
min-height: 0; /* 允许内部滚动区域正确计算高度 */
}
.render-div {
overflow-y: auto;
padding: 10px;
-webkit-user-select: text;
user-select: text;
min-height: 0;
}
/* 文章包裹:模拟公众号编辑器阅读宽度 */
.wechat-article-wrapper {
max-width: 720px;
width: 100%;
max-width: clamp(360px, 80vw, 760px);
margin: 0 auto;
padding: 12px 18px 80px 18px; /* 底部留白方便滚动到底部操作 */
box-sizing: border-box;
@@ -110,19 +102,6 @@
background: transparent;
}
.preview-toolbar {
position: relative;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
gap: 12px;
align-items: center;
min-height: auto;
padding: 8px 12px;
border-bottom: 1px solid #e8eaed;
background: var(--grad-toolbar);
box-shadow: var(--shadow-overlay);
}
.copy-button {
margin-right: 10px;
padding: 6px 14px;
@@ -204,6 +183,53 @@ label:hover { color: var(--c-primary); }
box-shadow: 0 2px 6px rgba(30, 136, 229, 0.2);
}
.nmp-settings-tabs {
display: flex;
gap: 8px;
margin-top: 16px;
border-bottom: 1px solid var(--c-border);
padding-bottom: 8px;
flex-wrap: wrap;
}
.nmp-settings-tab-button {
border: none;
border-radius: 6px;
padding: 6px 14px;
font-size: 13px;
font-weight: 500;
color: var(--c-text-muted);
background: transparent;
cursor: pointer;
transition: all 0.2s ease;
}
.nmp-settings-tab-button:hover {
color: var(--c-primary);
background: rgba(30, 136, 229, 0.08);
}
.nmp-settings-tab-button.is-active {
color: var(--c-primary);
background: white;
box-shadow: var(--shadow-sm);
}
.nmp-settings-panels {
margin-top: 16px;
}
.nmp-settings-panel {
display: none;
gap: 12px;
flex-direction: column;
}
.nmp-settings-panel.is-active {
display: flex;
flex-direction: column;
}
/* focus 规则见与 .upload-input:focus 的组合声明 */
.msg-view {
@@ -312,23 +338,6 @@ label:hover { color: var(--c-primary); }
/* Toolbar 行样式 */
/* =========================================================== */
.toolbar-line {
display: grid;
grid-auto-flow: column;
align-items: center;
gap: 12px;
padding: 8px 12px;
background: white;
border-radius: 6px;
margin: 8px 10px;
box-shadow: var(--shadow-sm);
}
.toolbar-line.flex-wrap {
grid-auto-flow: row;
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
}
.platform-selector-line {
background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%) !important;
border-left: 4px solid var(--c-primary);
@@ -337,7 +346,7 @@ label:hover { color: var(--c-primary); }
/* 平台选择容器:单层 Grid 排列 */
.platform-chooser-container.platform-chooser-grid {
display: grid;
grid-auto-flow: column;
grid-template-columns: auto minmax(160px, 1fr) auto auto;
align-items: center;
gap: 12px;
padding: 8px 12px;
@@ -347,6 +356,16 @@ label:hover { color: var(--c-primary); }
box-shadow: var(--shadow-sm);
}
.platform-chooser-container .toolbar-button {
justify-self: start;
}
@media (max-width: 720px) {
.platform-chooser-container.platform-chooser-grid {
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
}
}
/* =========================================================== */
/* 平台选择器样式 */
/* =========================================================== */
@@ -357,13 +376,125 @@ label:hover { color: var(--c-primary); }
font-weight: 500;
}
/* =========================================================== */
/* 微信公众号预览布局 */
/* =========================================================== */
.wechat-preview-container {
width: 100%;
height: 100%;
display: flex;
padding: 12px;
box-sizing: border-box;
}
.wechat-board {
flex: 1;
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-rows: auto auto auto minmax(0, 1fr);
grid-template-areas:
"account-select account-select account-select account-back-export account-back-export account-back-export"
"cover-select cover-select cover-select cover-select cover-input cover-input"
"style-label style-select highlight-label highlight-select highlight-select highlight-select"
"content content content content content content";
gap: 12px;
background: var(--grad-toolbar);
border-radius: 12px;
padding: 16px;
box-shadow: var(--shadow-sm);
min-height: 0;
}
.wechat-cell {
background: white;
border-radius: 10px;
padding: 12px 16px;
box-shadow: var(--shadow-sm);
display: flex;
align-items: center;
gap: 12px;
}
.wechat-cell[data-area="account-select"] {
grid-area: account-select;
justify-content: flex-start;
}
.wechat-cell[data-area="account-back-export"] {
grid-area: account-back-export;
justify-content: flex-center;
}
.wechat-cell[data-area="account-select"] .style-label {
white-space: nowrap;
}
.wechat-cell[data-area="account-select"] .wechat-select {
width: 100%;
}
.wechat-cell[data-area="account-back-export"] .wechat-action-button { white-space: nowrap; }
.wechat-cell[data-area="cover-select"] {
grid-area: cover-select;
justify-content: flex-start;
gap: 18px;
}
.wechat-cell[data-area="cover-input"] { grid-area: cover-input; }
.wechat-cell[data-area="cover-select"] label {
white-space: nowrap;
}
.wechat-cell[data-area="cover-input"] .upload-input {
margin-left: 0;
width: 100%;
}
.wechat-cell[data-area="style-label"] { grid-area: style-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="style-select"] { grid-area: style-select; width: 100%; }
.wechat-cell[data-area="highlight-label"] { grid-area: highlight-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="highlight-select"] { grid-area: highlight-select; width: 100%; }
.wechat-cell[data-area="style-select"] .style-select,
.wechat-cell[data-area="style-select"] .wechat-style-select,
.wechat-cell[data-area="highlight-select"] .style-select,
.wechat-cell[data-area="highlight-select"] .wechat-style-select {
width: 100%;
min-width: 0;
}
.wechat-cell[data-area="content"] {
grid-area: content;
overflow-y: auto;
padding: 10px;
-webkit-user-select: text;
user-select: text;
min-height: 0;
background: white;
border-radius: 12px;
box-shadow: var(--shadow-sm);
display: block;
}
.wechat-cell-placeholder {
background: transparent;
box-shadow: none;
padding: 0;
}
.wechat-cell-placeholder .toolbar-button {
display: none;
}
/* =========================================================== */
/* 微信公众号选择器样式 */
/* =========================================================== */
.wechat-select {
padding: 6px 12px;
min-width: 200px;
min-width: 100px;
width: 100%;
}
/* =========================================================== */
@@ -387,17 +518,6 @@ label:hover { color: var(--c-primary); }
.toolbar-button.purple-gradient:hover { box-shadow: var(--shadow-purple-4); }
/* =========================================================== */
/* 分隔线样式 */
/* =========================================================== */
.toolbar-separator {
width: 1px;
height: 24px;
background: var(--c-border);
margin: 0 4px;
}
/* =========================================================== */
/* Doc Modal 样式 */
/* =========================================================== */
@@ -460,38 +580,138 @@ label:hover { color: var(--c-primary); }
.xiaohongshu-preview-container {
width: 100%;
height: 100%;
display: flex;
padding: 12px;
box-sizing: border-box;
}
.xhs-preview-container:not([style*="display: none"]) {
display: grid !important;
grid-template-rows: auto 1fr auto;
height: 100%;
.xhs-board {
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-rows: auto auto auto 1fr auto;
grid-template-areas:
"template template preview preview font font"
"content content content content content content"
"content content content content content content"
"content content content content content content"
"pagination pagination pagination slice slice slice";
gap: 5px;
width: 100%;
background: var(--grad-xhs-bg);
border-radius: 12px;
padding: 5px;
box-shadow: var(--shadow-sm);
min-height: 0;
}
.xhs-page-container {
overflow-y: auto;
overflow-x: hidden;
display: grid;
align-content: start;
justify-content: center;
padding: 0px;
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
min-height: 0; /* 允许子项正确收缩和滚动 */
.xhs-card {
display: flex;
align-items: center;
gap: 10px;
background: white;
border-radius: 10px;
padding: 10px 14px;
box-shadow: var(--shadow-sm);
}
.xhs-label {
font-size: 13px;
font-weight: 600;
color: var(--c-text-muted);
white-space: nowrap;
}
.xhs-select {
flex: 1 1 auto;
padding: 6px 10px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: white;
font-size: 13px;
cursor: pointer;
max-width: 100px;
transition: border-color 0.2s ease;
}
.xhs-select:hover { border-color: var(--c-primary); }
.xhs-select:focus {
outline: none;
border-color: var(--c-primary);
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1);
}
.font-size-group {
display: grid;
grid-auto-flow: column;
align-items: center;
gap: 6px;
padding: 2px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: #f7f9fb;
}
.font-size-btn {
width: 26px;
height: 26px;
border: none;
background: transparent;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
color: #5f6368;
transition: background 0.2s ease;
}
.font-size-btn:hover { background: #eaf1fe; }
.font-size-input {
width: 35px;
border: none;
background: transparent;
text-align: center;
font: inherit;
color: inherit;
}
.font-size-input:focus { outline: none; }
.xhs-area-template { grid-area: template; }
.xhs-area-preview { grid-area: preview; }
.xhs-area-font {
grid-area: font;
flex-wrap: nowrap;
}
.xhs-area-pagination { grid-area: pagination; justify-content: center; gap: 16px; }
.xhs-area-slice { grid-area: slice; justify-content: center; gap: 16px; }
.xhs-area-content {
grid-area: content;
background: white;
border-radius: 12px;
padding: 0;
box-shadow: var(--shadow-sm);
display: flex;
}
.xhs-page-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
border-radius: 12px;
min-height: 0;
position: relative;
}
/* 小红书单页包裹器:为缩放后的页面预留正确的布局空间 */
.xhs-page-wrapper {
margin: 0px auto;
margin: 0 auto;
position: relative;
overflow: hidden;
}
/* 小红书单页样式:实际尺寸 1080×1440通过 scale 缩放到 540×720 */
.xhs-page {
/* 实际尺寸与缩放由代码在运行时设置 */
transform-origin: top left;
background: white;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
border-radius: 8px;
@@ -502,87 +722,10 @@ label:hover { color: var(--c-primary); }
height: auto;
}
.xhs-top-toolbar {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
align-items: center;
gap: 12px;
padding: 8px 12px;
background: var(--grad-toolbar);
border-bottom: 1px solid #e8eaed;
box-shadow: var(--shadow-overlay);
}
.toolbar-label {
font-size: 11px;
color: var(--c-text-muted);
font-weight: 500;
white-space: nowrap;
}
.xhs-select {
padding: 4px 8px;
border: 1px solid var(--c-border);
border-radius: 4px;
background: white;
font-size: 11px;
cursor: pointer;
transition: border-color 0.2s ease;
}
.xhs-select:hover {
border-color: var(--c-primary);
}
.xhs-select:focus {
outline: none;
border-color: var(--c-primary);
}
.font-size-group {
.xhs-pagination {
display: grid;
grid-auto-flow: column;
align-items: center;
gap: 6px;
background: white;
border: 1px solid var(--c-border);
border-radius: 4px;
padding: 2px;
}
.font-size-btn {
width: 24px;
height: 24px;
border: none;
background: transparent;
border-radius: 3px;
cursor: pointer;
font-size: 16px;
color: #5f6368;
transition: background 0.2s ease;
}
.font-size-btn:hover {
background: #f1f3f4;
}
.font-size-display {
min-width: 24px;
text-align: center;
font-size: 12px;
color: #202124;
font-weight: 500;
}
.xhs-page-navigation {
display: grid;
grid-auto-flow: column;
justify-content: center;
align-items: center;
gap: 16px;
padding: 12px;
background: white;
border-bottom: 1px solid #e8eaed;
}
.xhs-nav-btn {
@@ -614,7 +757,7 @@ label:hover { color: var(--c-primary); }
}
.xhs-page-number-input {
width: 56px;
width: 35px;
padding: 4px 6px;
text-align: center;
border: 1px solid var(--c-border);
@@ -638,17 +781,6 @@ label:hover { color: var(--c-primary); }
user-select: none;
}
.xhs-bottom-toolbar {
display: grid;
grid-auto-flow: column;
justify-content: center;
gap: 12px;
padding: 12px 16px;
background: var(--grad-toolbar-bottom);
border-top: 1px solid #e8eaed;
box-shadow: 0 -2px 4px rgba(0,0,0,0.04);
}
.xhs-slice-btn {
padding: 8px 20px;
background: var(--grad-primary);

829
styles.css.bk Normal file
View File

@@ -0,0 +1,829 @@
/* styles.css — 全局样式表,用于渲染及导出样式。 */
/* =========================================================== */
/* UI 样式 */
/* 共用样式与去重 */
/* =========================================================== */
/* 主题变量统一常用色值/阴影/渐变 */
:root {
--c-bg: #ffffff;
--c-border: #dadce0;
--c-text-muted: #5f6368;
--c-primary: #1e88e5;
--c-primary-dark: #1565c0;
--c-purple: #667eea;
--c-purple-dark: #764ba2;
--c-blue-2: #42a5f5;
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
--shadow-overlay: 0 2px 4px rgba(0,0,0,0.04);
--shadow-primary-2: 0 2px 6px rgba(30, 136, 229, 0.3);
--shadow-primary-4: 0 4px 8px rgba(30, 136, 229, 0.4);
--shadow-purple-2: 0 2px 6px rgba(102, 126, 234, 0.3);
--shadow-purple-4: 0 4px 8px rgba(102, 126, 234, 0.4);
--grad-primary: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
--grad-purple: linear-gradient(135deg, var(--c-purple) 0%, var(--c-purple-dark) 100%);
--grad-blue: linear-gradient(135deg, var(--c-blue-2) 0%, var(--c-primary) 100%);
--grad-toolbar: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
--grad-toolbar-bottom: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
--grad-xhs-bg: linear-gradient(135deg, #f5f7fa 0%, #e8eaf6 100%);
}
/* 通用按钮外观(不含背景与尺寸) */
.copy-button,
.refresh-button,
.toolbar-button,
.msg-ok-btn,
.xhs-slice-btn {
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
}
/* 通用按钮 hover 的位移效果(各自保留独立阴影) */
.copy-button:hover,
.refresh-button:hover,
.toolbar-button:hover,
.msg-ok-btn:hover {
transform: translateY(-1px);
}
/* 下拉选择的通用外观(各自保留尺寸差异) */
.platform-select,
.wechat-select,
.style-select {
border: 1px solid var(--c-border);
border-radius: 6px;
background: white;
font-size: 13px;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: var(--shadow-sm);
}
/* 平台与公众号选择的相同 hover/focus 效果style-select 单独增强) */
.platform-select:hover,
.wechat-select:hover { border-color: var(--c-primary); }
.platform-select:focus,
.wechat-select:focus { outline: none; border-color: var(--c-primary); }
.note-preview {
grid-template-rows: auto 1fr;
grid-template-columns: 1fr;
display: grid;
min-height: 100%;
width: 100%;
height: 100%;
background-color: var(--c-bg);
}
/* 预览内部平台容器需要可伸缩: */
.wechat-preview-container:not([style*="display: none"]),
.xiaohongshu-preview-container:not([style*="display: none"]) {
flex: 1;
display: flex !important;
min-height: 0; /* 允许内部滚动区域正确计算高度 */
}
/* 文章包裹:模拟公众号编辑器阅读宽度 */
.wechat-article-wrapper {
width: 100%;
max-width: clamp(360px, 80vw, 760px);
margin: 0 auto;
padding: 12px 18px 80px 18px; /* 底部留白方便滚动到底部操作 */
box-sizing: border-box;
}
/* 若内部 section.note-to-mp 主题没有撑开,确保文本可见基色 */
.wechat-article-wrapper .note-to-mp {
background: transparent;
}
.copy-button {
margin-right: 10px;
padding: 6px 14px;
background: var(--grad-primary);
color: white;
font-size: 13px;
box-shadow: var(--shadow-primary-2);
}
.copy-button:hover { box-shadow: var(--shadow-primary-4); }
.refresh-button {
margin-right: 10px;
padding: 6px 14px;
background: var(--grad-purple);
color: white;
font-size: 13px;
box-shadow: var(--shadow-purple-2);
}
.refresh-button:hover { box-shadow: var(--shadow-purple-4); }
.upload-input {
margin-left: 10px;
padding: 6px 10px;
border: 1px solid var(--c-border);
border-radius: 6px;
font-size: 13px;
transition: all 0.2s ease;
}
.upload-input[type="file"] {
cursor: pointer;
}
.upload-input:focus,
.style-select:focus {
outline: none;
border-color: var(--c-primary);
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1);
}
/* 单选按钮样式 */
.input-style[type="radio"] {
width: 16px;
height: 16px;
margin: 0 6px 0 0;
cursor: pointer;
accent-color: var(--c-primary);
}
/* Label 标签样式 */
label {
font-size: 13px;
color: var(--c-text-muted);
cursor: pointer;
user-select: none;
transition: color 0.2s ease;
}
label:hover { color: var(--c-primary); }
.style-label {
margin-right: 10px;
font-size: 13px;
color: var(--c-text-muted);
font-weight: 500;
white-space: nowrap;
}
.style-select {
margin-right: 10px;
width: 120px;
padding: 6px 10px;
}
.style-select:hover {
border-color: var(--c-primary);
box-shadow: 0 2px 6px rgba(30, 136, 229, 0.2);
}
/* focus 规则见与 .upload-input:focus 的组合声明 */
.msg-view {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--background-primary);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 18px;
z-index: 9999;
display: none;
}
.msg-title {
margin-bottom: 20px;
max-width: 90%;
}
.msg-ok-btn {
padding: 10px 24px;
margin: 0 8px;
background: var(--grad-primary);
color: white;
font-size: 14px;
box-shadow: var(--shadow-primary-2);
min-width: 80px;
}
.msg-ok-btn:hover { box-shadow: var(--shadow-primary-4); }
.msg-ok-btn:active {
transform: translateY(0);
}
.note-mpcard-wrapper {
margin: 20px 20px;
background-color: rgb(250, 250, 250);
padding: 10px 20px;
border-radius: 10px;
}
.note-mpcard-content {
display: grid;
grid-auto-flow: column;
align-items: center;
}
.note-mpcard-headimg {
border: none !important;
border-radius: 27px !important;
box-shadow: none !important;
width: 54px !important;
height: 54px !important;
margin: 0 !important;
}
.note-mpcard-info {
margin-left: 10px;
}
.note-mpcard-nickname {
font-size: 17px;
font-weight: 500;
color: rgba(0, 0, 0, 0.9);
}
.note-mpcard-signature {
font-size: 14px;
color: rgba(0, 0, 0, 0.55);
}
.note-mpcard-foot {
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #ececec;
font-size: 14px;
color: rgba(0, 0, 0, 0.3);
}
.loading-wrapper {
display: grid;
width: 100%;
height: 100%;
place-items: center;
}
.loading-spinner {
width: 50px; /* 可调整大小 */
height: 50px;
border: 4px solid #fcd6ff; /* 底色,浅灰 */
border-top: 4px solid #bb0cdf; /* 主色,蓝色顶部产生旋转感 */
border-radius: 50%; /* 圆形 */
animation: spin 1s linear infinite; /* 旋转动画 */
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* =========================================================== */
/* Toolbar 行样式 */
/* =========================================================== */
.platform-selector-line {
background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%) !important;
border-left: 4px solid var(--c-primary);
}
/* 平台选择容器:单层 Grid 排列 */
.platform-chooser-container.platform-chooser-grid {
display: grid;
grid-template-columns: auto minmax(160px, 1fr) auto auto;
align-items: center;
gap: 12px;
padding: 8px 12px;
background: white; /* 被 .platform-selector-line 的背景覆写 */
border-radius: 6px;
margin: 8px 10px;
box-shadow: var(--shadow-sm);
}
.platform-chooser-container .toolbar-button {
justify-self: start;
}
@media (max-width: 720px) {
.platform-chooser-container.platform-chooser-grid {
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
}
}
/* =========================================================== */
/* 平台选择器样式 */
/* =========================================================== */
.platform-select {
padding: 6px 12px;
min-width: 150px;
font-weight: 500;
}
/* =========================================================== */
/* 微信公众号预览布局 */
/* =========================================================== */
.wechat-preview-container {
width: 100%;
height: 100%;
display: flex;
padding: 12px;
box-sizing: border-box;
}
.wechat-board {
flex: 1;
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-rows: auto auto auto minmax(0, 1fr);
grid-template-areas:
"account-label account-select account-select account-select account-backend account-export"
"cover-label cover-default cover-upload cover-input cover-input cover-input"
"style-label style-select highlight-label highlight-select highlight-select highlight-select"
"content content content content content content";
gap: 12px;
background: var(--grad-toolbar);
border-radius: 12px;
padding: 16px;
box-shadow: var(--shadow-sm);
min-height: 0;
}
.wechat-cell {
background: white;
border-radius: 10px;
padding: 12px 16px;
box-shadow: var(--shadow-sm);
display: flex;
align-items: center;
gap: 12px;
}
.wechat-cell[data-area="account-label"] { grid-area: account-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="account-select"] { grid-area: account-select; }
.wechat-cell[data-area="account-backend"] { grid-area: account-backend; justify-content: flex-end; }
.wechat-cell[data-area="account-export"] { grid-area: account-export; justify-content: flex-end; }
.wechat-cell[data-area="account-select"] .wechat-select {
width: 100%;
}
.wechat-cell[data-area="account-backend"] .wechat-action-button,
.wechat-cell[data-area="account-export"] .wechat-action-button {
white-space: nowrap;
}
.wechat-cell[data-area="cover-label"] { grid-area: cover-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="cover-default"] { grid-area: cover-default; gap: 8px; }
.wechat-cell[data-area="cover-upload"] { grid-area: cover-upload; gap: 8px; }
.wechat-cell[data-area="cover-input"] { grid-area: cover-input; }
.wechat-cell[data-area="cover-default"] label,
.wechat-cell[data-area="cover-upload"] label {
white-space: nowrap;
}
.wechat-cell[data-area="cover-input"] .upload-input {
margin-left: 0;
width: 100%;
}
.wechat-cell[data-area="style-label"] { grid-area: style-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="style-select"] { grid-area: style-select; width: 100%; }
.wechat-cell[data-area="highlight-label"] { grid-area: highlight-label; white-space: nowrap; justify-content: flex-start; }
.wechat-cell[data-area="highlight-select"] { grid-area: highlight-select; width: 100%; }
.wechat-cell[data-area="style-select"] .style-select,
.wechat-cell[data-area="style-select"] .wechat-style-select,
.wechat-cell[data-area="highlight-select"] .style-select,
.wechat-cell[data-area="highlight-select"] .wechat-style-select {
width: 100%;
min-width: 0;
}
.wechat-cell[data-area="content"] {
grid-area: content;
overflow-y: auto;
padding: 10px;
-webkit-user-select: text;
user-select: text;
min-height: 0;
background: white;
border-radius: 12px;
box-shadow: var(--shadow-sm);
display: block;
}
.wechat-cell-placeholder {
background: transparent;
box-shadow: none;
padding: 0;
}
.wechat-cell-placeholder .toolbar-button {
display: none;
}
/* =========================================================== */
/* 微信公众号选择器样式 */
/* =========================================================== */
.wechat-select {
padding: 6px 12px;
min-width: 100px;
width: 100%;
}
/* =========================================================== */
/* 按钮样式 */
/* =========================================================== */
.toolbar-button {
padding: 6px 14px;
background: var(--grad-primary);
color: white;
font-size: 13px;
box-shadow: var(--shadow-primary-2);
}
.toolbar-button:hover { box-shadow: var(--shadow-primary-4); }
.toolbar-button.purple-gradient {
background: var(--grad-purple);
box-shadow: var(--shadow-purple-2);
}
.toolbar-button.purple-gradient:hover { box-shadow: var(--shadow-purple-4); }
/* =========================================================== */
/* Doc Modal 样式 */
/* =========================================================== */
.doc-modal {
width: 640px;
height: 720px;
}
.doc-modal-content {
display: grid;
grid-template-rows: auto auto 1fr;
row-gap: 8px;
min-height: 0;
}
.doc-modal-title {
margin-top: 0.5em;
}
.doc-modal-desc {
margin-bottom: 1em;
-webkit-user-select: text;
user-select: text;
}
.doc-modal-iframe {
min-height: 0;
}
/* =========================================================== */
/* Setting Tab 帮助文档样式 */
/* =========================================================== */
.setting-help-section {
display: grid;
grid-auto-flow: column;
align-items: center;
column-gap: 10px;
}
.setting-help-title {
margin-right: 10px;
}
/* =========================================================== */
/* Xiaohongshu WebView 样式 */
/* =========================================================== */
.xhs-webview {
display: none;
width: 1200px;
height: 800px;
}
/* =========================================================== */
/* Xiaohongshu Preview View 样式 */
/* =========================================================== */
.xiaohongshu-preview-container {
width: 100%;
height: 100%;
display: flex;
padding: 12px;
box-sizing: border-box;
}
.xhs-board {
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-rows: auto auto auto 1fr auto;
grid-template-areas:
"template template preview preview font font"
"content content content content content content"
"content content content content content content"
"content content content content content content"
"pagination pagination pagination slice slice slice";
gap: 5px;
width: 100%;
background: var(--grad-xhs-bg);
border-radius: 12px;
padding: 5px;
box-shadow: var(--shadow-sm);
min-height: 0;
}
.xhs-card {
display: flex;
align-items: center;
gap: 10px;
background: white;
border-radius: 10px;
padding: 10px 14px;
box-shadow: var(--shadow-sm);
}
.xhs-label {
font-size: 13px;
font-weight: 600;
color: var(--c-text-muted);
white-space: nowrap;
}
.xhs-select {
flex: 1 1 auto;
padding: 6px 10px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: white;
font-size: 13px;
cursor: pointer;
max-width: 100px;
transition: border-color 0.2s ease;
}
.xhs-select:hover { border-color: var(--c-primary); }
.xhs-select:focus {
outline: none;
border-color: var(--c-primary);
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1);
}
.font-size-group {
display: grid;
grid-auto-flow: column;
align-items: center;
gap: 6px;
padding: 2px;
border: 1px solid var(--c-border);
border-radius: 6px;
background: #f7f9fb;
}
.font-size-btn {
width: 26px;
height: 26px;
border: none;
background: transparent;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
color: #5f6368;
transition: background 0.2s ease;
}
.font-size-btn:hover { background: #eaf1fe; }
.font-size-input {
width: 35px;
border: none;
background: transparent;
text-align: center;
font: inherit;
color: inherit;
}
.font-size-input:focus { outline: none; }
.xhs-area-template { grid-area: template; }
.xhs-area-preview { grid-area: preview; }
.xhs-area-font {
grid-area: font;
flex-wrap: nowrap;
}
.xhs-area-pagination { grid-area: pagination; justify-content: center; gap: 16px; }
.xhs-area-slice { grid-area: slice; justify-content: center; gap: 16px; }
.xhs-area-content {
grid-area: content;
background: white;
border-radius: 12px;
padding: 0;
box-shadow: var(--shadow-sm);
display: flex;
}
.xhs-page-container {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
border-radius: 12px;
min-height: 0;
position: relative;
}
.xhs-page-wrapper {
margin: 0 auto;
position: relative;
overflow: hidden;
}
.xhs-page {
background: white;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
border-radius: 8px;
}
.xhs-page img {
max-width: 100%;
height: auto;
}
.xhs-pagination {
display: grid;
grid-auto-flow: column;
align-items: center;
}
.xhs-nav-btn {
width: 36px;
height: 36px;
border: 1px solid var(--c-border);
border-radius: 50%;
cursor: pointer;
font-size: 20px;
background: white;
color: #5f6368;
transition: all 0.2s ease;
box-shadow: var(--shadow-sm);
}
.xhs-nav-btn:hover {
background: var(--grad-primary);
color: white;
border-color: var(--c-primary);
}
.xhs-page-indicator {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 14px;
font-weight: 500;
color: #202124;
}
.xhs-page-number-input {
width: 35px;
padding: 4px 6px;
text-align: center;
border: 1px solid var(--c-border);
border-radius: 6px;
background: white;
color: inherit;
font: inherit;
box-shadow: inset 0 1px 2px rgba(0,0,0,0.08);
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.xhs-page-number-input:focus {
outline: none;
border-color: var(--c-primary);
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.15);
}
.xhs-page-number-total {
font-size: 14px;
color: #5f6368;
user-select: none;
}
.xhs-slice-btn {
padding: 8px 20px;
background: var(--grad-primary);
color: white;
font-size: 13px;
box-shadow: var(--shadow-primary-2);
}
.xhs-slice-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(30, 136, 229, 0.4);
}
.xhs-slice-btn.secondary {
background: var(--grad-blue);
box-shadow: 0 2px 6px rgba(66, 165, 245, 0.3);
}
.xhs-slice-btn.secondary:hover {
box-shadow: 0 4px 12px rgba(66, 165, 245, 0.4);
}
/* =========================================================== */
/* Xiaohongshu Login Modal 样式 */
/* =========================================================== */
.xiaohongshu-login-modal {
width: 400px;
padding: 20px;
}
.xhs-login-title {
text-align: center;
margin-bottom: 20px;
color: #ff4757;
}
.xhs-login-desc {
text-align: center;
color: #666;
margin-bottom: 30px;
}
.xhs-code-container {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 10px;
margin-bottom: 20px;
}
.xhs-code-label {
min-width: 80px;
}
.xhs-code-input-wrapper {
flex: 1;
}
.xhs-input-full {
width: 100%;
font-size: 16px;
}
.xhs-send-code-btn {
min-width: 120px;
margin-left: 10px;
}
.xhs-status-message {
min-height: 30px;
margin-bottom: 20px;
text-align: center;
font-size: 14px;
}
.xhs-status-message.success {
color: #27ae60;
}
.xhs-status-message.error {
color: #e74c3c;
}
.xhs-status-message.info {
color: #3498db;
}
.xhs-button-container {
display: grid;
grid-auto-flow: column;
justify-content: center;
gap: 15px;
margin-top: 20px;
}
.xhs-login-btn {
min-width: 100px;
}

170
t2.html Normal file
View File

@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>CSS Grid 5列布局示例</title>
<style>
:root{
--gap: 12px;
--radius: 12px;
--bg: gray;
--panel: #111827;
--muted: #1f2937;
--text: #e5e7eb;
--sub: #9ca3af;
--accent: #3b82f6;
}
*{box-sizing: border-box}
body{
margin:0;
min-height:100vh;
background: var(--bg);
color: var(--text);
font: 15px/1.6 system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial;
display: flex;
flex-direction: column;
}
.app{
flex: 1;
display: flex;
flex-direction: column;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.board{
flex: 1;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: auto auto 1fr auto;
grid-template-areas:
"label1_list1 label1_list1 label1_list1 btnA btnB"
"label2_list2 label2_list2 label3_list3 label3_list3 label4"
"content content content content content"
"component component component btnC btnD";
gap: var(--gap);
background: var(--panel);
border-radius: 12px;
padding: 16px;
min-height: 0;
}
.card{
background: var(--muted);
border-radius: var(--radius);
padding: 10px;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
min-height: 40px;
}
.label{
color: var(--sub);
font-weight: 600;
white-space: nowrap;
flex-shrink: 0;
}
.select{
flex: 1 1 auto;
background: #0b1220;
border: 1px solid #0f1a30;
border-radius: 8px;
padding: 6px 8px;
color: var(--text);
width: 100%;
}
.btn{
background: var(--accent);
color: white;
border: 0;
border-radius: 8px;
padding: 10px 20px;
font-weight: 600;
cursor: pointer;
text-align: center;
transition: all 0.2s ease;
}
.btn:hover{
background: #2563eb; /* 深蓝色 hover */
box-shadow: 0 4px 8px rgba(0,0,0,0.25);
}
.btn:active{
transform: translateY(1px);
}
/* 让按钮所在卡片居中对齐 */
.btnA, .btnB, .btnC, .btnD{
justify-content: center !important;
}
.content{
grid-area: content;
background: #0b1020;
border: 1px dashed #223253;
border-radius: 12px;
padding: 18px;
min-height: 0;
}
.label1_list1{ grid-area: label1_list1; }
.label2_list2{ grid-area: label2_list2; }
.label3_list3{ grid-area: label3_list3; }
.btnA { grid-area: btnA; }
.btnB { grid-area: btnB; }
.label4{ grid-area: label4; }
.component{ grid-area: component; }
.btnC { grid-area: btnC; }
.btnD { grid-area: btnD; }
</style>
</head>
<body>
<div class="app">
<h1>Grid 5列布局 Demo</h1>
<section class="board">
<div class="card label1_list1">
<span class="label">发布平台</span>
<select class="select">
<option>公众号</option>
<option>小红书</option>
</select>
</div>
<div class="card btnA"><button class="btn">刷新</button></div>
<div class="card btnB"><button class="btn">发布</button></div>
<div class="card label2_list2">
<span class="label">模版</span>
<select class="select">
<option>模版 1</option>
<option>模版 2</option>
</select>
</div>
<div class="card label3_list3">
<span class="label">预览宽度</span>
<select class="select">
<option>1080px</option>
<option>720px</option>
<option>540px</option>
<option>360px</option>
</select>
</div>
<div class="card label4">调节文字大小组件</div>
<div class="content">小红书预览区域</div>
<div class="card component">页面选择组件</div>
<div class="card btnC"><button class="btn">按钮</button></div>
<div class="card btnD"><button class="btn">按钮</button></div>
</section>
</div>
</body>
</html>

View File

@@ -1,19 +1,19 @@
# todo list
# todo list & recording
## 功能
1. 实现markdown预览页面切图功能预览页面是以完成渲染的页面生成一整张长图。再按文章顺序裁剪为图片(png格式)。(v1.3.1)
- 长图宽度为1080可配置。切图图片横竖比例3:4图片宽度保持与长图相同。
- 横竖比例和图片宽像素可配置。
- 标题取frontmatter的title属性。
- 图片保存路径可配置,默认为/Users/gavin/note2mp/images/xhs。
- 图片保存路径可配置,默认为/Users/gavin/note2any/images/xhs。
- 图片名取frontmatter的slug属性如: slug: mmm文章长图命名为mmm.png如切为3张图片则切图图片名按顺序依次为mmm_1.png,mmm_2.png,mmm_3.png
- 文章预览中增加“切图”按钮,点击执行预览文章的切图操作。
2. 说明/修改/增加:
- 发布平台选"小红书"时,保留“刷新”,“发布到小红书”,去掉“切图”按钮,用"当前页切图"和"全部页切图"替代切图按钮和功能。
@@ -56,14 +56,40 @@
- 点击"全部页切图"把所有html页面转为png图片图片保存路径和命名按此前设置。
3. 目前xhs模式发布功能未实现因为没有登录。
整合xhs登陆和发布功能。![登录项目](https://biboer.cn/gitea/gavin/xhslogin/src/branch/main/README.md)
- 在“用户配置”tab中增加“小红书用户名”配置项默认13357108011。 **后续可能需要维护多账号**
- xhslogin项目XHS_PHONE=13357108011 XHS_AUTO_CLOSE=1 npm run publish -- --title "恢复功能测试" --content "验证恢复核心功能后保留优化的代码" --images "/Users/gavin/myweb/static/img/ibook笔记.png" --visibility private --collection 自嗨 --timestamp
其中:
- 参数XHS_PHONE为“小红书用户名”配置项。
- title取markdown文章的title
- content取markdown文章frontmatter中的description信息如果没有description或内容为空取markdown正文前2段段以空行隔离不超过300字[n]段1+段2>n取段1段1+段2+段3>n取段1段2 ……)
- images取小红书切图结果按文章次序。
- visibility在小红书模式下预览页的工具栏中增加"公开"checkbox默认为不选即private。
- collection在小红书模式下预览页的工具栏中增加下拉框选择下拉框内容从登录小红书自动获取。
- timestamp是调试使用默认使用
❓ 重构后无法运行原因是obsidian中playwright环境没有。
❌ 要用xhslogin 的 Playwright 逻辑,就必须把 Playwright 当成外部依赖加载(运行前安装 playwright 和浏览器内核)。 如果一定要彻底摆脱 Playwright只能回到 webview 方案,重新实现一次自动化流程,与其说“利用现成 Chromium”不如说“自己写网页自动化框架”工作量很大。
**改变思路**
xhslogin改造成MCP server部署在远端服务器上。插件中只要实现mcp client就可以了。
这样xhslogin项目没有必要整合到note2any中。
4. 选中内容,右键发布到不同平台。发布时调用渲染,发布到特定的栏目中,比如网站中某个区块的“闪念集”。
## 问题
1. "发布平台"首次选“小红书”时,预览页面没有加载当前文章。
2. 顶部按钮适应窗口宽度,超出窗口,折行显示。
3. 小红书模式html分页预览不是从顶部开始显示显示不完整。
小红书模式,预览窗口似乎只显示了一部分?上面部分被挡住了吗?
参考微信公众号模式下的预览窗口,不同点在于小红书模式下,每页的宽高比按配置要求
3. 小红书模式问题:
- html分页预览不是从顶部开始显示显示不完整
- 预览窗口似乎只显示了一部分?上面部分被挡住了吗?
- 参考微信公众号模式下的预览窗口,不同点在于小红书模式下,每页的宽高比按配置要求。
4. 修改:
- 公共部分独立出来如“发布平台”放在新建platform-choose.ts中“发布平台”选择切换平台逻辑放在该模块中便于以后其他平台扩展。
@@ -103,17 +129,44 @@ SOLVEobsidian控制台打印信息定位在哪里阻塞AI修复。
问题:
- 字变大时,一页的内容放不下,重新分页应该会增加页数。但现在重新分页当前页放不下的内容只是被剪掉了。
- 表格显示不完整。
9. styles.css中有很多冗余。改为grid布局。部分完成这部分需要后面**手动调整**重构。🧶 ♻️ ❇️
问题:小红书预览布局有问题❓
小红书布局改为grid但平台选择器部分没有完成修改。
保持微信和小红书页面一致性都用grid重构复用css样式代码。
10. 新建docs文件夹把除了README和todolist以外的markdown文件放到docs中。
11. `![img](/img/img.png)` -- 不应该渲染为图片链接
## 经验
1. 在不确定AI是否理解或者需求是否准确的情况下先用chat模式提问看回答确定AI理解是否准确。
尤其对于较大规模的重构需求,这点很重要‼️ 。
1. 在不确定AI是否理解或者需求是否准确的情况下先用codex chat模式提问看回答确定AI理解是否准确。
尤其对于较大规模的重构需求,这点很重要 ‼️ 。
例如:
这个思路有问题。我提供命令行只是对参数做说明,这些参数实际上是函数参数。
我需要把xhslogin的功能代码无缝的整合进现有项目中而不是通过命令行传参的方式实现。
这么做的同时,保持结构和模块清晰。
请再提供思路,我来审核下。
2. 复杂页面codex生成的css可能无比复杂不便于维护修改。
自己写布局demo原型让codex参考布局修改(原来元素美化的css可保留)。
demo原型可以手绘后拍照让chatgpt生成在此基础上自己修改。
## 优化
1. 全量扫描系统,从设计、结构、冗余度、优雅、可维护性方便,检查是否有优化的地方。
2. 后续在主题切换和使用上的独立性和便捷性。
## 思路
1. 网上图片模版让AI快速生成css themes主题。快速套用。‼
**样式和功能必须结构样式必须可以0基础快速选择让用户可以选择足够多样式(AI生成)。**

View File

@@ -0,0 +1,48 @@
import { promises as fs } from "fs";
// Esbuild plugin that optionally obfuscates the emitted bundle with javascript-obfuscator.
export default function javascriptObfuscatorPlugin(obfuscatorOptions = {}) {
let obfuscatorPromise;
const loadObfuscator = async () => {
if (!obfuscatorPromise) {
obfuscatorPromise = import("javascript-obfuscator")
.then((module) => module.default ?? module)
.catch((error) => {
console.warn("[esbuild] javascript-obfuscator unavailable, skipping obfuscation.", error);
return null;
});
}
return obfuscatorPromise;
};
// Default to preserving line breaks unless explicitly overridden.
if (typeof obfuscatorOptions.compact === "undefined") {
obfuscatorOptions.compact = false;
}
return {
name: "javascript-obfuscator",
setup(build) {
build.onEnd(async (result) => {
if (result.errors.length) return;
const outfile = build.initialOptions.outfile;
if (!outfile) return;
try {
const obfuscator = await loadObfuscator();
if (!obfuscator?.obfuscate) return;
const source = await fs.readFile(outfile, "utf8");
const obfuscatedCode = obfuscator
.obfuscate(source, obfuscatorOptions)
.getObfuscatedCode();
await fs.writeFile(outfile, obfuscatedCode, "utf8");
} catch (error) {
console.warn("[esbuild] javascript-obfuscator plugin failed, continuing without obfuscation.", error);
}
});
},
};
}

View File

@@ -1,3 +1,5 @@
{
"1.3.7": "1.4.5"
"1.3.7": "1.4.5",
"1.3.12": "1.4.5",
"1.4.0": "1.4.5"
}

4
x
View File

@@ -105,8 +105,8 @@
box-sizing: border-box;
}
/* 若内部 section.note-to-mp 主题没有撑开,确保文本可见基色 */
.wechat-article-wrapper .note-to-mp {
/* 若内部 section.note2any 主题没有撑开,确保文本可见基色 */
.wechat-article-wrapper .note2any {
background: transparent;
}