mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-25 08:15:55 +02:00
v1.0.8 - Fix task list checkbox loss and empty line preservation on markdown roundtrip
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "helixnotes",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
||||
Generated
+1
-1
@@ -1778,7 +1778,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "helixnotes"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dirs",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "helixnotes"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
description = "Local-first markdown note-taking app"
|
||||
authors = ["HelixNotes"]
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "HelixNotes",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"identifier": "com.helixnotes.app",
|
||||
"build": {
|
||||
"frontendDist": "../build",
|
||||
|
||||
@@ -1071,14 +1071,23 @@
|
||||
}
|
||||
|
||||
function prosemirrorToMarkdown(doc: any): string {
|
||||
const listTypes = new Set(['bulletList', 'orderedList', 'taskList']);
|
||||
const parts: string[] = [];
|
||||
let prevType = '';
|
||||
let preserveEmptyParas = false;
|
||||
doc.forEach((node: any) => {
|
||||
// Skip empty paragraphs right after code blocks (TipTap cursor placeholder)
|
||||
if (node.type.name === 'paragraph' && node.childCount === 0 && prevType === 'codeBlock') {
|
||||
const isEmpty = node.type.name === 'paragraph' && node.childCount === 0;
|
||||
// After a list or code block, preserve empty paragraphs as HTML comments
|
||||
// so markdown-it doesn't merge adjacent lists or collapse spacing
|
||||
if (listTypes.has(prevType) || prevType === 'codeBlock') {
|
||||
preserveEmptyParas = true;
|
||||
}
|
||||
if (isEmpty && preserveEmptyParas) {
|
||||
parts.push('<!-- -->');
|
||||
prevType = node.type.name;
|
||||
return;
|
||||
}
|
||||
preserveEmptyParas = false;
|
||||
parts.push(serializeNode(node));
|
||||
prevType = node.type.name;
|
||||
});
|
||||
@@ -1488,8 +1497,11 @@
|
||||
html = html.replace(/<code([^>]*)>\n?/g, '<code$1>');
|
||||
html = html.replace(/\n<\/code>/g, '</code>');
|
||||
|
||||
// Post-process: convert task list items to TipTap format
|
||||
html = html.replace(/<li><tiptask checked="(true|false)">([\s\S]*?)<\/tiptask><\/li>/gi, (_, checked, content) => {
|
||||
// Post-process: convert list-separator comments back to empty paragraphs for TipTap
|
||||
html = html.replace(/<!-- -->/g, '<p></p>');
|
||||
|
||||
// Post-process: convert task list items to TipTap format (handle both tight and loose lists — loose lists wrap content in <p> tags)
|
||||
html = html.replace(/<li>\s*(?:<p>)?\s*<tiptask checked="(true|false)">([\s\S]*?)<\/tiptask>\s*(?:<\/p>)?\s*<\/li>/gi, (_, checked, content) => {
|
||||
return `<li data-type="taskItem" data-checked="${checked}">${content}</li>`;
|
||||
});
|
||||
html = html.replace(/<ul>\s*(<li data-type="taskItem")/gi, '<ul data-type="taskList">$1');
|
||||
|
||||
Reference in New Issue
Block a user