Suppressing (No heading)
headers in task groups
#1057
Replies: 2 comments 11 replies
-
That is the crux of the matter. And I would like to explore that first of all. So, before discussing implementation details, I would like to know what others think about the proposed behaviour? Is it desirable to REMOVE the group heading Please respond with 👍 or 👎 |
Beta Was this translation helpful? Give feedback.
-
@jonlong So nobody asked for the current behaviour to be changed, and you are asking for it to be removed, so let's go for that. The behaviour of the current code is that if there is an empty string returned for the name of a heading, then no heading is created... So on a hunch, I gave it a quick test: diff --git a/src/Query/Group.ts b/src/Query/Group.ts
index 3660f9e..901030f 100644
--- a/src/Query/Group.ts
+++ b/src/Query/Group.ts
@@ -178,7 +178,7 @@ export class Group {
task.precedingHeader === null ||
task.precedingHeader.length === 0
) {
- return ['(No heading)'];
+ return [''];
}
return [task.precedingHeader];
}
diff --git a/tests/Group.test.ts b/tests/Group.test.ts
index 7963edc..0ecd08a 100644
--- a/tests/Group.test.ts
+++ b/tests/Group.test.ts
@@ -348,13 +348,13 @@ describe('Group names', () => {
{
groupBy: 'heading',
taskLine: '- [ ] xxx',
- expectedGroupNames: ['(No heading)'],
+ expectedGroupNames: [''],
precedingHeading: null,
},
{
groupBy: 'heading',
taskLine: '- [ ] xxx',
- expectedGroupNames: ['(No heading)'],
+ expectedGroupNames: [''],
precedingHeading: '',
},
{ With this file content:
and this tasks block:
I get this result: And with this tasks block:
I get: |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
👋 Hello, and thanks for such an amazing project!
I've been interested in figuring out how to suppress the default
(No heading)
headers when usinggroup by header
, and poking around in the codebase revealed a number of possible approaches.Before going too far in any direction, I wanted to socialize this feature a bit and get some thoughts from the maintainers.
Here's a quick visual of the problem I'm looking to solve...
...and a markdown representation of the task list (the file is titled
A Sample Note
):In general, I'm curious to hear if this is something you'd consider worth addressing, and if so, whether the design decisions would have any bearing on some of the other grouping defaults (tags, folders, etc).
I spent a little time prototyping solutions and landed on a couple approaches:
Approach 1: using CSS to stay unobtrusive
My first thought was "the least destructive way to do this could be adding a new class name to elements without headings".
Something along the lines of:
Which folks could target and hide with custom CSS snippets:
The downside to this is that at the point in the code where we'd add this new class, it looks like the only way we can tell if a header is empty is by string matching against the value
(No heading)
.So in here...
obsidian-tasks/src/QueryRenderer.ts
Lines 259 to 282 in 201b828
...you'd be adding something like this towards the bottom:
Not terrible, but matching against string literals is a bit of a code smell and warrants some more thought. Also, leveraging this would require users to have familiarity with inspecting the Obsidian DOM and writing custom CSS.
Approach 2: skipping creation if the header is empty
My next thought was "I wonder if this is actually a desired default from a UX perspective". What if we just skipped making elements for empty headers?
It seems like if you were adding headers to a list of tasks, its reasonable to expect the document they're contained in would enforce an outline format. So something like this...
...would naturally get grouped together and displayed in that same format. And something like this...
...would consider
task 10
andtask 11
to be grouped underHeader 2
(rather than a new group with no header).It looks like the plugin enforces this as well, so I'd be curious to hear if there are any cases where not creating header element for empty headers could be problematic.
Unfortunately, we probably can't ship a lightweight solution here without relying on the same type of string matching in the first approach, which turns this...
obsidian-tasks/src/QueryRenderer.ts
Lines 250 to 257 in 201b828
...into something like this:
Alternatives to String Matching
I explored two different ideas here, and both had discussion-worthy drawbacks:
Returning
null
when headings are missingIf this...
obsidian-tasks/src/Query/Group.ts
Lines 176 to 184 in 201b828
...turned into this:
Functionally it works as expected, but a lot of type definitions throughout the code would need to change accordingly, which makes me think it's either not a good idea to introduce a
null
type by design, or refactoring could be a heavy lift.There's also the question of whether we'd need to consider applying this pattern to other group types as well.
Storing default strings as constants
We could make string comparison less brittle by storing the default group strings as constants...
... and importing and referencing those values instead:
I didn't see this pattern anywhere else in the code, and since the approach it introduces is pretty broad, it strikes me as the type of architectural decision to leave to the maintainers.
Definitely a more lightweight option, but opens up questions about what should be a constant and what shouldn't, and whether committing to that pattern means refactoring other areas of the code.
I'd love to hear what folks think — is this a feature that's worth exploring? If so, are there technical approaches to solving it that I may be missing? If we do land on something that warrants a PR, I'd be more than happy to contribute!
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions