1
0

feat: task checklist improvements (#797)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/797
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This commit is contained in:
konrad
2021-09-29 18:31:14 +00:00
parent d47b13647e
commit 96523f1fbf
9 changed files with 232 additions and 37 deletions

View File

@ -0,0 +1,91 @@
import {findCheckboxesInText, getChecklistStatistics} from './checklistFromText'
describe('Find checklists in text', () => {
it('should find no checkbox', () => {
const text: string = 'Lorem Ipsum'
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(0)
})
it('should find multiple checkboxes', () => {
const text: string = `* [ ] Lorem Ipsum
* [ ] Dolor sit amet
Here's some text in between
* [x] Dolor sit amet
- [ ] Dolor sit amet`
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(4)
expect(checkboxes[0]).toBe(0)
expect(checkboxes[1]).toBe(18)
expect(checkboxes[2]).toBe(69)
})
it('should find one checkbox with *', () => {
const text: string = '* [ ] Lorem Ipsum'
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(1)
expect(checkboxes[0]).toBe(0)
})
it('should find one checkbox with -', () => {
const text: string = '- [ ] Lorem Ipsum'
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(1)
expect(checkboxes[0]).toBe(0)
})
it('should find one checked checkbox with *', () => {
const text: string = '* [x] Lorem Ipsum'
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(1)
expect(checkboxes[0]).toBe(0)
})
it('should find one checked checkbox with -', () => {
const text: string = '- [x] Lorem Ipsum'
const checkboxes = findCheckboxesInText(text)
expect(checkboxes).toHaveLength(1)
expect(checkboxes[0]).toBe(0)
})
})
describe('Get Checklist Statistics in a Text', () => {
it('should find no checkbox', () => {
const text: string = 'Lorem Ipsum'
const stats = getChecklistStatistics(text)
expect(stats.total).toBe(0)
})
it('should find one checkbox', () => {
const text: string = '* [ ] Lorem Ipsum'
const stats = getChecklistStatistics(text)
expect(stats.total).toBe(1)
expect(stats.checked).toBe(0)
})
it('should find one checked checkbox', () => {
const text: string = '* [x] Lorem Ipsum'
const stats = getChecklistStatistics(text)
expect(stats.total).toBe(1)
expect(stats.checked).toBe(1)
})
it('should find multiple mixed and matched', () => {
const text: string = `* [ ] Lorem Ipsum
* [ ] Dolor sit amet
* [x] Dolor sit amet
- [x] Dolor sit amet
Here's some text in between
* [x] Dolor sit amet
- [ ] Dolor sit amet`
const stats = getChecklistStatistics(text)
expect(stats.total).toBe(6)
expect(stats.checked).toBe(3)
})
})

View File

@ -0,0 +1,53 @@
const checked = '[x]'
interface CheckboxStatistics {
total: number
checked: number
}
interface MatchedCheckboxes {
checked: number[]
unchecked: number[]
}
const getCheckboxesInText = (text: string): MatchedCheckboxes => {
const regex = /[*-] \[[ x]]/g
let match
const checkboxes: MatchedCheckboxes = {
checked: [],
unchecked: [],
}
while ((match = regex.exec(text)) !== null) {
if (match[0].endsWith(checked)) {
checkboxes.checked.push(match.index)
} else {
checkboxes.unchecked.push(match.index)
}
}
return checkboxes
}
/**
* Returns the indices where checkboxes start and end in the given text.
*
* @param text
*/
export const findCheckboxesInText = (text: string): number[] => {
const checkboxes = getCheckboxesInText(text)
return [
...checkboxes.checked,
...checkboxes.unchecked,
].sort()
}
export const getChecklistStatistics = (text: string): CheckboxStatistics => {
const checkboxes = getCheckboxesInText(text)
return {
total: checkboxes.checked.length + checkboxes.unchecked.length,
checked: checkboxes.checked.length,
}
}