This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/helpers/parseSubtasksViaIndention.ts

83 lines
2.4 KiB
TypeScript

import {getProjectFromPrefix, PrefixMode} from '@/modules/parseTaskText'
export interface TaskWithParent {
title: string,
parent: string | null,
project: string | null,
}
function cleanupTitle(title: string) {
return title.replace(/^((\* |\+ |- )(\[ \] )?)/g, '')
}
const spaceRegex = /^ */
/**
* @param taskTitles should be multiple lines of task tiles with indention to declare their parent/subtask
* relation between each other.
*/
export function parseSubtasksViaIndention(taskTitles: string, prefixMode: PrefixMode): TaskWithParent[] {
let titles = taskTitles
.split(/[\r\n]+/)
.filter(t => t.replace(/\s/g, '').length > 0) // Remove titles which are empty or only contain spaces / tabs
if (titles.length == 0) {
return []
}
const spaceOnFirstLine = /^(\t| )+/
const spaces = spaceOnFirstLine.exec(titles[0])
if (spaces !== null) {
let spacesToCut = spaces[0].length
titles = titles.map(title => {
const spacesOnThisLine = spaceOnFirstLine.exec(title)
if (spacesOnThisLine === null) {
// This means the current task title does not start with indention, but the very first one did
// To prevent cutting actual task data we now need to update the number of spaces to cut
spacesToCut = 0
}
if (spacesOnThisLine !== null && spacesOnThisLine[0].length < spacesToCut) {
spacesToCut = spacesOnThisLine[0].length
}
return title.substring(spacesToCut)
})
}
return titles.map((title, index) => {
const task: TaskWithParent = {
title: cleanupTitle(title),
parent: null,
project: null,
}
task.project = getProjectFromPrefix(task.title, prefixMode)
if (index === 0) {
return task
}
const matched = spaceRegex.exec(task.title)
const matchedSpaces = matched ? matched[0].length : 0
if (matchedSpaces > 0) {
// Go up the tree to find the first task with less indention than the current one
let pi = 1
let parentSpaces = 0
do {
task.parent = cleanupTitle(titles[index - pi])
pi++
const parentMatched = spaceRegex.exec(task.parent)
parentSpaces = parentMatched ? parentMatched[0].length : 0
} while (parentSpaces >= matchedSpaces)
task.title = cleanupTitle(task.title.replace(spaceRegex, ''))
task.parent = task.parent.replace(spaceRegex, '')
if (task.project === null) {
// This allows to specify a project once for the parent task and inherit it to all subtasks
task.project = getProjectFromPrefix(task.parent, prefixMode)
}
}
return task
})
}