From 4f683b2755d3509d68850825778645be1e2bb078 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 19:16:07 +0100 Subject: [PATCH 01/11] docs: Move examples up in 'Frontmatter Properties' --- .../Getting Started/Frontmatter Properties.md | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index 7f536007dc..855cf48f0e 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -58,61 +58,6 @@ In the Tasks documentation, we refer to these as Frontmatter Properties, to dist - If your vault contains a mixture of `alias`, `ALIAS` and `ALIASES`, your queries will need to be coded to handle both spellings, for now. - Tasks reads both YAML and [JSON](https://help.obsidian.md/Editing+and+formatting/Properties#JSON+Properties) properties. -## How does Tasks interpret Frontmatter Properties? - -Consider a file with the following example properties (or "Frontmatter"): - - - -```yaml ---- -sample_checkbox_property: true -sample_date_property: 2024-07-21 -sample_date_and_time_property: 2024-07-21T12:37:00 -sample_list_property: - - Sample - - List - - Value -sample_number_property: 246 -sample_text_property: Sample Text Value -sample_text_multiline_property: | - Sample - Text - Value -sample_link_property: "[[yaml_all_property_types_populated]]" -sample_link_list_property: - - "[[yaml_all_property_types_populated]]" - - "[[yaml_all_property_types_empty]]" -aliases: - - YAML All Property Types Populated -tags: - - tag-from-file-properties -creation date: 2024-05-25T15:17:00 -project: Secret Project ---- -``` - -The following table shows how most of those properties are interpreted in Tasks queries: - - - -| Field | Type 1 | Example 1 | -| ----- | ----- | ----- | -| `task.file.hasProperty('creation date')` | `boolean` | `true` | -| `task.file.property('creation date')` | `string` | `'2024-05-25T15:17:00'` | -| `task.file.property('sample_checkbox_property')` | `boolean` | `true` | -| `task.file.property('sample_date_property')` | `string` | `'2024-07-21'` | -| `task.file.property('sample_date_and_time_property')` | `string` | `'2024-07-21T12:37:00'` | -| `task.file.property('sample_list_property')` | `string[]` | `['Sample', 'List', 'Value']` | -| `task.file.property('sample_number_property')` | `number` | `246` | -| `task.file.property('sample_text_property')` | `string` | `'Sample Text Value'` | -| `task.file.property('sample_text_multiline_property')` | `string` | `'Sample\nText\nValue\n'` | -| `task.file.property('sample_link_property')` | `string` | `'[[yaml_all_property_types_populated]]'` | -| `task.file.property('sample_link_list_property')` | `string[]` | `['[[yaml_all_property_types_populated]]', '[[yaml_all_property_types_empty]]']` | -| `task.file.property('tags')` | `string[]` | `['#tag-from-file-properties']` | - - - ## Frontmatter Properties Examples ### Tags @@ -197,6 +142,61 @@ group by function \ +## How does Tasks interpret Frontmatter Properties? + +Consider a file with the following example properties (or "Frontmatter"): + + + +```yaml +--- +sample_checkbox_property: true +sample_date_property: 2024-07-21 +sample_date_and_time_property: 2024-07-21T12:37:00 +sample_list_property: + - Sample + - List + - Value +sample_number_property: 246 +sample_text_property: Sample Text Value +sample_text_multiline_property: | + Sample + Text + Value +sample_link_property: "[[yaml_all_property_types_populated]]" +sample_link_list_property: + - "[[yaml_all_property_types_populated]]" + - "[[yaml_all_property_types_empty]]" +aliases: + - YAML All Property Types Populated +tags: + - tag-from-file-properties +creation date: 2024-05-25T15:17:00 +project: Secret Project +--- +``` + +The following table shows how most of those properties are interpreted in Tasks queries: + + + +| Field | Type 1 | Example 1 | +| ----- | ----- | ----- | +| `task.file.hasProperty('creation date')` | `boolean` | `true` | +| `task.file.property('creation date')` | `string` | `'2024-05-25T15:17:00'` | +| `task.file.property('sample_checkbox_property')` | `boolean` | `true` | +| `task.file.property('sample_date_property')` | `string` | `'2024-07-21'` | +| `task.file.property('sample_date_and_time_property')` | `string` | `'2024-07-21T12:37:00'` | +| `task.file.property('sample_list_property')` | `string[]` | `['Sample', 'List', 'Value']` | +| `task.file.property('sample_number_property')` | `number` | `246` | +| `task.file.property('sample_text_property')` | `string` | `'Sample Text Value'` | +| `task.file.property('sample_text_multiline_property')` | `string` | `'Sample\nText\nValue\n'` | +| `task.file.property('sample_link_property')` | `string` | `'[[yaml_all_property_types_populated]]'` | +| `task.file.property('sample_link_list_property')` | `string[]` | `['[[yaml_all_property_types_populated]]', '[[yaml_all_property_types_empty]]']` | +| `task.file.property('tags')` | `string[]` | `['#tag-from-file-properties']` | + + + ## Limitations - It is not yet possible to use properties in the query file: From 5c6ab3f37927215cf20f99b9faa0a71a66286802 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 20:07:49 +0100 Subject: [PATCH 02/11] docs: Add some ideas for tracking projects via properties --- .../Getting Started/Frontmatter Properties.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index 855cf48f0e..523153c0dd 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -92,6 +92,53 @@ filter by function task.file.hasProperty('kanban-plugin') filter by function ! task.file.hasProperty('kanban-plugin') ``` +### Tracking projects + +#### Use a `project` property + +Suppose you have multiple files associated with a project, spread throughout your vault, and they all have a `project` property like this: + +```yaml +--- +project: Project 1 +--- +``` + +This search will find all tasks in those files: + +```javascript +filter by function task.file.property('project') === 'Project 1' +``` + +#### Use `#project/...` tag values + +Some people prefer to use properties tags to identify projects. One advantage of tags is it is easy to add multiple values. + +```yaml +--- +tags: + - project/project-1 +--- +``` + +This exact-match search will find all tasks in such files: + +```javascript +filter by function task.file.property('tags').includes('#project/project-1') +``` + +If you wanted to use a sub-string search to find all tasks in files with any properties tag beginning `#project/` you could use [optional chaining (?.)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) and the [nullish coalescing operator (??)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) like this: + +```javascript +filter by function task.file.property('tags')?.join(',').includes('#project/') ?? false +``` + +Or you could use [template literals (Template strings)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) like this: + +```javascript +filter by function `${task.file.property('tags')}`.includes('#project/') +``` + ### More filtering examples From 8afefe87299a16c7fe25e708a8d8a3701cfc846e Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 20:08:53 +0100 Subject: [PATCH 03/11] docs: Remove some machine-generated examples which are not too clear --- .../Getting Started/Frontmatter Properties.md | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index 523153c0dd..6d5ffab656 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -139,36 +139,6 @@ Or you could use [template literals (Template strings)](https://developer.mozill filter by function `${task.file.property('tags')}`.includes('#project/') ``` -### More filtering examples - - - -```javascript -filter by function task.file.hasProperty('kanban-plugin') -``` - -- find tasks in [Kanban Plugin](https://github.com/mgmeyers/obsidian-kanban) boards. - -```javascript -filter by function task.file.property("sample_list_property")?.length > 0 -``` - -- find tasks in files where the list property 'sample_list_property' exists and has at least one list item. - -```javascript -filter by function task.file.property("sample_list_property")?.length === 0 -``` - -- find tasks in files where the list property 'sample_list_property' exists and has no list items. - -```javascript -filter by function task.file.property('creation date')?.includes('2024') ?? false -``` - -- find tasks in files where the date property 'creation date' includes string '2024'. - - - ### More grouping examples From 398443b36cd3d0b341aff4d8ff5bae773307e46d Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 20:21:59 +0100 Subject: [PATCH 04/11] docs: Document use of date values --- .../Getting Started/Frontmatter Properties.md | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index 6d5ffab656..dfcd6f9c9a 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -139,26 +139,41 @@ Or you could use [template literals (Template strings)](https://developer.mozill filter by function `${task.file.property('tags')}`.includes('#project/') ``` -### More grouping examples +### Using date values - +Obsidian supports [Date](https://help.obsidian.md/Editing+and+formatting/Properties#^date-time) and [Date & time](https://help.obsidian.md/Editing+and+formatting/Properties#^date-time) property values. + +It stores them in the format shown in these examples: + +```yaml +--- +date: 2020-08-21 +time: 2020-08-21T10:30:00 +--- +``` + +Currently, Tasks does nothing special with these, seeing them as string values. + +#### Grouping by raw date values + +A `creation date` property might be used like this, to group tasks by the date their file was created, according to the stored property values: ```javascript group by function task.file.property('creation date') ?? 'no creation date' ``` -- group tasks by 'creation date' date property. +#### Formatting date values using Moment.js + +If you want to do date calculations on `Date` or `Date & time` values, you can use `window.moment(value)` to create a [Moment.js](https://momentjs.com) object. + +For example: ```javascript group by function \ const value = task.file.property('creation date'); \ - return value ? window.moment(value).format('MMMM') : 'no month' + return value ? window.moment(value).format('YYYY MMMM') : 'no date' ``` -- group tasks by month in 'creation date' date property. - - - ## How does Tasks interpret Frontmatter Properties? Consider a file with the following example properties (or "Frontmatter"): From ce95c85ebe81c7eb78931249281124a88a45b9a2 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 20:29:57 +0100 Subject: [PATCH 05/11] docs: Remove an unhelpful quote - suggestion from @ilandikov --- docs/Getting Started/Frontmatter Properties.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index dfcd6f9c9a..ec6a1608d1 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -20,11 +20,6 @@ publish: true Obsidian offers a facility called [Properties](https://help.obsidian.md/Editing+and+formatting/Properties). -The Obsidian documentation says: - -> [!Quote] -> Properties allow you to organize information about a note. Properties contain structured data such as text, links, dates, checkboxes, and numbers. Properties can also be used in combination with [Community plugins](https://help.obsidian.md/Extending+Obsidian/Community+plugins) that can do useful things with your structured data. - This is an example property section, and it *must* appear on the very first line of the markdown file: ```yaml From deb3eae5409e499b94318140d1e71cd4331084c1 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 20:42:01 +0100 Subject: [PATCH 06/11] docs: Improve wording - suggestions from @ilandikov --- docs/Getting Started/Frontmatter Properties.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index ec6a1608d1..ec51b09d9e 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -48,10 +48,10 @@ In the Tasks documentation, we refer to these as Frontmatter Properties, to dist - `property name` will find `Property Name`, for example. - Tags in Frontmatter can be accessed with `task.file.property('tags')` - `TAG` and `TAGS` are standardised to `tags`. - - The `#` prefix is added to all tag values in frontmatter. + - The `#` prefix is added to all tag values returned by this function. - Aliases in Frontmatter are not yet standardised. - If your vault contains a mixture of `alias`, `ALIAS` and `ALIASES`, your queries will need to be coded to handle both spellings, for now. -- Tasks reads both YAML and [JSON](https://help.obsidian.md/Editing+and+formatting/Properties#JSON+Properties) properties. +- Tasks reads both YAML and [JSON](https://help.obsidian.md/Editing+and+formatting/Properties#JSON+Properties) formats. ## Frontmatter Properties Examples From 7290408ed32f2c3413006c5e30ef56dd576f12f7 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 21:14:09 +0100 Subject: [PATCH 07/11] docs: Add a bit of motivation about why to use properties --- docs/Getting Started/Frontmatter Properties.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/Getting Started/Frontmatter Properties.md b/docs/Getting Started/Frontmatter Properties.md index ec51b09d9e..25c6b82c6a 100644 --- a/docs/Getting Started/Frontmatter Properties.md +++ b/docs/Getting Started/Frontmatter Properties.md @@ -20,6 +20,8 @@ publish: true Obsidian offers a facility called [Properties](https://help.obsidian.md/Editing+and+formatting/Properties). +Properties allow you to organize information about a note. Properties contain structured data such as text, links, dates, checkboxes, and numbers. + This is an example property section, and it *must* appear on the very first line of the markdown file: ```yaml @@ -30,6 +32,10 @@ name: value In the Tasks documentation, we refer to these as Frontmatter Properties, to distinguish them from Task and Query properties. +## Why use Frontmatter Properties in Tasks queries? + +For example, if you associate a tag with a project, you might want to put that tag in one place at the top of the file, instead of having to remember to add it on every single task line in the file. + ## How does Tasks treat Frontmatter Properties? - Frontmatter property values can be used in the following instructions: From bf1d72921a577b699ed19c2c8411855c4a66861f Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 21:23:19 +0100 Subject: [PATCH 08/11] docs: Add property functions to Quick Reference --- docs/Quick Reference.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Quick Reference.md b/docs/Quick Reference.md index e4e474aa52..83dfe9cf63 100644 --- a/docs/Quick Reference.md +++ b/docs/Quick Reference.md @@ -44,6 +44,7 @@ This table summarizes the filters and other options available inside a `tasks` b | `filename (includes, does not include) `
`filename (regex matches, regex does not match) /regex/i`
`filename includes {{query.file.filename}}`
`filename includes {{query.file.filenameWithoutExtension}}` | `sort by filename` | `group by filename` | | `task.file.filename`
`task.file.filenameWithoutExtension`
`query.file.filename`
`query.file.filenameWithoutExtension` | | `heading (includes, does not include) `
`heading (regex matches, regex does not match) /regex/i` | `sort by heading` | `group by heading` | | `task.hasHeading`
`task.heading` | | | | `group by backlink` | `hide backlink` | | +| **[[Frontmatter Properties]]** | | | | `task.file.hasProperty('property name')`
`task.file.property('property name')` | | **[[Filters#Description\|Description]]**, **[[Filters#Tags\|Tags]]** and other odds and ends | | | | | | `description (includes, does not include) `
`description (regex matches, regex does not match) /regex/i` | `sort by description` | | | `task.description`
`task.descriptionWithoutTags` | | `has tags`
`no tags`
`tag (includes, does not include) `
`tags (include, do not include) `
`tag (regex matches, regex does not match) /regex/i`
`tags (regex matches, regex does not match) /regex/i` | `sort by tag`
`sort by tag ` | `group by tags` | `hide tags` | `task.tags` | From 235af41960be50f7843beca8b1585e61648ca0e7 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 21:27:37 +0100 Subject: [PATCH 09/11] docs: Expand on Task Properties.md --- docs/Scripting/Task Properties.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Scripting/Task Properties.md b/docs/Scripting/Task Properties.md index 4f60944832..24fa23dad5 100644 --- a/docs/Scripting/Task Properties.md +++ b/docs/Scripting/Task Properties.md @@ -205,7 +205,7 @@ For more information, including adding your own customised statuses, see [[Statu > [!released] > Access to the frontmatter properties was introduced in Tasks X.Y.Z. -These values are described in [[Frontmatter Properties]]. +These are described in full in [[Frontmatter Properties]]. @@ -225,3 +225,7 @@ These values are described in [[Frontmatter Properties]]. | `task.file.property('tags')` | `string[]` | `['#tag-from-file-properties']` | + +1. `task.file.hasProperty()` and `task.file.property()` were added in Tasks X.Y.Z +1. `task.file.hasProperty('property name')` returns true if the property `'property name'` is both present in the file and has a non-`null` value. +1. `task.file.property('property name')` returns either the value in the file, or `null` if there is no value. From e0e10156f41311752820aa46bf86d7df7436dc00 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 21:41:09 +0100 Subject: [PATCH 10/11] vault: Update properties examples for latest code --- .../Access properties in frontmatter.md | 34 ++++++++- ...Find tasks in notes with particular tag.md | 74 +------------------ 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/resources/sample_vaults/Tasks-Demo/How To/Access properties in frontmatter.md b/resources/sample_vaults/Tasks-Demo/How To/Access properties in frontmatter.md index 940c374907..f3d60e4a6c 100644 --- a/resources/sample_vaults/Tasks-Demo/How To/Access properties in frontmatter.md +++ b/resources/sample_vaults/Tasks-Demo/How To/Access properties in frontmatter.md @@ -1,15 +1,43 @@ # Access properties in frontmatter -## Accessing a custom property +These examples work with Tasks X.Y.Z and later. + +## Accessing a custom property for grouping + +Group by property `custom_number_prop`, with tasks from files without that property being un-grouped: ```tasks folder includes Test Data -group by function task.file.frontmatter.custom_number_prop ?? 'not set' +group by function task.file.property('custom_number_prop') + +limit groups 5 +``` + +Group by property `custom_number_prop`, with a fixed gorup name for tasks from files without that property: + +```tasks +folder includes Test Data +group by function task.file.property('custom_number_prop') ?? 'no "custom_number_prop" value' + +limit groups 5 ``` ## Accessing tags +Group by each tag property value, and tasks with more than one tag are listed multiple times: + +```tasks +folder includes Test Data +group by function task.file.property('tags') + +limit groups 5 +``` + +Group by tag property values, and tasks with more than one tag are listed only once + ```tasks folder includes Test Data -group by function task.file.frontmatter.tags +group by function task.file.property('tags').sort().join(', ') + +limit groups 5 ``` diff --git a/resources/sample_vaults/Tasks-Demo/How To/Find tasks in notes with particular tag.md b/resources/sample_vaults/Tasks-Demo/How To/Find tasks in notes with particular tag.md index c918098c9e..7168212a47 100644 --- a/resources/sample_vaults/Tasks-Demo/How To/Find tasks in notes with particular tag.md +++ b/resources/sample_vaults/Tasks-Demo/How To/Find tasks in notes with particular tag.md @@ -1,77 +1,9 @@ # Find tasks in notes with particular tag -Suppose we wanted to find all tasks in notes that had a particular tag in the frontmatter. +Suppose we wanted to find all tasks in notes that had a particular tag `#examples` in the frontmatter. -## Dataview approach - -This is not currently possible in Tasks directly, but we could get dataview to do the search for us and create a Tasks query. - -Note that the following finds all tasks where the tag is present anywhere in the file, not just in the frontmatter. - -```dataviewjs -const tag = '#examples' -const matching_files = dv.pagePaths(tag) -if ( matching_files.length > 0 ) { - const query = ` - not done - (path includes ${matching_files.join(') OR (path includes ')}) - - # you can add any number of extra Tasks instructions, for example: - group by path -`; - - dv.paragraph('```tasks\n' + query + '\n```'); -} else { - const message = `No files found with tag ${tag}` - dv.paragraph(message) -} -``` - -Credit: jonlemon in [this Obsidian Forum thread](https://forum.obsidian.md/t/how-can-i-list-tasks-from-all-notes-with-a-certain-tag-using-the-tasks-plugin/44634). - -## Tasks experimental approach - -### Tasks in files that have a Tag in frontmatter - -#### Presence of tag - in frontmatter - -```tasks -filter by function task.file.frontmatter.tags.includes('#examples') -``` - -### Tasks in files that have a Tag anywhere - in frontmatter or body - -#### Presence of tag - in frontmatter or body +Since Tasks X.Y.Z, this is now possible in Tasks queries: ```tasks -filter by function task.file.tags.includes('#examples') -``` - -#### Absence of tag - in frontmatter or body - -```tasks -filter by function ! task.file.tags.includes('#examples') - -limit 20 -``` - -#### Group by tags - in frontmatter or body - -```tasks -group by function task.file.tags -folder does not include Test Data - -limit groups 3 -limit 100 -``` - -#### Group by tags - in frontmatter or body, ignoring the global filter - -```tasks -# TODO Provide task.file.tagsWithoutGlobalFilter -group by function task.file.tags.filter( (t) => t !== '#task' ) -folder does not include Test Data - -limit groups 3 -limit 100 +filter by function task.file.property('tags').includes('#examples') ``` From 09c61a5738ada6b9d80c7336742209fa7951bf03 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Thu, 1 Aug 2024 21:44:50 +0100 Subject: [PATCH 11/11] docs: Update Tags page for support of Frontmatter Properties --- docs/Getting Started/Tags.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/Getting Started/Tags.md b/docs/Getting Started/Tags.md index 1284e3e1d5..0840ad79e9 100644 --- a/docs/Getting Started/Tags.md +++ b/docs/Getting Started/Tags.md @@ -68,9 +68,12 @@ tags: --- ``` -Tasks does not currently read this data. We are tracking this in [discussion #232](https://github.com/obsidian-tasks-group/obsidian-tasks/discussions/232). +Since Tasks X.Y.Z, Tasks **does** now read this data. -For now, see [Find tasks in notes with particular tag](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/resources/sample_vaults/Tasks-Demo/How%20To/Find%20tasks%20in%20notes%20with%20particular%20tag.md) for a workaround using [[Dataview]] and Tasks together. +You can learn more in: + +- [[Frontmatter Properties]], and the examples in that file +- [Find tasks in notes with particular tag](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/resources/sample_vaults/Tasks-Demo/How%20To/Find%20tasks%20in%20notes%20with%20particular%20tag.md). ### Order of tags in task lines