一、版本兼容性优化
当前环境:Node.js v23.8.0 + npm 10.9.2
需调整配置:
- 使用nvm安装LTS版本(推荐v18.17.0)
nvm install 18.17.0
nvm use 18.17.0
注:Joplin插件工具链对Node.js 23.x存在兼容性问题,官方推荐使用18.x LTS版本
- 升级npm至最新稳定版
npm install -g [email protected] --legacy-peer-deps
二、开发环境搭建
(一)插件开发套件
- 安装Yeoman脚手架
npm install -g yo [email protected] --python=python3
需确保已安装Python 3.10+并配置环境变量
- 生成插件模板
yo joplin --typescript --webpack5
参数说明:
- –typescript:生成TypeScript模板
- –webpack5:启用Webpack 5构建
- 安装核心依赖
npm install @joplin/[email protected] [email protected] @types/[email protected] --save-exact
(二)主题开发套件
- 创建主题工作区
mkdir joplin-theme && cd joplin-theme
npm init -y
- 安装主题开发工具
npm install [email protected] [email protected] [email protected] --save-dev
三、开发环境验证
(一)插件开发测试
- 实时编译模式
npm run dev -- --watch --mode=development
支持热重载,修改代码自动构建
- 单元测试配置
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
}
(二)主题开发测试
- 创建样式入口
// src/main.scss
@use "sass:color";
:root {
--primary-color: #{color.adjust(#2d7ff9, $lightness: 10%)};
--font-stack: 'Cascadia Code', 'Segoe UI', system-ui;
}
- 构建命令配置
// package.json
"scripts": {
"build": "sass src/main.scss dist/theme.css && postcss dist/theme.css -o dist/theme.min.css"
}
四、开发调试技巧
(一)插件调试方案
- 使用VSCode调试配置
// .vscode/launch.json
{
"type": "node",
"request": "launch",
"name": "Joplin Debug",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"console": "integratedTerminal",
"skipFiles": ["<node_modules/**>"]
}
- 跨平台测试建议
docker run -it --rm -v ${PWD}:/workspace node:18.17.0 bash
- 主题调试方案
a. 实时注入样式
npm run build && joplin plugins dev ../joplin-theme/dist
支持在Joplin运行时动态加载主题
b. 响应式测试技巧
/* 媒体查询调试断点 */
@media (max-width: 768px) {
body:after {
content: "Mobile Layout Active";
position: fixed;
bottom: 0;
right: 0;
background: red;
color: white;
padding: 5px;
z-index: 9999;
}
}
五、生产环境构建
- 生成发布包
npm run build -- --mode=production && joplin-plugin-cli pack
优化项:
- Tree-shaking移除未使用代码
- CSS压缩率提升至85%
- Sourcemap生成独立文件
- 版本兼容性检查
npx joplin-plugin-cli check-compat --min-joplin=3.0.0 --max-joplin=4.0.0
(二)环境维护建议
- 使用Docker沙箱环境
FROM node:18.17.0-bullseye
RUN npm install -g [email protected]
COPY . /workspace
WORKDIR /workspace
ENTRYPOINT ["pnpm", "dev"]
- 版本锁定策略
npm config set save-exact=true
pnpm add --save-exact @joplin/[email protected]
通过以上配置可构建企业级Joplin扩展开发环境,建议参考
的版本管理实践进行长期维护。若需外网同步测试,可结合
的Docker部署方案搭建私有Joplin Server。
// src/index.ts
import joplin from 'api';
import { SettingItemType } from 'api/types';
import * as xmlrpc from 'xmlrpc';
import { MenuItemLocation } from 'api/types';
interface WordPressConfig {
url: string;
username: string;
password: string;
}
async function postToWordPress(title: string, content: string, config: WordPressConfig) {
const client = xmlrpc.createClient({
url: config.url,
});
const postData = {
title: title,
description: content,
};
return new Promise((resolve, reject) => {
client.methodCall(
'metaWeblog.newPost',
[1, config.username, config.password, postData, true],
(error, value) => {
if (error) reject(error);
else resolve(value);
}
);bobyai
});
}
joplin.plugins.register({
onStart: async function () {
// 注册设置项
await joplin.settings.registerSection('wordpressSettings', {
label: 'WordPress 设置',
iconName: 'fas fa-blog',
});
await joplin.settings.registerSettings({
wpUrl: {
value: '',
type: SettingItemType.String,
section: 'wordpressSettings',
public: true,
label: 'WordPress 站点地址(如:https://example.com/xmlrpc.php)',
},
wpUser: {
value: '',
type: SettingItemType.Slaoxiongb2c tring,
section: 'wordpressSettings',
public: true,
label: '用户名',
},
wpPassword: {
value: '',
type: SettingItemType.String,
section: 'wordpressSettings',
public: true,
label: '密码',
},
});
// 批量发布所有笔记
await joplin.commands.register({
name: 'publishAllNotes',
label: '批量发布所有笔记到 WordPress',
execute: async () => {
const config: WordPressConfig = {
url: await joplin.settings.value('wpUrl'),
username: await joplin.settings.value('wpUser'),
password: await joplin.settings.value('wpPassword'),
};
if (!config.url || !config.username || !config.password) {
await joplin.views.dialogs.showMessageBox('请先在设置中填写完整的 WordPress 信息。');
return;
}
let page = 1;
let publishedCount = 0;
let failedCount = 0;
while (true) {
const notes = await joplin.data.get(['notes'], {
fields: ['id', 'title', 'body'],
page,
});
for (const note of notes.items) {
try {
await postToWordPress(note.title, note.body, config);
console.info(`✅ 成功发布: ${note.title}`);
publishedCount++;
} catch (err) {
console.error(`❌ 发布失败: ${note.title}`, err);
failedCount++;
}
}
if (!notes.has_more) break;
page++;
}
await joplin.views.dialogs.showMessageBox(
`发布完成!成功:${publishedCount} 篇,失败:${failedCount} 篇。`
);
},
});
// 发布选中的笔记
await joplin.commands.register({
name: 'publishSelectedNotes',
label: '发布选中笔记到 WordPress',
execute: async () => {
const config: WordPressConfig = {
url: await joplin.settings.value('wpUrl'),
username: await joplin.settings.value('wpUser'),
password: await joplin.settings.value('wpPassword'),
};
if (!config.url || !config.username || !config.password) {
await joplin.views.dialogs.showMessageBox('请先在设置中填写完整的 WordPress 信息。');
return;
}
const selectedIds: string[] = await joplin.workspace.selectedNoteIds();
if (selectedIds.length === 0) {
await joplin.views.bobyai dialogs.showMessageBox('请先选中要发布的笔记。');
return;
}
let publishedCount = 0;
let failedCount = 0;
for (const id of selectedIds) {
const note = await joplin.data.get(['notes', id], { fields: ['title', 'body'] });
try {
await postToWordPress(note.title, note.body, config);
console.info(`✅ 成功发布: ${note.title}`);
publishedCount++;
} catch (err) {
console.error(`❌ 发布失败: ${note.title}`, err);
failedCount++;
}
}
await joplin.views.dialogs.showMessageBox(
`发布完成!成功:${publishedCount} 篇,失败:${failedCount} 篇。`
);
},
});
// 主菜单(顶部工具栏)
await joplin.views.menus.create('mainMenu', 'WordPress 工具', [
{
commandName: 'publishAllNotes',
label: '批量发布笔记到 WordPress',
},
{
commandName: 'publishSelectedNotes',
label: '发布选中笔记',
}
]);
},
});
[Total: 0 Average: 0]
必须 注册 为本站用户, 登录 后才可以发表评论!