@@ -3,7 +3,6 @@ import { postponeButtonTitle, shouldShowPostponeButton } from '../DateTime/Postp
33import { QueryLayout } from '../Layout/QueryLayout' ;
44import { TaskLayout } from '../Layout/TaskLayout' ;
55import type { GroupDisplayHeading } from '../Query/Group/GroupDisplayHeading' ;
6- import type { TaskGroup } from '../Query/Group/TaskGroup' ;
76import type { QueryResult } from '../Query/QueryResult' ;
87import type { ListItem } from '../Task/ListItem' ;
98import type { Task } from '../Task/Task' ;
@@ -13,6 +12,13 @@ import type { QueryRendererParameters } from './QueryResultsRenderer';
1312import { QueryResultsRendererBase , type QueryResultsRendererGetters } from './QueryResultsRendererBase' ;
1413import { TaskLineRenderer , type TextRenderer , createAndAppendElement } from './TaskLineRenderer' ;
1514
15+ /**
16+ * HTML-specific implementation of {@link QueryResultsRendererBase} abstract class.
17+ *
18+ * @example
19+ * this.htmlRenderer.content = content;
20+ * await this.htmlRenderer.renderQuery(state, tasks);
21+ */
1622export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
1723 // Renders the description in TaskLineRenderer:
1824 protected readonly textRenderer ;
@@ -22,13 +28,13 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
2228 protected readonly obsidianComponent : Component | null ;
2329 protected readonly obsidianApp : App ;
2430
25- // TODO access this via getContent() for now
26- public content : HTMLDivElement | null = null ;
27-
2831 private readonly taskLineRenderer : TaskLineRenderer ;
2932
33+ // document.createElement() creates dummy elements that must be overwritten later
34+ // with the values of elements that will be rendered
35+ public content : HTMLDivElement = document . createElement ( 'div' ) ;
3036 private readonly ulElementStack : HTMLUListElement [ ] = [ ] ;
31- private readonly liElementStack : HTMLLIElement [ ] = [ ] ;
37+ private lastLIElement : HTMLLIElement = document . createElement ( 'li' ) ;
3238
3339 private readonly queryRendererParameters : QueryRendererParameters ;
3440
@@ -63,15 +69,6 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
6369 } ) ;
6470 }
6571
66- private getContent ( ) {
67- // TODO remove throw
68- const content = this . content ;
69- if ( ! content ) {
70- throw new Error ( 'Must initialize content field before calling renderQuery()' ) ;
71- }
72- return content ;
73- }
74-
7572 protected renderSearchResultsHeader ( queryResult : QueryResult ) : void {
7673 this . addCopyButton ( queryResult ) ;
7774 }
@@ -81,22 +78,22 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
8178 }
8279
8380 protected renderErrorMessage ( errorMessage : string ) {
84- const container = createAndAppendElement ( 'div' , this . getContent ( ) ) ;
81+ const container = createAndAppendElement ( 'div' , this . content ) ;
8582 container . innerHTML = '<pre>' + `Tasks query: ${ errorMessage . replace ( / \n / g, '<br>' ) } ` + '</pre>' ;
8683 }
8784
8885 protected renderLoadingMessage ( ) {
89- this . getContent ( ) . textContent = 'Loading Tasks ...' ;
86+ this . content . textContent = 'Loading Tasks ...' ;
9087 }
9188
9289 protected renderExplanation ( explanation : string | null ) {
93- const explanationsBlock = createAndAppendElement ( 'pre' , this . getContent ( ) ) ;
90+ const explanationsBlock = createAndAppendElement ( 'pre' , this . content ) ;
9491 explanationsBlock . classList . add ( 'plugin-tasks-query-explanation' ) ;
9592 explanationsBlock . textContent = explanation ;
9693 }
9794
9895 private addCopyButton ( queryResult : QueryResult ) {
99- const copyButton = createAndAppendElement ( 'button' , this . getContent ( ) ) ;
96+ const copyButton = createAndAppendElement ( 'button' , this . content ) ;
10097 copyButton . textContent = 'Copy results' ;
10198 copyButton . classList . add ( 'plugin-tasks-copy-button' ) ;
10299 copyButton . addEventListener ( 'click' , async ( ) => {
@@ -105,12 +102,9 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
105102 } ) ;
106103 }
107104
108- protected async addTaskGroup ( group : TaskGroup ) : Promise < void > {
109- await this . addTaskList ( group . tasks ) ;
110- }
111-
112105 protected beginTaskList ( ) : void {
113- const taskListContainer = this . ulElementStack . length > 0 ? this . currentLIElement ( ) : this . getContent ( ) ;
106+ const isFirstTaskListInContainer = this . ulElementStack . length === 0 ;
107+ const taskListContainer = isFirstTaskListInContainer ? this . content : this . lastLIElement ;
114108 const taskList = createAndAppendElement ( 'ul' , taskListContainer ) ;
115109
116110 taskList . classList . add (
@@ -134,19 +128,16 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
134128
135129 protected beginListItem ( ) {
136130 const taskList = this . currentULElement ( ) ;
137- const listItemElement = createAndAppendElement ( 'li' , taskList ) ;
138- this . liElementStack . push ( listItemElement ) ;
131+ this . lastLIElement = createAndAppendElement ( 'li' , taskList ) ;
139132 }
140133
141134 protected async addListItem ( listItem : ListItem , listItemIndex : number ) : Promise < void > {
142- const listItemElement = this . currentLIElement ( ) ;
143-
144- await this . taskLineRenderer . renderListItem ( listItemElement , listItem , listItemIndex ) ;
135+ await this . taskLineRenderer . renderListItem ( this . lastLIElement , listItem , listItemIndex ) ;
145136 }
146137
147138 protected async addTask ( task : Task , taskIndex : number ) : Promise < void > {
148139 const isFilenameUnique = this . isFilenameUnique ( { task } , this . queryRendererParameters . allMarkdownFiles ( ) ) ;
149- const listItem = this . currentLIElement ( ) ;
140+ const listItem = this . lastLIElement ;
150141
151142 await this . taskLineRenderer . renderTaskLine ( {
152143 li : listItem ,
@@ -215,7 +206,7 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
215206 header = 'h5' ;
216207 }
217208
218- const headerEl = createAndAppendElement ( header , this . getContent ( ) ) ;
209+ const headerEl = createAndAppendElement ( header , this . content ) ;
219210 headerEl . classList . add ( 'tasks-group-heading' ) ;
220211
221212 if ( this . obsidianComponent === null ) {
@@ -298,7 +289,7 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
298289
299290 private addTaskCount ( queryResult : QueryResult ) {
300291 if ( ! this . getters . query ( ) . queryLayoutOptions . hideTaskCount ) {
301- const taskCount = createAndAppendElement ( 'div' , this . getContent ( ) ) ;
292+ const taskCount = createAndAppendElement ( 'div' , this . content ) ;
302293 taskCount . classList . add ( 'task-count' ) ;
303294 taskCount . textContent = queryResult . totalTasksCountDisplayText ( ) ;
304295 }
@@ -333,8 +324,4 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
333324 private currentULElement ( ) : HTMLUListElement {
334325 return this . ulElementStack [ this . ulElementStack . length - 1 ] ;
335326 }
336-
337- private currentLIElement ( ) {
338- return this . liElementStack [ this . liElementStack . length - 1 ] ;
339- }
340327}
0 commit comments