feat: Initial clean release of CHM
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled

这个提交包含在:
chen
2026-11-04 11:29:39 +08:00
当前提交 301194963b
共有 8663 个文件被更改,包括 1962691 次插入 和 0 次删除

查看文件

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="64px" height="64px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<use xlink:href="#_Image1" x="0" y="0" width="64px" height="64px"/>
<defs>
<image id="_Image1" width="64px" height="64px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAlklEQVR4nO3QQRHAMADDsKz8OXcw9KiFwOdv293Djg7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkBrgA7QGqADtAboAK0BOkD7AVC0AX8AKmT5AAAAAElFTkSuQmCC"/>
</defs>
</svg>

之后

宽度:  |  高度:  |  大小: 922 B

查看文件

@@ -0,0 +1 @@
<svg viewBox="4.86 6.543831521739131 4.585597826086956 1.171875" width="117" height="30" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" class="js-draw--autoresize"><style id="js-draw-style-sheet">path{stroke-linecap:round;stroke-linejoin:round;}text{white-space:pre;}</style><path d="M9.445597826086956,7.71570652173913L9.445597826086956,6.543831521739131L4.86,6.543831521739131L4.86,7.71570652173913L9.445597826086956,7.71570652173913" fill="#ffffff" class="js-draw-image-background"></path><text style="transform: matrix(0.0509511, 0, 0, 0.0509511, 4.86, 7.41); font-family: Courier; font-size: 30px; fill: rgb(255, 0, 0);" data-highp-transform="matrix(0.05095108695652172,0,0,0.05095108695652172,4.86,7.41)">Image</text></svg>

之后

宽度:  |  高度:  |  大小: 750 B

查看文件

@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<h1>Test HTML file 2!</h1>
</body>
</html>

查看文件

@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<body>
<h1>Test HTML file!</h1>
<p>This is a test file. Resource:</p>
<img src="./image.svg" alt="An SVG image."/>
</body>
</html>

查看文件

@@ -0,0 +1 @@
<p><span style="margin-left: 100px;">test</span></p>

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 416 KiB

二进制文件未显示。

查看文件

@@ -0,0 +1 @@
This is a test.

查看文件

@@ -0,0 +1,22 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.crashBeforeRegister",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "Crash Before Register",
"description": "Plugin that crashes before calling register()",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
// Crash before calling joplin.plugins.register()
// This tests the fix for https://github.com/laurent22/joplin/issues/12793
throw new Error('Simulated plugin crash before register()');

查看文件

@@ -0,0 +1,83 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.dialogs",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
const dialogs = joplin.views.dialogs;
const dialogHandle = await dialogs.create('test-dialog');
await dialogs.setHtml(
dialogHandle,
`
<form name="main-form">
<label>Test: <input type="checkbox" name="test" checked/></label>
</form>
`,
);
await dialogs.setButtons(dialogHandle, [
{
id: 'ok',
title: 'Okay',
},
]);
await joplin.commands.register({
name: 'showTestDialog',
label: 'showTestDialog',
iconName: 'fas fa-drum',
execute: async () => {
const result = await joplin.views.dialogs.open(dialogHandle);
await joplin.commands.execute('editor.setText', JSON.stringify({
id: result.id,
hasFormData: !!result.formData,
}));
},
});
const dismissDialogHandle = await dialogs.create('test-dialog-with-dismiss');
await dialogs.setHtml(dismissDialogHandle, '<p>Press Escape to dismiss</p>');
await dialogs.setButtons(dismissDialogHandle, [
{ id: 'ok', title: 'Okay' },
{ id: 'cancel', title: 'Cancel' },
]);
await joplin.commands.register({
name: 'showTestDialogWithDismiss',
label: 'showTestDialogWithDismiss',
execute: async () => {
const result = await joplin.views.dialogs.open(dismissDialogHandle);
await joplin.commands.execute('editor.setText', result.id);
},
});
await joplin.commands.register({
name: 'getTestDialogVisibility',
label: 'Returns the dialog visibility state',
execute: async () => {
// panels.visible should also work for dialogs.
const visible = await joplin.views.panels.visible(dialogHandle);
// For dialogs, isActive should return the visibility.
// (Prefer panels.visible for dialogs).
const active = await joplin.views.panels.isActive(dialogHandle);
await joplin.commands.execute('editor.setText', JSON.stringify({
visible,
active,
}));
},
});
},
});

查看文件

@@ -0,0 +1,72 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.editorPlugin",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
const registerEditorPlugin = async (editorViewId) => {
const editors = joplin.views.editors;
const saveCallbacks = [];
await editors.register(editorViewId, {
onSetup: async (viewHandle) => {
await editors.setHtml(
viewHandle,
'<code>Loaded!</code>',
);
let noteId;
// The note ID is exposed in the DOM so tests can wait for the first update.
await editors.onUpdate(viewHandle, async event => {
noteId = event.noteId;
await editors.setHtml(
viewHandle,
`<code>Loaded!</code><code id="note-id">${noteId}</code>`,
);
});
saveCallbacks.push(async () => {
if (!noteId) throw new Error('saveNote called before the first onUpdate event');
await editors.saveNote(viewHandle, {
noteId,
body: `Changed by ${editorViewId}`,
});
});
},
onActivationCheck: async _event => {
// Always enable
return true;
},
});
await joplin.commands.register({
name: `testEditorPluginSave-${editorViewId}`,
label: `Test editor plugin save for ${editorViewId}`,
iconName: 'fas fa-music',
execute: async () => {
for (const saveCallback of saveCallbacks) {
await saveCallback();
}
},
});
};
joplin.plugins.register({
onStart: async function() {
await registerEditorPlugin('test-editor-plugin');
},
});

查看文件

@@ -0,0 +1,31 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.execCommand",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.commands.register({
name: 'testUpdateEditorText',
label: 'Test setting the editor\'s text with editor.setText',
iconName: 'fas fa-drum',
execute: async () => {
await joplin.commands.execute('editor.setText', 'PASS');
},
});
},
});

查看文件

@@ -0,0 +1,46 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.editorPlugin",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
const registerEditorPlugin = async (editorViewId) => {
const editors = joplin.views.editors;
await editors.register(editorViewId, {
async onSetup(view) {
await editors.setHtml(
view,
`<div id="frame-summary">
Editor plugin:
<code id="view-id-base">${editorViewId}</code>
for view handle: <code>${encodeURI(view)}</code>
</div>`,
);
},
async onActivationCheck(_event) {
// Always enable
return true;
},
});
};
joplin.plugins.register({
onStart: async function() {
// Register two different editor plugins:
await registerEditorPlugin('test-editor-plugin-1');
await registerEditorPlugin('test-editor-plugin-2');
},
});

查看文件

@@ -0,0 +1,71 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.panels",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
const waitFor = async (condition) => {
const wait = () => {
return new Promise(resolve => {
setTimeout(() => resolve(), 100);
});
};
for (let i = 0; i < 500; i++) {
if (await condition()) {
return;
}
// Pause for a brief delay
await wait();
}
throw new Error('Condition was never true');
};
joplin.plugins.register({
onStart: async function() {
const panels = joplin.views.panels;
const view = await panels.create('panelTestView');
await panels.setHtml(view, '<h1>Panel content</h1><p>Test</p>');
await panels.hide(view);
await joplin.commands.register({
name: 'testShowPanel',
label: 'Test panel visibility',
execute: async () => {
await panels.show(view);
await waitFor(async () => {
return await panels.visible(view);
});
await joplin.commands.execute('editor.setText', 'visible');
},
});
await joplin.commands.register({
name: 'testHidePanel',
label: 'Test: Hide the panel',
execute: async () => {
await panels.hide(view);
await waitFor(async () => {
return !await panels.visible(view);
});
await joplin.commands.execute('editor.setText', 'hidden');
},
});
},
});

查看文件

@@ -0,0 +1,34 @@
// Allows referencing the Joplin global:
/* eslint-disable no-undef */
// Allows the `joplin-manifest` block comment:
/* eslint-disable multiline-comment-style */
/* joplin-manifest:
{
"id": "org.joplinapp.plugins.example.showToast",
"manifest_version": 1,
"app_min_version": "3.1",
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.commands.register({
name: 'testShowToastNotification',
label: 'testShowToastNotification',
iconName: 'fas fa-drum',
execute: async () => {
await joplin.views.dialogs.showToast({
message: 'Toast: This is a test info message.',
duration: 1_000 * 60 * 60, // One hour
});
},
});
},
});

二进制文件未显示。

之后

宽度:  |  高度:  |  大小: 8.6 KiB

二进制文件未显示。