Compare commits

...

20 commits
1.0.13 ... main

Author SHA1 Message Date
Yeban8090
5a68d36341
Merge pull request #29 from Yeban8090/1.0.19
1.0.19
2025-08-21 10:59:56 +08:00
yeban
e8651dd050 插件视图创建优化 2025-08-21 10:54:54 +08:00
yeban
5400e81d85 插件视图创建优化 2025-08-21 10:53:55 +08:00
Yeban8090
b900096ad5 发布1.0.18 2025-06-15 13:00:38 +08:00
Yeban8090
66073354a1
Merge pull request #26 from bushnerd/main
Add heading level option for content splitting
2025-06-15 12:36:00 +08:00
bushnerd
1b6e0a1bb0 Add heading level option for content splitting 2025-06-15 11:59:59 +08:00
bushnerd
aa1e14d586 Change content divider from h2(##) to h1(#) and update related prompt messages 2025-06-15 11:24:43 +08:00
Yeban8090
8b339e833f
Merge pull request #23 from Yeban8090/1.0.17
1.0.17
2025-06-03 23:15:59 +08:00
Yeban8090
bcf6def0e8 新增头像圆角设置 2025-06-03 23:05:21 +08:00
Yeban8090
f2075f421e 调整整体视窗布局,使低分辨率机器更加舒适 2025-06-03 22:46:15 +08:00
Yeban8090
dba9de9d27
Merge pull request #22 from Yeban8090/1.0.16
1.0.16
2025-05-23 17:03:34 +08:00
Yeban8090
0af7fdcf57 优化认证图标 2025-05-23 17:02:41 +08:00
Yeban8090
17c2521a45 初始化1.0.16版本 2025-05-02 14:41:00 +08:00
Yeban8090
52b417ecff
Update README.md 2025-05-02 14:34:45 +08:00
Yeban8090
412d1faae7
Update README.md 2025-05-02 14:34:22 +08:00
Yeban8090
b230f68ba4
Merge pull request #19 from Yeban8090/1.0.15
1.0.15
2025-05-02 14:27:24 +08:00
Yeban8090
887940936c 更新版本号 2025-05-02 14:26:12 +08:00
Yeban8090
2148c746cc 优化readme和预览是否显示页脚 2025-05-02 14:25:43 +08:00
Yeban8090
f8598d1ee4
Merge pull request #18 from Yeban8090/1.0.14
新增控制页眉页脚内容显示
2025-05-01 22:32:49 +08:00
Yeban8090
9568afada1 新增控制页眉页脚内容显示 2025-05-01 22:32:11 +08:00
28 changed files with 295 additions and 129 deletions

View file

@ -1,5 +1,5 @@
# Note to RED
![downloads](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=downloads&query=%24%5B%22note-to-red%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json&style=flat) ![version](https://img.shields.io/github/v/tag/Yeban8090/note-to-red?color=blue&label=version&style=flat) ![license](https://img.shields.io/badge/license-MIT-green) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-支持作者-yellow)](https://ko-fi.com/bruceyeban)
![downloads](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=downloads&query=%24%5B%22note-to-red%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json&style=flat) ![version](https://img.shields.io/github/v/tag/Yeban8090/note-to-red?color=blue&label=version&style=flat) ![license](https://img.shields.io/badge/license-MIT-green) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-支持作者-yellow)](#支持作者)
> 一键将 Obsidian 笔记转换为小红书图片的插件。
@ -12,7 +12,7 @@
</p>
## 功能特点
- 📝 使用二级标题分割内容,每个标题自动生成一张配图
- 📝 可设置使用一级或二级标题分割内容,每个标题自动生成一张配图
- 🎨 提供多种精美模板,支持自定义字体和字号
- 🎯 支持自定义主题,可调整颜色、字体、间距等样式
- 👤 可自定义用户头像、昵称和页脚文案
@ -21,7 +21,7 @@
- 🔒 锁定功能避免预览刷新打断书写
## 使用方法
1. 核心用法:用二级标题(##)分割内容,每个标题生成一张小红书配图
1. 核心用法:在设置中选择标题级别(一级#或二级##),用对应标题分割内容,每个标题生成一张小红书配图
2. 首图制作单独调整首节字号至20-24px使用【下载当前页】导出
3. 长文优化内容较多的章节可调小字号至14-16px后单独导出
4. 批量操作:保持统一字号时,用【导出全部页】批量生成
@ -44,7 +44,8 @@
4. 在设置中启用插件
## 使用技巧
- 使用二级标题来分割不同的图片内容
- 在设置中选择适合的标题级别(一级#或二级##)来分割不同的图片内容
- 一级标题适合大章节分割,二级标题适合小章节分割
- 调整字号大小以适应不同长度的内容
- 可以自定义头像和用户信息
- 支持实时预览和编辑
@ -60,11 +61,27 @@
## 支持作者
如果这个插件对你有所帮助,可以考虑请作者喝杯咖啡 ☕:
- 微信支付
- 支付宝
- [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-支持作者-yellow)](https://ko-fi.com/bruceyeban)
<div align="center">
<div style="display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;">
<div style="text-align: center; margin: 1px;">
<strong>微信支付</strong><br/>
<img src="src/assets/donate/wechat_pay.png" alt="微信支付" width="180px" style="margin-top: 10px;">
</div>
<div style="text-align: center; margin: 1px;">
<strong>支付宝</strong><br/>
<img src="src/assets/donate/alipay.png" alt="支付宝" width="180px" style="margin-top: 10px;">
</div>
<div style="text-align: center; margin: 1px;">
<strong>Buy Me a Coffee</strong><br/>
<a href="https://ko-fi.com/bruceyeban" style="margin-top: 10px; display: inline-block;">
<img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-支持作者-yellow?style=for-the-badge&logo=ko-fi" alt="Buy Me a Coffee" />
</a>
</div>
</div>
</div>
您的支持是我持续改进这个插件的动力!
## 许可证
MIT License。查看 [LICENSE](LICENSE) 获取更多信息。
MIT License。查看 [LICENSE](LICENSE) 获取更多信息。

View file

@ -1,7 +1,7 @@
{
"id": "note-to-red",
"name": "Note to RED",
"version": "1.0.13",
"version": "1.0.19",
"minAppVersion": "0.15.0",
"description": "Convert Markdown notes to RED (Xiaohongshu) style images",
"author": "Yeban",

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 845 KiB

After

Width:  |  Height:  |  Size: 705 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 987 KiB

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 KiB

After

Width:  |  Height:  |  Size: 688 KiB

View file

@ -1,27 +1,34 @@
import { App } from 'obsidian';
import RedPlugin from './main';
export class RedConverter {
private static app: App;
private static plugin: RedPlugin;
static initialize(app: App) {
static initialize(app: App, plugin: RedPlugin) {
this.app = app;
this.plugin = plugin;
}
static hasValidContent(element: HTMLElement): boolean {
const headers = element.querySelectorAll('h2');
const settings = this.plugin?.settingsManager?.getSettings();
const headingLevel = settings?.headingLevel || 'h1';
const headers = element.querySelectorAll(headingLevel);
return headers.length > 0;
}
static formatContent(element: HTMLElement): void {
const headers = Array.from(element.querySelectorAll('h2'));
const settings = this.plugin?.settingsManager?.getSettings();
const headingLevel = settings?.headingLevel || 'h1';
const headers = Array.from(element.querySelectorAll(headingLevel));
if (headers.length === 0) {
element.empty();
const tip = element.createEl('div', {
cls: 'red-empty-message',
text: `⚠️ 温馨提示
使(##)
使${headingLevel === 'h1' ? '一级标题(#)' : '二级标题(##)'}
${headingLevel === 'h1' ? '一级标题' : '二级标题'}
`
});
// 触发自定义事件
@ -98,11 +105,14 @@ export class RedConverter {
}
private static createContentSection(header: Element, index: number): HTMLElement | null {
const settings = this.plugin?.settingsManager?.getSettings();
const headingLevel = settings?.headingLevel || 'h1';
// 获取当前标题到下一个标题之间的所有内容
let content: Element[] = [];
let current = header.nextElementSibling;
while (current && current.tagName !== 'H2') {
while (current && current.tagName !== headingLevel.toUpperCase()) {
content.push(current.cloneNode(true) as Element);
current = current.nextElementSibling;
}

View file

@ -18,6 +18,8 @@ export class DefaultTemplate implements ImgTemplate {
render(element: HTMLElement) {
const sections = element.querySelectorAll('.red-content-section');
const settings = this.settingsManager.getSettings();
sections.forEach(section => {
// 获取已有的头部和页脚元素
const header = element.querySelector('.red-preview-header');
@ -30,7 +32,13 @@ export class DefaultTemplate implements ImgTemplate {
// 页脚内容
if (this.sections.footer && footer) {
this.createFooterContent(footer as HTMLElement);
// 检查是否显示页脚
if (settings.showFooter !== false) {
this.createFooterContent(footer as HTMLElement);
} else {
// 完全移除页脚元素
footer.remove();
}
}
});
}
@ -91,10 +99,12 @@ export class DefaultTemplate implements ImgTemplate {
text: settings.userName,
attr: { 'title': '点击编辑用户名' }
});
userNameContainer.createEl('div', {
userNameContainer.createEl('span', {
cls: 'red-verified-icon',
text: '✓'
});
attr: {
role: 'img'
}
}).innerHTML = `<svg viewBox="0 0 22 22" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-bnwqim r-lrvibr r-m6rgpd r-1cvl2hr r-f9ja8p r-og9te1 r-3t4u6i"><g><path d="M20.396 11c-.018-.646-.215-1.275-.57-1.816-.354-.54-.852-.972-1.438-1.246.223-.607.27-1.264.14-1.897-.131-.634-.437-1.218-.882-1.687-.47-.445-1.053-.75-1.687-.882-.633-.13-1.29-.083-1.897.14-.273-.587-.704-1.086-1.245-1.44S11.647 1.62 11 1.604c-.646.017-1.273.213-1.813.568s-.969.854-1.24 1.44c-.608-.223-1.267-.272-1.902-.14-.635.13-1.22.436-1.69.882-.445.47-.749 1.055-.878 1.688-.13.633-.08 1.29.144 1.896-.587.274-1.087.705-1.443 1.245-.356.54-.555 1.17-.574 1.817.02.647.218 1.276.574 1.817.356.54.856.972 1.443 1.245-.224.606-.274 1.263-.144 1.896.13.634.433 1.218.877 1.688.47.443 1.054.747 1.687.878.633.132 1.29.084 1.897-.136.274.586.705 1.084 1.246 1.439.54.354 1.17.551 1.816.569.647-.016 1.276-.213 1.817-.567s.972-.854 1.245-1.44c.604.239 1.266.296 1.903.164.636-.132 1.22-.447 1.68-.907.46-.46.776-1.044.908-1.681s.075-1.299-.165-1.903c.586-.274 1.084-.705 1.439-1.246.354-.54.551-1.17.569-1.816zM9.662 14.85l-3.429-3.428 1.293-1.302 2.072 2.072 4.4-4.794 1.347 1.246z"></path></g></svg>`;
const userId = userMeta.createEl('div', {
cls: 'red-user-id',

View file

@ -7,71 +7,79 @@ import { DonateManager } from './donateManager';
import { RedSettingTab } from './settings/SettingTab';
export default class RedPlugin extends Plugin {
settingsManager: SettingsManager;
themeManager: ThemeManager;
settingsManager: SettingsManager;
themeManager: ThemeManager;
async onload() {
// 初始化设置管理器
this.settingsManager = new SettingsManager(this);
await this.settingsManager.loadSettings();
async onload() {
// 初始化设置管理器
this.settingsManager = new SettingsManager(this);
await this.settingsManager.loadSettings();
// 初始化主题管理器
this.themeManager = new ThemeManager(this.app, this.settingsManager);
// 初始化主题管理器
this.themeManager = new ThemeManager(this.app, this.settingsManager);
// 初始化转换器
RedConverter.initialize(this.app);
// 初始化转换器
RedConverter.initialize(this.app, this);
DonateManager.initialize(this.app, this);
DonateManager.initialize(this.app, this);
// 注册视图
this.registerView(
VIEW_TYPE_RED,
(leaf) => new RedView(leaf, this.themeManager, this.settingsManager)
);
// 注册视图
this.registerView(
VIEW_TYPE_RED,
(leaf) => new RedView(leaf, this.themeManager, this.settingsManager)
);
// 添加首次加载自动打开视图的逻辑
this.app.workspace.onLayoutReady(() => {
if (this.app.workspace.getLeavesOfType(VIEW_TYPE_RED).length === 0) {
const leaf = this.app.workspace.getRightLeaf(false);
if (leaf) {
leaf.setViewState({
type: VIEW_TYPE_RED,
active: false // 设置为 false 表示不聚焦
});
}
}
});
// 添加首次加载自动打开视图的逻辑
// this.app.workspace.onLayoutReady(() => {
// this.app.workspace.on("layout-change", () => {
// const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_RED);
// if (leaves.length === 0) {
// const rightLeaf = this.app.workspace.getRightLeaf(false);
// if (rightLeaf) {
// rightLeaf.setViewState({
// type: VIEW_TYPE_RED,
// active: false,
// });
// }
// }
// });
// });
// 添加命令到命令面板
this.addCommand({
// 添加命令到命令面板
this.addCommand({
id: 'open-mp-preview',
name: '打开小红书图片预览',
callback: async () => {
await this.activateView();
}
});
callback: async () => {
await this.activateView();
},
});
// 在插件的 onload 方法中添加:
this.addSettingTab(new RedSettingTab(this.app, this));
}
// 添加一个功能按钮用于打开所有面板
this.addRibbonIcon("image", "打开小红书图片预览", () => {
this.activateView();
});
async activateView() {
// 如果视图已经存在,激活它
// 在插件的 onload 方法中添加:
this.addSettingTab(new RedSettingTab(this.app, this));
}
async activateView() {
// 如果视图已经存在,激活它
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_RED); // 使用原来的视图类型
if (leaves.length > 0) {
this.app.workspace.revealLeaf(leaves[0]);
return;
}
// 创建新视图
const rightLeaf = this.app.workspace.getRightLeaf(false);
if (rightLeaf) {
await rightLeaf.setViewState({
type: VIEW_TYPE_RED,
active: true,
});
} else {
new Notice('无法创建视图面板');
}
if (leaves.length > 0) {
this.app.workspace.revealLeaf(leaves[0]);
return;
}
}
// 创建新视图
const rightLeaf = this.app.workspace.getRightLeaf(false);
if (rightLeaf) {
await rightLeaf.setViewState({
type: VIEW_TYPE_RED,
active: true,
});
} else {
new Notice('无法创建视图面板');
}
}
}

View file

@ -39,7 +39,7 @@ export class CreateThemeModal extends Modal {
userName: "font-size: 17px; font-weight: 600; color: #8b4513; serif; text-shadow: 0 2px 4px rgba(139,69,19,0.1);",
userId: "font-size: 14px; color: #b87333; font-family: 'Noto Serif SC', serif;",
postTime: "font-size: 13px; color: #d2691e; font-style: italic;",
verifiedIcon: "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #fffaf5; background: linear-gradient(135deg, #d2691e, #b87333); border-radius: 50%; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(210,105,30,0.2); border: 1px solid #b8733380;"
verifiedIcon: "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
footer: {
container: "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #b87333; font-size: 13px; border-top: 1px solid #b8733380; background: rgba(255,250,245,0.95); backdrop-filter: blur(8px);",
@ -126,7 +126,7 @@ export class CreateThemeModal extends Modal {
.onChange(value => {
const selectedTheme = this.getThemeById(value);
if (selectedTheme) {
this.theme = { ...selectedTheme, id: '', name: '', description: '', isPreset: false};
this.theme = { ...selectedTheme, id: '', name: '', description: '', isPreset: false };
}
})
.selectEl;
@ -566,38 +566,72 @@ export class CreateThemeModal extends Modal {
.replace(/border:\s*1px solid\s*#[a-fA-F0-9]+80/, `border: 1px solid ${value}80`);
});
});
// 添加头像圆角设置
new Setting(headerSection)
.setName('头像圆角')
.setDesc('设置头像的圆角大小单位px。设置为-1表示圆形大于1则有圆角')
.addText(text => {
// 获取当前圆角值
const currentRadius = styles.avatar.container.match(/border-radius:\s*([\d-]+)px/)?.[1] || '12';
text.setValue(currentRadius)
.setPlaceholder('输入圆角大小')
.onChange(value => {
// 解析输入值
let radius: string;
if (value === '-1') {
// 设置为圆形50%
radius = '50%';
} else {
// 设置为具体的像素值
const pixelValue = parseInt(value) || 12;
radius = `${pixelValue}px`;
}
// 更新样式
styles.avatar.container = styles.avatar.container
.replace(/border-radius:\s*[^;]+/, `border-radius: ${radius}`);
});
});
new Setting(headerSection)
.setName('认证图标颜色')
.setDesc('设置认证(已验证)图标的主色')
.setDesc('设置认证图标的颜色')
.addColorPicker(color => {
// 兼容 background: linear-gradient(...) 和 background-color: ...
let currentColor = '#b87333';
const bgMatch = styles.verifiedIcon.match(/background:\s*linear-gradient\([^,]+,\s*(#[a-fA-F0-9]+)/);
if (bgMatch) {
currentColor = bgMatch[1];
} else {
const colorMatch = styles.verifiedIcon.match(/background-color:\s*(#[a-fA-F0-9]+)/);
if (colorMatch) {
currentColor = colorMatch[1];
}
}
const currentColor = styles.verifiedIcon.match(/fill:\s*(#[a-fA-F0-9]+)/)?.[1] || '#1DA1F2';
color.setValue(currentColor)
.onChange(value => {
// 先处理 linear-gradient
if (styles.verifiedIcon.includes('linear-gradient')) {
styles.verifiedIcon = styles.verifiedIcon
.replace(/background:\s*linear-gradient\([^)]+\)/, `background: linear-gradient(135deg, ${value}, ${value})`);
}
// 再处理 background-color
if (styles.verifiedIcon.includes('background-color')) {
styles.verifiedIcon = styles.verifiedIcon
.replace(/background-color:\s*#[a-fA-F0-9]+/, `background-color: ${value}`);
}
// 统一处理 border 和 box-shadow
styles.verifiedIcon = styles.verifiedIcon
.replace(/border:\s*1px solid\s*#[a-fA-F0-9]+80/, `border: 1px solid ${value}80`)
.replace(/box-shadow:\s*0 2px 8px [^;]+;/, `box-shadow: 0 2px 8px ${value}1a;`);
.replace(/fill:\s*[^;]+/, `fill: ${value}`);
if (!styles.verifiedIcon.includes('fill:')) {
styles.verifiedIcon += `; fill: ${value}`;
}
});
});
new Setting(headerSection)
.setName('认证图标尺寸')
.setDesc('设置认证图标的宽度和高度单位px')
.addText(text => {
text.setValue('25')
.setPlaceholder('输入图标尺寸')
.onChange(value => {
const size = value + 'px';
styles.verifiedIcon = styles.verifiedIcon
.replace(/width:\s*[^;]+/, `width: ${size}`)
.replace(/height:\s*[^;]+/, `height: ${size}`);
});
});
new Setting(headerSection)
.setName('认证图标间距')
.setDesc('设置认证图标的左边距单位px')
.addText(text => {
text.setValue('-5')
.setPlaceholder('输入左边距')
.onChange(value => {
const margin = value + 'px';
styles.verifiedIcon = styles.verifiedIcon
.replace(/margin-left:\s*[^;]+/, `margin-left: ${margin}`);
});
});
}

View file

@ -58,6 +58,39 @@ export class RedSettingTab extends PluginSettingTab {
}
private renderBasicSettings(containerEl: HTMLElement): void {
// 排版管理区域
const typographySection = containerEl.createDiv('red-settings-subsection');
const typographyHeader = typographySection.createDiv('red-settings-subsection-header');
const typographyToggle = typographyHeader.createSpan('red-settings-subsection-toggle');
setIcon(typographyToggle, 'chevron-right');
typographyHeader.createEl('h3', { text: '排版管理' });
const typographyContent = typographySection.createDiv('red-settings-subsection-content');
// 折叠/展开逻辑
typographyHeader.addEventListener('click', () => {
const isExpanded = !typographySection.hasClass('is-expanded');
typographySection.toggleClass('is-expanded', isExpanded);
setIcon(typographyToggle, isExpanded ? 'chevron-down' : 'chevron-right');
});
// 内容分割标题级别设置
new Setting(typographyContent)
.setName('内容分割标题级别')
.setDesc('选择用于分割内容生成图片的标题级别:')
.addDropdown(dropdown => dropdown
.addOption('h1', '一级标题(#) - 按大章节分割')
.addOption('h2', '二级标题(##) - 按小章节分割')
.setValue(this.plugin.settingsManager.getSettings().headingLevel)
.onChange(async (value: 'h1' | 'h2') => {
await this.plugin.settingsManager.updateSettings({
headingLevel: value
});
new Notice('标题级别设置已更新,请重启 Obsidian 或重新加载以使更改生效');
})
);
// 字体管理区域
const fontSection = containerEl.createDiv('red-settings-subsection');
const fontHeader = fontSection.createDiv('red-settings-subsection-header');
@ -155,8 +188,36 @@ export class RedSettingTab extends PluginSettingTab {
setIcon(themeVisibilityToggle, isExpanded ? 'chevron-down' : 'chevron-right');
});
// 添加页脚显示设置
new Setting(themeVisibilityContent)
.setName('是否显示时间')
.setDesc('控制是否在主题中显示页眉时间')
.addToggle(toggle => toggle
.setValue(this.plugin.settingsManager.getSettings().showTime !== false)
.onChange(async (value) => {
await this.plugin.settingsManager.updateSettings({
showTime: value
});
new Notice('请重启 Obsidian 或重新加载以使更改生效');
})
);
// 添加页脚显示设置
new Setting(themeVisibilityContent)
.setName('是否显示页脚')
.setDesc('控制是否在主题中显示页脚部分')
.addToggle(toggle => toggle
.setValue(this.plugin.settingsManager.getSettings().showFooter !== false)
.onChange(async (value) => {
await this.plugin.settingsManager.updateSettings({
showFooter: value
});
new Notice('请重启 Obsidian 或重新加载以使更改生效');
})
);
themeVisibilityContent.createEl('hr', { cls: 'red-settings-divider' });
// 主题选择容器
const themeSelectionContainer = themeVisibilityContent.createDiv('theme-selection-container');
@ -325,4 +386,4 @@ export class RedSettingTab extends PluginSettingTab {
).open();
}));
}
}
}

View file

@ -50,7 +50,14 @@ export class ThemePreviewModal extends Modal {
const userMeta = userLeft.createEl('div', { cls: 'red-user-meta' });
const userNameContainer = userMeta.createEl('div', { cls: 'red-user-name-container' });
userNameContainer.createEl('div', { cls: 'red-user-name', text: `${settings.userName}` });
userNameContainer.createEl('div', { cls: 'red-verified-icon', text: '✓' });
userNameContainer.createEl('span', {
cls: 'red-verified-icon',
attr: {
'aria-label': 'Verified account',
role: 'img'
}
}).innerHTML = `<svg viewBox="0 0 22 22" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-bnwqim r-lrvibr r-m6rgpd r-1cvl2hr r-f9ja8p r-og9te1 r-3t4u6i"><g><path d="M20.396 11c-.018-.646-.215-1.275-.57-1.816-.354-.54-.852-.972-1.438-1.246.223-.607.27-1.264.14-1.897-.131-.634-.437-1.218-.882-1.687-.47-.445-1.053-.75-1.687-.882-.633-.13-1.29-.083-1.897.14-.273-.587-.704-1.086-1.245-1.44S11.647 1.62 11 1.604c-.646.017-1.273.213-1.813.568s-.969.854-1.24 1.44c-.608-.223-1.267-.272-1.902-.14-.635.13-1.22.436-1.69.882-.445.47-.749 1.055-.878 1.688-.13.633-.08 1.29.144 1.896-.587.274-1.087.705-1.443 1.245-.356.54-.555 1.17-.574 1.817.02.647.218 1.276.574 1.817.356.54.856.972 1.443 1.245-.224.606-.274 1.263-.144 1.896.13.634.433 1.218.877 1.688.47.443 1.054.747 1.687.878.633.132 1.29.084 1.897-.136.274.586.705 1.084 1.246 1.439.54.354 1.17.551 1.816.569.647-.016 1.276-.213 1.817-.567s.972-.854 1.245-1.44c.604.239 1.266.296 1.903.164.636-.132 1.22-.447 1.68-.907.46-.46.776-1.044.908-1.681s.075-1.299-.165-1.903c.586-.274 1.084-.705 1.439-1.246.354-.54.551-1.17.569-1.816zM9.662 14.85l-3.429-3.428 1.293-1.302 2.072 2.072 4.4-4.794 1.347 1.246z"></path></g></svg>`;
userMeta.createEl('div', { cls: 'red-user-id', text: `${settings.userId}` });
const userRight = userInfo.createEl('div', { cls: 'red-user-right' });
userRight.createEl('div', { cls: 'red-post-time', text: '2025/4/20' });
@ -92,9 +99,18 @@ export class ThemePreviewModal extends Modal {
// 页脚区域
const footer = previewContainer.createDiv('red-preview-footer');
footer.createEl('div', { cls: 'red-footer-text', text: `${settings.footerLeftText}` });
footer.createEl('div', { cls: 'red-footer-separator', text: '|' });
footer.createEl('div', { cls: 'red-footer-text', text: `${settings.footerRightText}` });
// 页脚内容
if (footer) {
// 检查是否显示页脚
if (settings.showFooter !== false) {
footer.createEl('div', { cls: 'red-footer-text', text: `${settings.footerLeftText}` });
footer.createEl('div', { cls: 'red-footer-separator', text: '|' });
footer.createEl('div', { cls: 'red-footer-text', text: `${settings.footerRightText}` });
} else {
// 完全移除页脚元素
footer.remove();
}
}
this.themeManager.applyTheme(container, this.theme);
}

View file

@ -18,8 +18,10 @@ interface RedSettings {
userId: string;
showTime: boolean;
timeFormat: string;
showFooter?: boolean;
footerLeftText: string;
footerRightText: string;
headingLevel: 'h1' | 'h2'; // 标题级别选项
customFonts: { value: string; label: string; isPreset?: boolean }[]; // 添加自定义字体配置
backgroundSettings: {
imageUrl: string;
@ -43,6 +45,7 @@ export const DEFAULT_SETTINGS: RedSettings = {
userId: '@Yeban',
showTime: true,
timeFormat: 'zh-CN',
headingLevel: 'h2', // 默认使用二级标题
footerLeftText: '夜半过后,光明便启程',
footerRightText: '欢迎关注公众号:夜半',
customFonts: [

View file

@ -244,7 +244,7 @@
/* 设置子区域折叠样式 */
.red-settings .red-settings-subsection {
margin: 0 12px;
margin: 0 12px 12px 12px;
border: 1px solid var(--background-modifier-border);
border-radius: 8px;
overflow-y: auto;
@ -284,4 +284,11 @@
.red-settings .red-settings-subsection.is-expanded .red-settings-subsection-content {
display: block;
}
}
.red-settings-divider {
margin: 15px 0;
border: none;
height: 1px;
background-color: var(--background-modifier-border);
}

View file

@ -23,7 +23,7 @@
.red-preview-container {
position: relative;
min-width: 490px;
height: 100%;
aspect-ratio: 3/4;
display: flex;
justify-content: center;
align-items: flex-start;
@ -90,7 +90,7 @@
/* 导航容器 */
.red-nav-container {
position: fixed;
bottom: 120px; /* 调整位置避免与底部工具栏重叠 */
bottom: 110px; /* 调整位置避免与底部工具栏重叠 */
left: 50%;
transform: translateX(-50%);
display: flex;

View file

@ -16,8 +16,8 @@
"nameContainer": "display: flex; align-items: center; gap: 8px;",
"userName": "font-size: 16px; font-weight: 600; color: #ff00ff; cursor: pointer; transition: all 0.2s ease; text-shadow: 0 0 10px rgba(255, 0, 255, 0.3); &:hover { color: #ff2a6d; }",
"userId": "font-size: 14px; color: #00ffff; cursor: pointer; transition: all 0.2s ease; &:hover { color: #05ffa1; }",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #ffffff; background-color: #ff00ff; border-radius: 50%; font-size: 10px; flex-shrink: 0; transition: all 0.3s ease; box-shadow: 0 0 10px rgba(255, 0, 255, 0.3); &:hover { transform: scale(1.1); background-color: #05ffa1; }",
"postTime": "font-size: 14px; color: #00ffff; cursor: pointer; transition: all 0.2s ease; &:hover { color: #05ffa1; }"
"postTime": "font-size: 14px; color: #00ffff; cursor: pointer; transition: all 0.2s ease; &:hover { color: #05ffa1; }",
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 600; color: #ffffff;",
"userId": "font-size: 14px; color: #98989d;",
"postTime": "font-size: 13px; color: #636366;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #ffffff; background-color: #0A84FF; border-radius: 50%; font-size: 10px; flex-shrink: 0;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #98989d; font-size: 13px; border-top: 1px solid #2c2c2e; background: #1c1c1e;",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 600; color: #e2d9f3; letter-spacing: 0.02em;",
"userId": "font-size: 14px; color: #a393c9;",
"postTime": "font-size: 13px; color: #6d617f;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #1a1721; background-color: #b490ff; border-radius: 6px; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(180,144,255,0.2);"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #a393c9; font-size: 13px; border-top: 1px solid #2a2433; background: rgba(26,23,33,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 600; color: #2ecc71; text-shadow: 0 2px 4px rgba(46,204,113,0.1);",
"userId": "font-size: 14px; color: #27ae60; font-family: 'SF Pro Text';",
"postTime": "font-size: 13px; color: #16a085; letter-spacing: 0.02em;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #1a2420; background-color: #2ecc71; border-radius: 6px; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(46,204,113,0.3); border: 1px solid #2ecc7180;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #27ae60; font-size: 13px; border-top: 1px solid #2ecc7140; background: rgba(26,36,32,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 700; color: #f0f0f0; text-shadow: 0 2px 4px rgba(0,0,0,0.3);",
"userId": "font-size: 14px; color: #a0a0a0; font-family: 'SF Pro Display';",
"postTime": "font-size: 13px; color: #808080; letter-spacing: 0.03em;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #1e2228; background: linear-gradient(135deg, #d0d0d0, #ffffff); border-radius: 4px; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0,0,0,0.3); border: 1px solid #4d4d4d80;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #a0a0a0; font-size: 13px; border-top: 1px solid #4d4d4d80; background: rgba(30,34,40,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 600; color: #333333; letter-spacing: 0.02em;",
"userId": "font-size: 14px; color: #666666;",
"postTime": "font-size: 13px; color: #999999;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #ffffff; background-color: #6c9eb8; border-radius: 4px; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 4px rgba(108,158,184,0.1);"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 16px; padding: 16px; color: #999999; font-size: 13px; border-top: 1px solid #eeeeee; background: rgba(250,250,250,0.95); backdrop-filter: blur(8px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 700; color: #40a9ff; text-shadow: 0 2px 8px rgba(64,169,255,0.2);",
"userId": "font-size: 14px; color: #69c0ff; font-family: 'SF Pro Text';",
"postTime": "font-size: 13px; color: #91d5ff; letter-spacing: 0.03em;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #0a192f; background: linear-gradient(135deg, #40a9ff, #69c0ff); border-radius: 6px; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 12px rgba(64,169,255,0.3); border: 1px solid #69c0ff80;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #69c0ff; font-size: 13px; border-top: 1px solid #1d3552; background: rgba(10,25,47,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 700; color: #ffb6c1; text-shadow: 0 2px 8px rgba(255,182,193,0.2);",
"userId": "font-size: 14px; color: #ff8da1; font-family: 'SF Pro Text';",
"postTime": "font-size: 13px; color: #ff6b88; letter-spacing: 0.03em;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #1f1a1d; background: linear-gradient(135deg, #ffb6c1, #ff8da1); border-radius: 50%; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 12px rgba(255,182,193,0.3); border: 1px solid #ffb6c180;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #ff8da1; font-size: 13px; border-top: 1px solid #ffb6c140; background: rgba(31,26,29,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 700; color: #9370db; text-shadow: 0 2px 8px rgba(147,112,219,0.2);",
"userId": "font-size: 14px; color: #b19cd9; font-family: 'SF Pro Text';",
"postTime": "font-size: 13px; color: #8a7bb5; letter-spacing: 0.03em;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #0d0f1a; background: linear-gradient(135deg, #9370db, #b19cd9); border-radius: 50%; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 12px rgba(147,112,219,0.3); border: 1px solid #9370db80;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #b19cd9; font-size: 13px; border-top: 1px solid #252640; background: rgba(13,15,26,0.95); backdrop-filter: blur(12px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 17px; font-weight: 600; color: #8b4513; serif; text-shadow: 0 2px 4px rgba(139,69,19,0.1);",
"userId": "font-size: 14px; color: #b87333; font-family: 'Noto Serif SC', serif;",
"postTime": "font-size: 13px; color: #d2691e; font-style: italic;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #fffaf5; background: linear-gradient(135deg, #d2691e, #b87333); border-radius: 50%; font-size: 10px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(210,105,30,0.2); border: 1px solid #b8733380;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #b87333; font-size: 13px; border-top: 1px solid #b8733380; background: rgba(255,250,245,0.95); backdrop-filter: blur(8px);",

View file

@ -13,7 +13,7 @@
"userName": "font-size: 16px; font-weight: 600; color: #ffffff;",
"userId": "font-size: 14px; color: #98989d;",
"postTime": "font-size: 13px; color: #636366;",
"verifiedIcon": "width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; color: #ffffff; background-color: #c57512; border-radius: 50%; font-size: 10px; flex-shrink: 0;"
"verifiedIcon": "width: 20px; height: 20px; margin-left: -5px; fill: #1DA1F2;"
},
"footer": {
"container": "position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 16px; color: #98989d; font-size: 13px; border-top: 1px solid #2c2c2e; background: #1c1c1e;",

View file

@ -316,12 +316,12 @@ export class RedView extends ItemView {
attr: { 'aria-label': '使用指南' }
});
setIcon(helpButton, 'help');
const headingLevel = this.settingsManager.getSettings().headingLevel || 'h1';
parent.createEl('div', {
cls: 'red-help-tooltip',
text: `使用指南:
1. (##)
2. 使 ---
1. ${headingLevel === 'h1' ? '一级标题(#)' : '二级标题(##)'}
2. ${headingLevel === 'h1' ? '一级标题(#)' : '二级标题(##)'}使 ---
3. 20-24px使
4. 14-16px后单独导出
5.
@ -553,7 +553,7 @@ export class RedView extends ItemView {
this.updateControlsState(hasValidContent);
if (!hasValidContent) {
this.copyButton.setAttribute('title', '请先添加级标题内容');
this.copyButton.setAttribute('title', '请先添加级标题内容');
} else {
this.copyButton.removeAttribute('title');
}
@ -737,4 +737,4 @@ export class RedView extends ItemView {
return false;
}
}
}