fix: improve task regex to prevent matching nested brackets in status

Updated task regex pattern from [.] to [^\[\]]{1} to ensure only single
non-bracket characters are captured as task status. This prevents parsing
errors when task text contains square brackets.
This commit is contained in:
Quorafind 2025-09-01 20:57:55 +08:00
parent d18267c095
commit 26cd6028b8
4 changed files with 46 additions and 24 deletions

View file

@ -1,5 +1,5 @@
// Task identification
const TASK_REGEX = /^(([\s>]*)?(-|\d+\.|\*|\+)\s\[(.)\])\s*(.*)$/m;
const TASK_REGEX = /^(([\s>]*)?(-|\d+\.|\*|\+)\s\[([^\[\]]{1})\])\s+(.*)$/m;
// --- Emoji/Tasks Style Regexes ---
const EMOJI_START_DATE_REGEX = /🛫\s*(\d{4}-\d{2}-\d{2})/;

View file

@ -11,22 +11,31 @@ import {
import {
createEmbeddableMarkdownEditor,
EmbeddableMarkdownEditor,
} from '@/editor-extensions/core/markdown-editor';
import TaskProgressBarPlugin from '@/index';
import { saveCapture, processDateTemplates } from '@/utils/file/file-operations';
} from "@/editor-extensions/core/markdown-editor";
import TaskProgressBarPlugin from "@/index";
import {
saveCapture,
processDateTemplates,
} from "@/utils/file/file-operations";
import { FileSuggest } from "@/components/ui/inputs/AutoComplete";
import { t } from '@/translations/helper';
import { MarkdownRendererComponent } from '@/components/ui/renderers/MarkdownRenderer';
import { StatusComponent } from '@/components/ui/feedback/StatusIndicator';
import { Task } from '@/types/task';
import { ContextSuggest, ProjectSuggest } from '@/components/ui/inputs/AutoComplete';
import { t } from "@/translations/helper";
import { MarkdownRendererComponent } from "@/components/ui/renderers/MarkdownRenderer";
import { StatusComponent } from "@/components/ui/feedback/StatusIndicator";
import { Task } from "@/types/task";
import {
ContextSuggest,
ProjectSuggest,
} from "@/components/ui/inputs/AutoComplete";
import {
TimeParsingService,
DEFAULT_TIME_PARSING_CONFIG,
ParsedTimeResult,
LineParseResult,
} from '@/services/time-parsing-service';
import { SuggestManager, UniversalEditorSuggest } from '@/components/ui/suggest';
} from "@/services/time-parsing-service";
import {
SuggestManager,
UniversalEditorSuggest,
} from "@/components/ui/suggest";
interface TaskMetadata {
startDate?: Date;
@ -652,7 +661,7 @@ export class QuickCaptureModal extends Modal {
// Step 6: Check if line is already a task or a list item
const isTaskOrList = cleanedLine
.trim()
.match(/^(-|\d+\.|\*|\+)(\s+\[[^\]]+\])?/);
.match(/^(-|\d+\.|\*|\+)(\s+\[[^\]\[]+\])?/);
if (isSubTask) {
// Don't add metadata to sub-tasks, but still clean time expressions

View file

@ -76,7 +76,7 @@ export function clearAllMarks(markdown: string): string {
// Special handling for tilde prefix dates: remove ~ and 📅 but keep date
cleanedMarkdown = cleanedMarkdown.replace(/\s*~\s*📅\s*/g, " ");
// Remove date fields (symbol followed by date) - normal case
symbolsToRemove.forEach((symbol) => {
if (!symbol) return; // Should be redundant due to filter, but safe
@ -118,7 +118,7 @@ export function clearAllMarks(markdown: string): string {
const escapedOtherSymbols = symbolsToRemove
.map((s) => s!.replace(/[.*+?^${}()|[\\\]]/g, "\\$&"))
.join("");
// Add escaped non-date symbols to lookahead
const escapedNonDateSymbols = ["🆔", "⛔", "🏁"]
.map((s) => s.replace(/[.*+?^${}()|[\\\]]/g, "\\$&"))
@ -232,7 +232,7 @@ export function clearAllMarks(markdown: string): string {
// Remove tags from temporary markdown (where links/code are placeholders)
tempMarkdown = removeTagsWithLinkProtection(tempMarkdown);
// Remove context tags from temporary markdown
// Remove context tags from temporary markdown
tempMarkdown = tempMarkdown.replace(/@[\w-]+/g, "");
// Remove target location patterns (like "target: office 📁")
@ -240,7 +240,10 @@ export function clearAllMarks(markdown: string): string {
tempMarkdown = tempMarkdown.replace(/\s*📁\s*/g, " ");
// Remove any remaining simple tags but preserve special tags like #123-123-123
tempMarkdown = tempMarkdown.replace(/#(?![0-9-]+\b)[^\u2000-\u206F\u2E00-\u2E7F'!"#$%&()*+,.:;<=>?@^`{|}~\[\]\\\s]+/g, "");
tempMarkdown = tempMarkdown.replace(
/#(?![0-9-]+\b)[^\u2000-\u206F\u2E00-\u2E7F'!"#$%&()*+,.:;<=>?@^`{|}~\[\]\\\s]+/g,
""
);
// Remove any remaining tilde symbols (~ symbol) that weren't handled by the special case
tempMarkdown = tempMarkdown.replace(/\s+~\s+/g, " ");
@ -254,7 +257,7 @@ export function clearAllMarks(markdown: string): string {
// Task marker and final cleaning (applied to the string with links/code restored)
tempMarkdown = tempMarkdown.replace(
/^([\s>]*)?(-|\d+\.|\*|\+)\s\[(.)\]\s*/,
/^([\s>]*)?(-|\d+\.|\*|\+)\s\[([^\[\]]{1})\]\s*/,
""
);
tempMarkdown = tempMarkdown.replace(/^# /, "");

View file

@ -18,7 +18,7 @@ import "@/styles/task-gutter.css";
import { getConfig } from "@/common/task-parser-config";
import { TaskParserConfig } from "@/types/TaskParserConfig";
const taskRegex = /^(([\s>]*)?(-|\d+\.|\*|\+)\s\[(.)\])\s+(.*)$/m;
const taskRegex = /^(([\s>]*)?(-|\d+\.|\*|\+)\s\[([^\[\]]{1})\])\s+(.*)$/m;
// Task icon marker
class TaskGutterMarker extends GutterMarker {
@ -113,7 +113,7 @@ const showTaskDetails = (
if (plugin.writeAPI) {
await plugin.writeAPI.updateTask({
taskId: updatedTask.id,
updates: updatedTask
updates: updatedTask,
});
}
};
@ -147,7 +147,10 @@ const getTaskFromLine = (
): Task | null => {
try {
// Try to get the task from dataflow index first
if (plugin.dataflowOrchestrator && plugin.settings.projectConfig?.enableEnhancedProject) {
if (
plugin.dataflowOrchestrator &&
plugin.settings.projectConfig?.enableEnhancedProject
) {
try {
// Try to find the task by ID in the existing index
const taskId = `${filePath}-L${lineNum}`;
@ -164,18 +167,25 @@ const getTaskFromLine = (
// Fallback to direct parser
if (!taskParser) {
taskParser = new MarkdownTaskParser(
getConfig(plugin.settings.preferMetadataFormat, plugin) as TaskParserConfig
getConfig(
plugin.settings.preferMetadataFormat,
plugin
) as TaskParserConfig
);
}
const task = taskParser.parseTask(line, filePath, lineNum);
// If we have a task and enhanced project is enabled, ensure the ID matches what Dataflow expects
if (task && plugin.dataflowOrchestrator && plugin.settings.projectConfig?.enableEnhancedProject) {
if (
task &&
plugin.dataflowOrchestrator &&
plugin.settings.projectConfig?.enableEnhancedProject
) {
// Ensure the task ID matches the format used by Dataflow
task.id = `${filePath}-L${lineNum}`;
}
return task;
} catch (error) {
console.error("Error parsing task:", error);