Repository: obsidian-tasks-group/obsidian-tasks
Pull request #1426 (2022-12-23 12:42:07)

feat: 'group by filename' now links to the note
_Copy paste from original pull request #1418, first part of the discussion is there_

<!--- Provide a general summary of your changes in the Title above -->

# Description
Hello. First of all thanks a lot for your work on the plugin that I enjoy a lot. Please note I'm not an active programmer nowadays and JS is not my main competence, I just wish to contribute as much as I can and bring the functionalities I need myself instead of asking others to spend their time. If I have done something wrong please let me know how to fix that.

Add another option for group by - filelink = [[filename]]

<!--- Describe your changes in detail -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->
When grouping by filename, the backlinks are redundant information, so they could/should be hidden by the user. However it would be good to have a link somewhere to the file, where the task is described. This mode permits to have this functionality

<!--- If it fixes an open issue, please link to the issue here. -->

## How has this been tested?

<!--- Please describe in detail how you tested your changes. -->
I did run the plugin in my Obsidian setup. I don't think new tests are necessary since I'm using the same functionality as `filename` option, but with adding a markdown link to that.

<!--- Include details of your testing environment, tests ran to see how -->
I did run the included yarn tests (yarn run jest --coverage) without issue

<!--- your change affects other areas of the code, etc. -->

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [ ] **Bug fix** (prefix: `fix` - non-breaking change which fixes an issue)
- [x] **New feature** (prefix: `feat` - non-breaking change which adds functionality)
- [ ] **Breaking change** (prefix: `feat!!` or `fix!!` - fix or feature that would cause existing functionality to not work as expected)
- [x] **Documentation** (prefix: `docs` - improvements to any documentation content)
- [ ] **Sample vault** (prefix: `vault` - improvements to the [Tasks-Demo sample vault](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/resources/sample_vaults/Tasks-Demo))

Internal changes:

- [ ] **Refactor** (prefix: `refactor` - non-breaking change which only improves the design or structure of existing code, and making no changes to its external behaviour)
- [ ] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)
- [ ] **Infrastructure** (prefix: `chore` - examples include GitHub Actions, issue templates)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change requires a change to the documentation.
- [x] I have [updated the documentation](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#updating-documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#maintaining-the-tests).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)



Patch:
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index 542d72bc..695dddfe 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -14,7 +14,7 @@ GEM
       execjs
     coffee-script-source (1.11.1)
     colorator (1.1.0)
-    commonmarker (0.23.5)
+    commonmarker (0.23.6)
     concurrent-ruby (1.1.10)
     dnsruby (1.61.9)
       simpleidn (~> 0.1)
@@ -206,12 +206,14 @@ GEM
       rb-fsevent (~> 0.10, >= 0.10.3)
       rb-inotify (~> 0.9, >= 0.9.10)
     mercenary (0.3.6)
+    mini_portile2 (2.8.1)
     minima (2.5.1)
       jekyll (>= 3.5, < 5.0)
       jekyll-feed (~> 0.9)
       jekyll-seo-tag (~> 2.1)
     minitest (5.16.2)
-    nokogiri (1.13.8)
+    nokogiri (1.13.10)
+      mini_portile2 (~> 2.8.0)
       racc (~> 1.4)
     octokit (4.25.1)
       faraday (>= 1, < 3)
@@ -219,7 +221,7 @@ GEM
     pathutil (0.16.2)
       forwardable-extended (~> 2.6)
     public_suffix (4.0.7)
-    racc (1.6.0)
+    racc (1.6.2)
     rb-fsevent (0.11.1)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
diff --git a/docs/queries/grouping.md b/docs/queries/grouping.md
index 6c5e8179..f691e784 100644
--- a/docs/queries/grouping.md
+++ b/docs/queries/grouping.md
@@ -37,7 +37,7 @@ File locations:
 1. `path` (the path to the file that contains the task, that is, the folder and the filename)
 1. `root` (the top-level folder of the file that contains the task, that is, the first directory in the path, which will be `/` for files in root of the vault)
 1. `folder` (the folder to the file that contains the task, which will be `/` for files in root of the vault)
-1. `filename` (the filename of the file that contains the task, without the `.md` extension)
+1. `filename` (the link to the file that contains the task, without the `.md` extension)
     - Note that tasks from different notes with the same file name will be grouped together in the same group.
 
 > `root` grouping option was introduced in Tasks 1.11.0.
diff --git a/package.json b/package.json
index 38963a19..ff396613 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
     "prettier": "^2.2.1",
     "prettier-plugin-svelte": "^2.7.0",
     "svelte": "^3.48.0",
-    "svelte-check": "^2.9.0",
+    "svelte-check": "^2.10.3",
     "svelte-preprocess": "^4.10.1",
     "ts-jest": "^29.0.3",
     "tslib": "^2.3.1",
diff --git a/src/Query/Group.ts b/src/Query/Group.ts
index a62668b9..0001dae1 100644
--- a/src/Query/Group.ts
+++ b/src/Query/Group.ts
@@ -148,7 +148,7 @@ export class Group {
         if (filename === null) {
             return ['Unknown Location'];
         }
-        return [Group.escapeMarkdownCharacters(filename)];
+        return ['[[' + Group.escapeMarkdownCharacters(filename) + ']]'];
     }
 
     private static groupByRoot(task: Task): string[] {
@@ -166,12 +166,18 @@ export class Group {
             return ['Unknown Location'];
         }
 
-        // Markdown characters in the file name must be escaped.
-        // Markdown characters in the heading must NOT be escaped.
-        const filenameComponent = Group.groupByFileName(task)[0];
+        let filenameComponent = 'Unknown Location';
+
+        if (task.filename !== null) {
+            // Markdown characters in the file name must be escaped.
+            filenameComponent = Group.escapeMarkdownCharacters(task.filename);
+        }
+
         if (task.precedingHeader === null || task.precedingHeader.length === 0) {
             return [filenameComponent];
         }
+
+        // Markdown characters in the heading must NOT be escaped.
         const headingComponent = Group.groupByHeading(task)[0];
 
         if (filenameComponent === headingComponent) {
diff --git a/yarn.lock b/yarn.lock
index edc2779e..1d142597 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -813,7 +813,7 @@
     "@jridgewell/sourcemap-codec" "^1.4.10"
     "@jridgewell/trace-mapping" "^0.3.9"
 
-"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3":
+"@jridgewell/resolve-uri@3.1.0":
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
   integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
@@ -828,15 +828,7 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
   integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
 
-"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.9":
-  version "0.3.14"
-  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
-  integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
-  dependencies:
-    "@jridgewell/resolve-uri" "^3.0.3"
-    "@jridgewell/sourcemap-codec" "^1.4.10"
-
-"@jridgewell/trace-mapping@^0.3.15":
+"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.9":
   version "0.3.17"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
   integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
@@ -4221,10 +4213,10 @@ supports-preserve-symlinks-flag@^1.0.0:
   resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
   integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
 
-svelte-check@^2.9.0:
-  version "2.9.0"
-  resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-2.9.0.tgz#94a4bbe5bccade5a9edae987f417040ab7af4a2a"
-  integrity sha512-9AVrtP7WbfDgCdqTZNPdj5CCCy1OrYMxFVWAWzNw7fl93c9klFJFtqzVXa6fovfQ050CcpUyJE2dPFL9TFAREw==
+svelte-check@^2.10.3:
+  version "2.10.3"
+  resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-2.10.3.tgz#c16426c47630e024bf3cd5fab9b8c4f1702db34a"
+  integrity sha512-Nt1aWHTOKFReBpmJ1vPug0aGysqPwJh2seM1OvICfM2oeyaA62mOiy5EvkXhltGfhCcIQcq2LoE0l1CwcWPjlw==
   dependencies:
     "@jridgewell/trace-mapping" "^0.3.9"
     chokidar "^3.4.1"


Test patch:
diff --git a/tests/Group.test.ts b/tests/Group.test.ts
index 37ccc76a..88cbde50 100644
--- a/tests/Group.test.ts
+++ b/tests/Group.test.ts
@@ -193,22 +193,22 @@ describe('Grouping tasks', () => {
         // Assert
         expect(groups.toString()).toMatchInlineSnapshot(`
             "
-            Group names: [folder\\_a/folder\\_b/,file\\_c]
+            Group names: [folder\\_a/folder\\_b/,[[file\\_c]]]
             #### folder\\_a/folder\\_b/
-            ##### file\\_c
+            ##### [[file\\_c]]
             - [ ] Task 3 - but path is 1st, alphabetically
 
             ---
 
-            Group names: [folder\\_b/folder\\_c/,file\\_c]
+            Group names: [folder\\_b/folder\\_c/,[[file\\_c]]]
             #### folder\\_b/folder\\_c/
-            ##### file\\_c
+            ##### [[file\\_c]]
             - [ ] Task 1 - but path is 2nd, alphabetically
 
             ---
 
-            Group names: [folder\\_b/folder\\_c/,file\\_d]
-            ##### file\\_d
+            Group names: [folder\\_b/folder\\_c/,[[file\\_d]]]
+            ##### [[file\\_d]]
             - [ ] Task 2 - but path is 2nd, alphabetically
 
             ---
@@ -300,13 +300,13 @@ describe('Group names', () => {
         {
             groupBy: 'filename',
             taskLine: '- [ ] a',
-            expectedGroupNames: ['c'],
+            expectedGroupNames: ['[[c]]'],
             path: 'a/b/c.md',
         },
         {
             groupBy: 'filename',
             taskLine: '- [ ] a',
-            expectedGroupNames: ['\\_c\\_'], // underscores in file names are escaped
+            expectedGroupNames: ['[[\\_c\\_]]'], // underscores in file names are escaped
             path: 'a/b/_c_.md',
         },