From 38a0eeb1603062e730f31006e6651a30bb7b772e Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:08:02 +0600 Subject: [PATCH 1/9] refactor: . add li parameter to taskToHtml() --- src/TaskLineRenderer.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index cbf1bda815..4220fec2b1 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -97,7 +97,7 @@ export class TaskLineRenderer { const textSpan = document.createElement('span'); li.appendChild(textSpan); textSpan.classList.add('tasks-list-text'); - const attributes = await this.taskToHtml(task, textSpan); + const attributes = await this.taskToHtml(task, textSpan, li); for (const key in attributes) li.dataset[key] = attributes[key]; // NOTE: this area is mentioned in `CONTRIBUTING.md` under "How does Tasks handle status changes". When @@ -142,7 +142,11 @@ export class TaskLineRenderer { return li; } - private async taskToHtml(task: Task, parentElement: HTMLElement): Promise { + private async taskToHtml( + task: Task, + parentElement: HTMLElement, + _li: HTMLLIElement, + ): Promise { let allAttributes: AttributesDictionary = {}; const taskLayout = new TaskLayout(this.layoutOptions); const emojiSerializer = TASK_FORMATS.tasksPluginEmoji.taskSerializer; From efd1e669dc017fa43633c3fe9d2b00f5baf17db0 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:10:42 +0600 Subject: [PATCH 2/9] refactor: - taskToHtml() now applies attributes --- src/TaskLineRenderer.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index 4220fec2b1..da7ca41cda 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -97,8 +97,7 @@ export class TaskLineRenderer { const textSpan = document.createElement('span'); li.appendChild(textSpan); textSpan.classList.add('tasks-list-text'); - const attributes = await this.taskToHtml(task, textSpan, li); - for (const key in attributes) li.dataset[key] = attributes[key]; + await this.taskToHtml(task, textSpan, li); // NOTE: this area is mentioned in `CONTRIBUTING.md` under "How does Tasks handle status changes". When // moving the code, remember to update that reference too. @@ -142,11 +141,7 @@ export class TaskLineRenderer { return li; } - private async taskToHtml( - task: Task, - parentElement: HTMLElement, - _li: HTMLLIElement, - ): Promise { + private async taskToHtml(task: Task, parentElement: HTMLElement, li: HTMLLIElement): Promise { let allAttributes: AttributesDictionary = {}; const taskLayout = new TaskLayout(this.layoutOptions); const emojiSerializer = TASK_FORMATS.tasksPluginEmoji.taskSerializer; @@ -198,6 +193,8 @@ export class TaskLineRenderer { allAttributes = { ...allAttributes, ...priorityDataAttribute }; } + for (const key in allAttributes) li.dataset[key] = allAttributes[key]; + return allAttributes; } From 2a7f9adc722f326aed5d079ee320cec3f5c3c4a9 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:11:28 +0600 Subject: [PATCH 3/9] refactor: . remove return type from taskToHtml() --- src/TaskLineRenderer.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index da7ca41cda..7b0f30b6a0 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -141,7 +141,7 @@ export class TaskLineRenderer { return li; } - private async taskToHtml(task: Task, parentElement: HTMLElement, li: HTMLLIElement): Promise { + private async taskToHtml(task: Task, parentElement: HTMLElement, li: HTMLLIElement): Promise { let allAttributes: AttributesDictionary = {}; const taskLayout = new TaskLayout(this.layoutOptions); const emojiSerializer = TASK_FORMATS.tasksPluginEmoji.taskSerializer; @@ -194,8 +194,6 @@ export class TaskLineRenderer { } for (const key in allAttributes) li.dataset[key] = allAttributes[key]; - - return allAttributes; } /* From ef5d46e5e8812f7632a574372fc3f06a7e35d673 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:18:17 +0600 Subject: [PATCH 4/9] refactor: . rename FieldLayouts to TaskFieldRenderer class --- src/TaskFieldRenderer.ts | 4 ++-- src/TaskLineRenderer.ts | 4 ++-- tests/TaskFieldRenderer.test.ts | 8 ++++---- tests/TaskLineRenderer.test.ts | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/TaskFieldRenderer.ts b/src/TaskFieldRenderer.ts index 1c8f7cf909..efadf9396f 100644 --- a/src/TaskFieldRenderer.ts +++ b/src/TaskFieldRenderer.ts @@ -5,7 +5,7 @@ import type { TaskLayoutComponent } from './TaskLayout'; export type AttributesDictionary = { [key: string]: string }; -export class FieldLayouts { +export class TaskFieldRenderer { private readonly details = FieldLayoutDetails; /** @@ -107,7 +107,7 @@ export class FieldLayoutDetail { } /** - * Shall be called only by {@link FieldLayouts}. Use that class if you need the data attributes. + * Shall be called only by {@link TaskFieldRenderer}. Use that class if you need the data attributes. * * @returns the data attribute, associated to with a task's component, added in the task's ``. * For example, a task with medium priority and done yesterday will have diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index 7b0f30b6a0..3bb7186576 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -5,11 +5,11 @@ import { TASK_FORMATS, getSettings } from './Config/Settings'; import { replaceTaskWithTasks } from './File'; import type { Task } from './Task'; import * as taskModule from './Task'; -import { type AttributesDictionary, FieldLayouts } from './TaskFieldRenderer'; +import { type AttributesDictionary, TaskFieldRenderer } from './TaskFieldRenderer'; import type { LayoutOptions, TaskLayoutComponent } from './TaskLayout'; import { TaskLayout } from './TaskLayout'; -const fieldLayouts = new FieldLayouts(); +const fieldLayouts = new TaskFieldRenderer(); /** * The function used to render a Markdown task line into an existing HTML element. diff --git a/tests/TaskFieldRenderer.test.ts b/tests/TaskFieldRenderer.test.ts index da36c42dd9..cd575267e4 100644 --- a/tests/TaskFieldRenderer.test.ts +++ b/tests/TaskFieldRenderer.test.ts @@ -2,7 +2,7 @@ * @jest-environment jsdom */ import moment from 'moment'; -import { FieldLayoutDetail, FieldLayouts } from '../src/TaskFieldRenderer'; +import { FieldLayoutDetail, TaskFieldRenderer } from '../src/TaskFieldRenderer'; import { TaskBuilder } from './TestingTools/TaskBuilder'; window.moment = moment; @@ -18,7 +18,7 @@ describe('Field Layouts Container tests', () => { }); it('should get the data attribute of an existing component (date)', () => { - const container = new FieldLayouts(); + const container = new TaskFieldRenderer(); const task = new TaskBuilder().dueDate('2023-11-20').build(); const dueDateDataAttribute = container.dataAttribute('dueDate', task); @@ -28,7 +28,7 @@ describe('Field Layouts Container tests', () => { }); it('should get the data attribute of an existing component (not date)', () => { - const container = new FieldLayouts(); + const container = new TaskFieldRenderer(); const task = TaskBuilder.createFullyPopulatedTask(); const dueDateDataAttribute = container.dataAttribute('priority', task); @@ -38,7 +38,7 @@ describe('Field Layouts Container tests', () => { }); it('should return empty data attributes dictionary for a missing component', () => { - const container = new FieldLayouts(); + const container = new TaskFieldRenderer(); const task = new TaskBuilder().build(); const dueDateDataAttribute = container.dataAttribute('recurrenceRule', task); diff --git a/tests/TaskLineRenderer.test.ts b/tests/TaskLineRenderer.test.ts index 3a862e28c2..94bb44420a 100644 --- a/tests/TaskLineRenderer.test.ts +++ b/tests/TaskLineRenderer.test.ts @@ -8,7 +8,7 @@ import { resetSettings, updateSettings } from '../src/Config/Settings'; import { DateParser } from '../src/Query/DateParser'; import type { Task } from '../src/Task'; import { TaskRegularExpressions } from '../src/Task'; -import { type AttributesDictionary, FieldLayouts } from '../src/TaskFieldRenderer'; +import { type AttributesDictionary, TaskFieldRenderer } from '../src/TaskFieldRenderer'; import { LayoutOptions } from '../src/TaskLayout'; import type { TextRenderer } from '../src/TaskLineRenderer'; import { TaskLineRenderer } from '../src/TaskLineRenderer'; @@ -19,7 +19,7 @@ import { TaskBuilder } from './TestingTools/TaskBuilder'; jest.mock('obsidian'); window.moment = moment; -const fieldLayouts = new FieldLayouts(); +const fieldLayouts = new TaskFieldRenderer(); /** * Creates a dummy 'parent element' to host a task render, renders a task inside it, From 5a175505d34613c955359b1d22368c8169966cde Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:24:23 +0600 Subject: [PATCH 5/9] refactor: . rename FieldLayoutDetail to TaskFieldHTMLData --- src/TaskFieldRenderer.ts | 46 ++++++++++++++++----------------- tests/TaskFieldRenderer.test.ts | 6 ++--- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/TaskFieldRenderer.ts b/src/TaskFieldRenderer.ts index efadf9396f..3de385a8cb 100644 --- a/src/TaskFieldRenderer.ts +++ b/src/TaskFieldRenderer.ts @@ -16,7 +16,7 @@ export class TaskFieldRenderer { * * If the data attribute is absent in the task, an empty {@link AttributesDictionary} is returned. * - * For detailed calculation see {@link FieldLayoutDetail.dataAttribute}. + * For detailed calculation see {@link TaskFieldHTMLData.dataAttribute}. * * @param component the component of the task for which the data attribute has to be generated. * @param task the task from which the data shall be taken @@ -36,7 +36,7 @@ export class TaskFieldRenderer { type AttributeValueCalculator = (component: TaskLayoutComponent, task: Task) => string; -export class FieldLayoutDetail { +export class TaskFieldHTMLData { public readonly className: string; private readonly attributeName: string; private readonly attributeValueCalculator: AttributeValueCalculator; @@ -86,14 +86,14 @@ export class FieldLayoutDetail { * @param className CSS class that describes what the component is, e.g. a due date or a priority. * * @param attributeName if the component needs data attribute (`data-key="value"`) this is the key. - * Otherwise, set this to {@link FieldLayoutDetail.noAttributeName}. + * Otherwise, set this to {@link TaskFieldHTMLData.noAttributeName}. * * @param attributeValueCalculator And this is the value calculator. - * Set to {@link FieldLayoutDetail.noAttributeValueCalculator} if the component has no data attribute. + * Set to {@link TaskFieldHTMLData.noAttributeValueCalculator} if the component has no data attribute. * * There is a relation between {@link attributeName} and {@link attributeValueCalculator}. * For a component to have the data attribute, both need to be set to values other than - * {@link FieldLayoutDetail.noAttributeName} and {@link FieldLayoutDetail.noAttributeValueCalculator} respectively. + * {@link TaskFieldHTMLData.noAttributeName} and {@link TaskFieldHTMLData.noAttributeValueCalculator} respectively. * This means that having an empty data attribute (`data-key=""`) is not supported. */ constructor(className: string, attributeName: string, attributeValueCalculator: AttributeValueCalculator) { @@ -113,7 +113,7 @@ export class FieldLayoutDetail { * For example, a task with medium priority and done yesterday will have * `data-task-priority="medium" data-task-due="past-1d" ` in its data attributes. * - * Calculation of the value is done with {@link FieldLayoutDetail.attributeValueCalculator}. + * Calculation of the value is done with {@link TaskFieldHTMLData.attributeValueCalculator}. * * @param component the component of the task for which the data attribute has to be generated. * @param task the task from which the data shall be taken @@ -121,7 +121,7 @@ export class FieldLayoutDetail { public dataAttribute(component: TaskLayoutComponent, task: Task) { const dataAttribute: AttributesDictionary = {}; - if (this.attributeName !== FieldLayoutDetail.noAttributeName) { + if (this.attributeName !== TaskFieldHTMLData.noAttributeName) { dataAttribute[this.attributeName] = this.attributeValueCalculator(component, task); } @@ -129,32 +129,32 @@ export class FieldLayoutDetail { } } -const FieldLayoutDetails: { [c in TaskLayoutComponent]: FieldLayoutDetail } = { +const FieldLayoutDetails: { [c in TaskLayoutComponent]: TaskFieldHTMLData } = { // NEW_TASK_FIELD_EDIT_REQUIRED - createdDate: new FieldLayoutDetail('task-created', 'taskCreated', FieldLayoutDetail.dateAttributeCalculator), - dueDate: new FieldLayoutDetail('task-due', 'taskDue', FieldLayoutDetail.dateAttributeCalculator), - startDate: new FieldLayoutDetail('task-start', 'taskStart', FieldLayoutDetail.dateAttributeCalculator), - scheduledDate: new FieldLayoutDetail('task-scheduled', 'taskScheduled', FieldLayoutDetail.dateAttributeCalculator), - doneDate: new FieldLayoutDetail('task-done', 'taskDone', FieldLayoutDetail.dateAttributeCalculator), + createdDate: new TaskFieldHTMLData('task-created', 'taskCreated', TaskFieldHTMLData.dateAttributeCalculator), + dueDate: new TaskFieldHTMLData('task-due', 'taskDue', TaskFieldHTMLData.dateAttributeCalculator), + startDate: new TaskFieldHTMLData('task-start', 'taskStart', TaskFieldHTMLData.dateAttributeCalculator), + scheduledDate: new TaskFieldHTMLData('task-scheduled', 'taskScheduled', TaskFieldHTMLData.dateAttributeCalculator), + doneDate: new TaskFieldHTMLData('task-done', 'taskDone', TaskFieldHTMLData.dateAttributeCalculator), - description: new FieldLayoutDetail( + description: new TaskFieldHTMLData( 'task-description', - FieldLayoutDetail.noAttributeName, - FieldLayoutDetail.noAttributeValueCalculator, + TaskFieldHTMLData.noAttributeName, + TaskFieldHTMLData.noAttributeValueCalculator, ), - recurrenceRule: new FieldLayoutDetail( + recurrenceRule: new TaskFieldHTMLData( 'task-recurring', - FieldLayoutDetail.noAttributeName, - FieldLayoutDetail.noAttributeValueCalculator, + TaskFieldHTMLData.noAttributeName, + TaskFieldHTMLData.noAttributeValueCalculator, ), - priority: new FieldLayoutDetail('task-priority', 'taskPriority', (_component, task) => { + priority: new TaskFieldHTMLData('task-priority', 'taskPriority', (_component, task) => { return PriorityTools.priorityNameUsingNormal(task.priority).toLocaleLowerCase(); }), - blockLink: new FieldLayoutDetail( + blockLink: new TaskFieldHTMLData( 'task-block-link', - FieldLayoutDetail.noAttributeName, - FieldLayoutDetail.noAttributeValueCalculator, + TaskFieldHTMLData.noAttributeName, + TaskFieldHTMLData.noAttributeValueCalculator, ), }; diff --git a/tests/TaskFieldRenderer.test.ts b/tests/TaskFieldRenderer.test.ts index cd575267e4..0e52a81985 100644 --- a/tests/TaskFieldRenderer.test.ts +++ b/tests/TaskFieldRenderer.test.ts @@ -2,7 +2,7 @@ * @jest-environment jsdom */ import moment from 'moment'; -import { FieldLayoutDetail, TaskFieldRenderer } from '../src/TaskFieldRenderer'; +import { TaskFieldHTMLData, TaskFieldRenderer } from '../src/TaskFieldRenderer'; import { TaskBuilder } from './TestingTools/TaskBuilder'; window.moment = moment; @@ -49,14 +49,14 @@ describe('Field Layouts Container tests', () => { describe('Field Layout Detail tests', () => { it('should supply a class name and a data attribute name', () => { - const fieldLayoutDetail = new FieldLayoutDetail('stuff', 'taskAttribute', () => { + const fieldLayoutDetail = new TaskFieldHTMLData('stuff', 'taskAttribute', () => { return ''; }); expect(fieldLayoutDetail.className).toEqual('stuff'); }); it('should return a data attribute', () => { - const fieldLayoutDetail = new FieldLayoutDetail('dataAttributeTest', 'aKey', () => { + const fieldLayoutDetail = new TaskFieldHTMLData('dataAttributeTest', 'aKey', () => { return 'aValue'; }); const dataAttribute = fieldLayoutDetail.dataAttribute('description', new TaskBuilder().build()); From da35c771757ddab8dce07b6fe5262c248d03e4c7 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:27:41 +0600 Subject: [PATCH 6/9] refactor: . rename FieldLayoutDetails to taskFieldHTMLData --- src/TaskFieldRenderer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TaskFieldRenderer.ts b/src/TaskFieldRenderer.ts index 3de385a8cb..008175723b 100644 --- a/src/TaskFieldRenderer.ts +++ b/src/TaskFieldRenderer.ts @@ -6,10 +6,10 @@ import type { TaskLayoutComponent } from './TaskLayout'; export type AttributesDictionary = { [key: string]: string }; export class TaskFieldRenderer { - private readonly details = FieldLayoutDetails; + private readonly details = taskFieldHTMLData; /** - * Searches for the component among the {@link FieldLayoutDetails} and gets its data attribute + * Searches for the component among the {@link taskFieldHTMLData} and gets its data attribute * in a given task. The data attribute shall be added in the task's ``. * For example, a task with medium priority and done yesterday will have * `data-task-priority="medium" data-task-due="past-1d" ` in its data attributes. @@ -129,7 +129,7 @@ export class TaskFieldHTMLData { } } -const FieldLayoutDetails: { [c in TaskLayoutComponent]: TaskFieldHTMLData } = { +const taskFieldHTMLData: { [c in TaskLayoutComponent]: TaskFieldHTMLData } = { // NEW_TASK_FIELD_EDIT_REQUIRED createdDate: new TaskFieldHTMLData('task-created', 'taskCreated', TaskFieldHTMLData.dateAttributeCalculator), dueDate: new TaskFieldHTMLData('task-due', 'taskDue', TaskFieldHTMLData.dateAttributeCalculator), From 88f540c5f42828da955aedc1e90ec20b14c74da3 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:28:12 +0600 Subject: [PATCH 7/9] refactor: . rename TaskFieldRenderer.details to data --- src/TaskFieldRenderer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TaskFieldRenderer.ts b/src/TaskFieldRenderer.ts index 008175723b..a3658f2366 100644 --- a/src/TaskFieldRenderer.ts +++ b/src/TaskFieldRenderer.ts @@ -6,7 +6,7 @@ import type { TaskLayoutComponent } from './TaskLayout'; export type AttributesDictionary = { [key: string]: string }; export class TaskFieldRenderer { - private readonly details = taskFieldHTMLData; + private readonly data = taskFieldHTMLData; /** * Searches for the component among the {@link taskFieldHTMLData} and gets its data attribute @@ -22,7 +22,7 @@ export class TaskFieldRenderer { * @param task the task from which the data shall be taken */ public dataAttribute(component: TaskLayoutComponent, task: Task) { - return this.details[component].dataAttribute(component, task); + return this.data[component].dataAttribute(component, task); } /** @@ -30,7 +30,7 @@ export class TaskFieldRenderer { * @param component of the task. */ public className(component: TaskLayoutComponent) { - return this.details[component].className; + return this.data[component].className; } } From 63191e0aaf156bb093c228322be18e9e73706292 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:29:54 +0600 Subject: [PATCH 8/9] refactor: . rename local variables --- src/TaskLineRenderer.ts | 10 ++-- tests/TaskLineRenderer.test.ts | 94 +++++++++++++++++----------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index 3bb7186576..975029de42 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -9,7 +9,7 @@ import { type AttributesDictionary, TaskFieldRenderer } from './TaskFieldRendere import type { LayoutOptions, TaskLayoutComponent } from './TaskLayout'; import { TaskLayout } from './TaskLayout'; -const fieldLayouts = new TaskFieldRenderer(); +const fieldRenderer = new TaskFieldRenderer(); /** * The function used to render a Markdown task line into an existing HTML element. @@ -166,11 +166,11 @@ export class TaskLineRenderer { this.addInternalClasses(component, internalSpan); // Add the component's CSS class describing what this component is (priority, due date etc.) - const componentClass = fieldLayouts.className(component); + const componentClass = fieldRenderer.className(component); span.classList.add(...[componentClass]); // Add the component's attribute ('priority-medium', 'due-past-1d' etc.) - const componentDataAttribute = fieldLayouts.dataAttribute(component, task); + const componentDataAttribute = fieldRenderer.dataAttribute(component, task); for (const key in componentDataAttribute) span.dataset[key] = componentDataAttribute[key]; allAttributes = { ...allAttributes, ...componentDataAttribute }; } @@ -179,7 +179,7 @@ export class TaskLineRenderer { // Now build classes for the hidden task components without rendering them for (const component of taskLayout.hiddenTaskLayoutComponents) { - const hiddenComponentDataAttribute = fieldLayouts.dataAttribute(component, task); + const hiddenComponentDataAttribute = fieldRenderer.dataAttribute(component, task); allAttributes = { ...allAttributes, ...hiddenComponentDataAttribute }; } @@ -189,7 +189,7 @@ export class TaskLineRenderer { // So if the priority was not rendered, force it through the pipe of getting the component data for the // priority field. if (allAttributes.taskPriority === undefined) { - const priorityDataAttribute = fieldLayouts.dataAttribute('priority', task); + const priorityDataAttribute = fieldRenderer.dataAttribute('priority', task); allAttributes = { ...allAttributes, ...priorityDataAttribute }; } diff --git a/tests/TaskLineRenderer.test.ts b/tests/TaskLineRenderer.test.ts index 94bb44420a..58f3092a57 100644 --- a/tests/TaskLineRenderer.test.ts +++ b/tests/TaskLineRenderer.test.ts @@ -19,7 +19,7 @@ import { TaskBuilder } from './TestingTools/TaskBuilder'; jest.mock('obsidian'); window.moment = moment; -const fieldLayouts = new TaskFieldRenderer(); +const fieldRenderer = new TaskFieldRenderer(); /** * Creates a dummy 'parent element' to host a task render, renders a task inside it, @@ -59,7 +59,7 @@ function getOtherLayoutComponents(parentElement: HTMLElement): string[] { const textSpan = getTextSpan(parentElement); const components: string[] = []; for (const childSpan of Array.from(textSpan.children)) { - if (childSpan.classList.contains(fieldLayouts.className('description'))) continue; + if (childSpan.classList.contains(fieldRenderer.className('description'))) continue; if (childSpan?.textContent) components.push(childSpan.textContent); } return components; @@ -352,19 +352,19 @@ describe('task line rendering', () => { await testComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', {}, - fieldLayouts.className('priority'), + fieldRenderer.className('priority'), { taskPriority: 'high' }, ); await testComponentClasses( '- [ ] Full task 🔼 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', {}, - fieldLayouts.className('priority'), + fieldRenderer.className('priority'), { taskPriority: 'medium' }, ); await testComponentClasses( '- [ ] Full task 🔽 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', {}, - fieldLayouts.className('priority'), + fieldRenderer.className('priority'), { taskPriority: 'low' }, ); }); @@ -373,174 +373,174 @@ describe('task line rendering', () => { await testComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', {}, - fieldLayouts.className('recurrenceRule'), + fieldRenderer.className('recurrenceRule'), {}, ); }); it('adds a correct "today" CSS class to dates', async () => { const today = DateParser.parseDate('today').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${today}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${today}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'today', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${today}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${today}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'today', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${today}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${today}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'today', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${today}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${today}`, {}, fieldRenderer.className('startDate'), { taskStart: 'today', }); - await testComponentClasses(`- [x] Done task ✅ ${today}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${today}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'today', }); }); it('adds a correct "future-1d" CSS class to dates', async () => { const future = DateParser.parseDate('tomorrow').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'future-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'future-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'future-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldRenderer.className('startDate'), { taskStart: 'future-1d', }); - await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'future-1d', }); }); it('adds a correct "future-7d" CSS class to dates', async () => { const future = DateParser.parseDate('in 7 days').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'future-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'future-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'future-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldRenderer.className('startDate'), { taskStart: 'future-7d', }); - await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'future-7d', }); }); it('adds a correct "past-1d" CSS class to dates', async () => { const past = DateParser.parseDate('yesterday').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'past-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'past-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'past-1d', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldRenderer.className('startDate'), { taskStart: 'past-1d', }); - await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'past-1d', }); }); it('adds a correct "past-7d" CSS class to dates', async () => { const past = DateParser.parseDate('7 days ago').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'past-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'past-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'past-7d', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldRenderer.className('startDate'), { taskStart: 'past-7d', }); - await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'past-7d', }); }); it('adds the classes "...future-far" and "...past-far" to dates that are further than 7 days', async () => { const future = DateParser.parseDate('in 8 days').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${future}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'future-far', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${future}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'future-far', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${future}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'future-far', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${future}`, {}, fieldRenderer.className('startDate'), { taskStart: 'future-far', }); - await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${future}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'future-far', }); const past = DateParser.parseDate('8 days ago').format(TaskRegularExpressions.dateFormat); - await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldLayouts.className('createdDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ➕ ${past}`, {}, fieldRenderer.className('createdDate'), { taskCreated: 'past-far', }); - await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldLayouts.className('dueDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 📅 ${past}`, {}, fieldRenderer.className('dueDate'), { taskDue: 'past-far', }); - await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldLayouts.className('scheduledDate'), { + await testComponentClasses(`- [ ] Full task ⏫ ⏳ ${past}`, {}, fieldRenderer.className('scheduledDate'), { taskScheduled: 'past-far', }); - await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldLayouts.className('startDate'), { + await testComponentClasses(`- [ ] Full task ⏫ 🛫 ${past}`, {}, fieldRenderer.className('startDate'), { taskStart: 'past-far', }); - await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldLayouts.className('doneDate'), { + await testComponentClasses(`- [x] Done task ✅ ${past}`, {}, fieldRenderer.className('doneDate'), { taskDone: 'past-far', }); }); it('does not add specific classes to invalid dates', async () => { - await testComponentClasses('- [ ] Full task ⏫ 📅 2023-02-29', {}, fieldLayouts.className('dueDate'), {}); + await testComponentClasses('- [ ] Full task ⏫ 📅 2023-02-29', {}, fieldRenderer.className('dueDate'), {}); }); it('does not render hidden components but sets their specific classes to the upper li element', async () => { await testHiddenComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', { hidePriority: true }, - fieldLayouts.className('priority'), + fieldRenderer.className('priority'), { taskPriority: 'high' }, ); await testHiddenComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 ➕ 2022-07-04 🔁 every day', { hideCreatedDate: true }, - fieldLayouts.className('createdDate'), + fieldRenderer.className('createdDate'), { taskCreated: 'past-far' }, ); await testHiddenComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', { hideDueDate: true }, - fieldLayouts.className('dueDate'), + fieldRenderer.className('dueDate'), { taskDue: 'past-far' }, ); await testHiddenComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', { hideScheduledDate: true }, - fieldLayouts.className('scheduledDate'), + fieldRenderer.className('scheduledDate'), { taskScheduled: 'past-far' }, ); await testHiddenComponentClasses( '- [ ] Full task ⏫ 📅 2022-07-02 ⏳ 2022-07-03 🛫 2022-07-04 🔁 every day', { hideStartDate: true }, - fieldLayouts.className('startDate'), + fieldRenderer.className('startDate'), { taskStart: 'past-far' }, ); }); From 1625bcdd1cdd191536a17f30833285808a92b09a Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Wed, 22 Nov 2023 17:34:29 +0600 Subject: [PATCH 9/9] refactor: - update LI.dataset earlier on --- src/TaskLineRenderer.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts index 975029de42..a50cf38ab2 100644 --- a/src/TaskLineRenderer.ts +++ b/src/TaskLineRenderer.ts @@ -5,7 +5,7 @@ import { TASK_FORMATS, getSettings } from './Config/Settings'; import { replaceTaskWithTasks } from './File'; import type { Task } from './Task'; import * as taskModule from './Task'; -import { type AttributesDictionary, TaskFieldRenderer } from './TaskFieldRenderer'; +import { TaskFieldRenderer } from './TaskFieldRenderer'; import type { LayoutOptions, TaskLayoutComponent } from './TaskLayout'; import { TaskLayout } from './TaskLayout'; @@ -142,7 +142,6 @@ export class TaskLineRenderer { } private async taskToHtml(task: Task, parentElement: HTMLElement, li: HTMLLIElement): Promise { - let allAttributes: AttributesDictionary = {}; const taskLayout = new TaskLayout(this.layoutOptions); const emojiSerializer = TASK_FORMATS.tasksPluginEmoji.taskSerializer; // Render and build classes for all the task's visible components @@ -172,7 +171,7 @@ export class TaskLineRenderer { // Add the component's attribute ('priority-medium', 'due-past-1d' etc.) const componentDataAttribute = fieldRenderer.dataAttribute(component, task); for (const key in componentDataAttribute) span.dataset[key] = componentDataAttribute[key]; - allAttributes = { ...allAttributes, ...componentDataAttribute }; + for (const key in componentDataAttribute) li.dataset[key] = componentDataAttribute[key]; } } } @@ -180,7 +179,7 @@ export class TaskLineRenderer { // Now build classes for the hidden task components without rendering them for (const component of taskLayout.hiddenTaskLayoutComponents) { const hiddenComponentDataAttribute = fieldRenderer.dataAttribute(component, task); - allAttributes = { ...allAttributes, ...hiddenComponentDataAttribute }; + for (const key in hiddenComponentDataAttribute) li.dataset[key] = hiddenComponentDataAttribute[key]; } // If a task has no priority field set, its priority will not be rendered as part of the loop above and @@ -188,12 +187,10 @@ export class TaskLineRenderer { // In such a case we want the upper task LI element to mark the task has a 'normal' priority. // So if the priority was not rendered, force it through the pipe of getting the component data for the // priority field. - if (allAttributes.taskPriority === undefined) { + if (li.dataset.taskPriority === undefined) { const priorityDataAttribute = fieldRenderer.dataAttribute('priority', task); - allAttributes = { ...allAttributes, ...priorityDataAttribute }; + for (const key in priorityDataAttribute) li.dataset[key] = priorityDataAttribute[key]; } - - for (const key in allAttributes) li.dataset[key] = allAttributes[key]; } /*