master 5ad0994ff384 cached
148 files
749.9 KB
188.8k tokens
682 symbols
1 requests
Download .txt
Showing preview only (793K chars total). Download the full file or copy to clipboard to get everything.
Repository: blacksmithgu/obsidian-dataview
Branch: master
Commit: 5ad0994ff384
Files: 148
Total size: 749.9 KB

Directory structure:
gitextract_umn6h50l/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── bug_report_mobile.yml
│   │   ├── config.yml
│   │   ├── documentation.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── documentation.yml
│       └── test.yml
├── .gitignore
├── .prettierrc.json
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── __mocks__/
│   ├── data-import/
│   │   └── web-worker/
│   │       └── import-manager.ts
│   └── obsidian.ts
├── cspell.json
├── docs/
│   ├── .gitignore
│   ├── docs/
│   │   ├── annotation/
│   │   │   ├── add-metadata.md
│   │   │   ├── metadata-pages.md
│   │   │   ├── metadata-tasks.md
│   │   │   └── types-of-metadata.md
│   │   ├── api/
│   │   │   ├── code-examples.md
│   │   │   ├── code-reference.md
│   │   │   ├── data-array.md
│   │   │   └── intro.md
│   │   ├── changelog.md
│   │   ├── friends.md
│   │   ├── index.md
│   │   ├── queries/
│   │   │   ├── data-commands.md
│   │   │   ├── differences-to-sql.md
│   │   │   ├── dql-js-inline.md
│   │   │   ├── query-types.md
│   │   │   └── structure.md
│   │   ├── reference/
│   │   │   ├── expressions.md
│   │   │   ├── functions.md
│   │   │   ├── literals.md
│   │   │   └── sources.md
│   │   └── resources/
│   │       ├── develop-against-dataview.md
│   │       ├── examples.md
│   │       ├── faq.md
│   │       └── resources-and-support.md
│   ├── mkdocs.yml
│   └── overrides/
│       └── main.html
├── jest.config.js
├── manifest-beta.json
├── manifest.json
├── package.json
├── rollup.config.js
├── scripts/
│   ├── beta-release
│   ├── install-built
│   └── release
├── src/
│   ├── api/
│   │   ├── data-array.ts
│   │   ├── extensions.ts
│   │   ├── inline-api.ts
│   │   ├── plugin-api.ts
│   │   └── result.ts
│   ├── data-import/
│   │   ├── common.ts
│   │   ├── csv.ts
│   │   ├── inline-field.ts
│   │   ├── markdown-file.ts
│   │   ├── persister.ts
│   │   └── web-worker/
│   │       ├── import-entry.ts
│   │       ├── import-impl.ts
│   │       └── import-manager.ts
│   ├── data-index/
│   │   ├── index.ts
│   │   ├── resolver.ts
│   │   └── source.ts
│   ├── data-model/
│   │   ├── markdown.ts
│   │   ├── serialized/
│   │   │   └── markdown.ts
│   │   ├── transferable.ts
│   │   └── value.ts
│   ├── expression/
│   │   ├── binaryop.ts
│   │   ├── context.ts
│   │   ├── field.ts
│   │   ├── functions.ts
│   │   └── parse.ts
│   ├── index.ts
│   ├── main.ts
│   ├── query/
│   │   ├── engine.ts
│   │   ├── parse.ts
│   │   └── query.ts
│   ├── settings.ts
│   ├── test/
│   │   ├── api/
│   │   │   └── data-array.test.ts
│   │   ├── common.ts
│   │   ├── data/
│   │   │   ├── index-map.test.ts
│   │   │   ├── transferable.test.ts
│   │   │   └── values.test.ts
│   │   ├── function/
│   │   │   ├── aggregation.test.ts
│   │   │   ├── coerce.test.ts
│   │   │   ├── constructors.test.ts
│   │   │   ├── eval.test.ts
│   │   │   ├── functions.test.ts
│   │   │   ├── meta.test.ts
│   │   │   ├── string.test.ts
│   │   │   └── vectorization.test.ts
│   │   ├── markdown/
│   │   │   └── parse.file.test.ts
│   │   ├── parse/
│   │   │   ├── parse.expression.test.ts
│   │   │   ├── parse.inline.test.ts
│   │   │   └── parse.query.test.ts
│   │   └── util/
│   │       ├── normalize.test.ts
│   │       └── paths.test.ts
│   ├── typings/
│   │   ├── obsidian-ex.d.ts
│   │   └── workers.d.ts
│   ├── ui/
│   │   ├── export/
│   │   │   └── markdown.ts
│   │   ├── lp-render.ts
│   │   ├── markdown.tsx
│   │   ├── refreshable-view.ts
│   │   ├── render.ts
│   │   └── views/
│   │       ├── calendar-view.ts
│   │       ├── inline-field-live-preview.ts
│   │       ├── inline-field.tsx
│   │       ├── inline-view.ts
│   │       ├── js-view.ts
│   │       ├── list-view.tsx
│   │       ├── table-view.tsx
│   │       └── task-view.tsx
│   └── util/
│       ├── hash.ts
│       ├── locale.ts
│       ├── media.ts
│       └── normalize.ts
├── styles.css
├── test-vault/
│   ├── .obsidian/
│   │   └── community-plugins.json
│   ├── Books.md
│   ├── Home.md
│   ├── blog/
│   │   ├── 2020-08-08-an-earlier-post.md
│   │   └── 2021-08-08-a-post.md
│   ├── books/
│   │   ├── Catcher in the Rye.md
│   │   ├── Origin of Species.md
│   │   └── The Great Gatsby.md
│   ├── example calendars.md
│   ├── example lists.md
│   ├── example tables.md
│   ├── recipes/
│   │   ├── pbj.md
│   │   └── toast.md
│   ├── tasks/
│   │   ├── Annotated Tasks.md
│   │   ├── Completed Tasks.md
│   │   ├── Grouped Sorted Tasks.md
│   │   ├── Sorted Tasks.md
│   │   ├── Tasks Completed on specific Date.md
│   │   ├── Tasks in a specific section.md
│   │   ├── Uncompleted Tasks.md
│   │   ├── checklist.md
│   │   └── example tasks.md
│   └── untracked/
│       └── README.md
├── tsconfig-lib.json
├── tsconfig.json
└── versions.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

# Matches multiple files with brace expansion notation
# Set default charset
[*.{ts,js}]
charset = utf-8
indent_style = space
indent_size = 4

================================================
FILE: .github/FUNDING.yml
================================================
github: ["blacksmithgu"]


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report (desktop)
description: "File a bug report for Dataview on desktop Obsidian"
title: "Bug report"
labels: ["bug", "needs-investigation"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to fill out this bug report!
  - type: textarea
    id: what-happened
    attributes:
      label: What happened?
      description: Also tell us, what did you expect to happen?
      placeholder: Tell us what you see!
    validations:
      required: true
  - type: textarea
    id: dql
    attributes:
      label: DQL
      description: If applicable, provide the query where the bug occurred
      placeholder: |
        ```dataview
        LIST FROM #example
        ```
  - type: textarea
    id: js
    attributes:
      label: JS
      description: If applicable, provide the javascript where the bug occurred
      render: js
  - type: input 
    id: version
    attributes:
      label: Dataview Version
      description: What version of Dataview are you running?
      placeholder: 0.4.20
    validations:
      required: true
  - type: input 
    id: obsidian-version 
    attributes:
      label: Obsidian Version
      placeholder: 0.12.19
    validations:
      required: true
  - type: dropdown
    id: os
    attributes:
      label: OS
      options:
         - Windows
         - MacOS
         - Linux
    validations:
      required: true
         


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report_mobile.yml
================================================
name: Bug Report (mobile)
description: "File a bug report for Dataview on mobile Obsidian"
title: "Bug report"
labels: ["bug", "needs-investigation", "mobile"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to fill out this bug report!
  - type: textarea
    id: what-happened
    attributes:
      label: What happened?
      description: Also tell us, what did you expect to happen?
      placeholder: Tell us what you see!
    validations:
      required: true
  - type: textarea
    id: dql
    attributes:
      label: DQL
      description: If applicable, provide the query where the bug occurred
      placeholder: |
        ```dataview
        LIST FROM #example
        ```
  - type: textarea
    id: js
    attributes:
      label: JS
      description: If applicable, provide the javascript where the bug occurred
      render: js
  - type: input 
    id: version
    attributes:
      label: Dataview Version
      description: What version of Dataview are you running?
      placeholder: 0.4.20
    validations:
      required: true
  - type: input 
    id: obsidian-version 
    attributes:
      label: Obsidian Version
      placeholder: 0.12.19
    validations:
      required: true
  - type: input
    id: device
    attributes:
      label: Device
      description: What device are you running Obsidian on? Please provide the full model (version, year, etc.)
      placeholder: iPhone 6
    validations:
      required: true
  - type: input
    id: os
    attributes:
      label: OS
      description: What OS are you running Obsidian on? Please provide the full OS version.
      placeholder: iOS 8.1
    validations:
      required: true
         


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Dataview Discussions
    url: https://github.com/blacksmithgu/obsidian-dataview/discussions
    about: Please ask and answer questions here.
  - name: Obsidian Discord
    url: https://obsidian.md/community
    about: "Check out the #dataview channel under the Plugins section."
  - name: Dataview Snippet Showcase
    url: https://forum.obsidian.md/t/dataview-plugin-snippet-showcase
    about: Show off your Dataview snippets here!
  - name: DataviewJS Snippet Showcase
    url: https://forum.obsidian.md/t/dataviewjs-snippet-showcase
    about: Show off your DataviewJS snippets here!


================================================
FILE: .github/ISSUE_TEMPLATE/documentation.md
================================================
---
name: Documentation
about: Suggest improvements to documentation
title: ''
labels: documentation

---

**Please provide a link to the documentation page and section**

**Describe the problem**
A clear and concise description of what is unclear about the documentation

**Describe the solution you'd like**
A clear and concise description of what you want to happen. Feel free to suggest wording, full sentences, etc.

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature-request

---

[//]: # (Note: If you are unsure about or have questions related to your feature request prefer making a discussion first. After we understand what you are looking for we can easily create an issue to track the solution and progress)

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/documentation.yml
================================================
name: docs
on:
  release:
    types:
      - published
  workflow_dispatch:
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: 3.x
      - run: |
          pip install mkdocs-material mkdocs-redirects
          cd docs
          mkdocs gh-deploy --force


================================================
FILE: .github/workflows/test.yml
================================================
name: Build and test project
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  format:
    runs-on: ubuntu-latest
    name: Check code formatting
    steps:
      - uses: actions/checkout@v3
      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm install
      - run: npm run check-format
  build:
    runs-on: ubuntu-latest
    name: Build project
    steps:
      - uses: actions/checkout@v3
      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm install
      - run: npm run build
  test:
    runs-on: ubuntu-latest
    name: Test project
    steps:
      - uses: actions/checkout@v3
      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm install
      - run: npm run test


================================================
FILE: .gitignore
================================================
# Intellij
*.iml
.idea

# VSCode
.vscode
.history/

# npm
node_modules

# build
build/

# Ignore .obsidian
# No one will commit these files, they just spam 'git status'
test-vault/.obsidian/*
# Tells obsidian what plugins are enabled
!test-vault/.obsidian/community-plugins.json
# This plugin should still be tracked by git.
# It might need updated at some point
!test-vault/.obsidian/hot-reload-master/*

# Don't track this folder. For random things to try.
# If its import to test though, add it somewhere where other
# people can test it too.
test-vault/untracked/*
!test-vault/untracked/README.md

lib
yarn.lock


================================================
FILE: .prettierrc.json
================================================
{
    "tabWidth": 4,
    "semi": true,
    "embeddedLanguageFormatting": "off",
    "parser": "typescript",
    "printWidth": 120,
    "arrowParens": "avoid"
}


================================================
FILE: CHANGELOG.md
================================================
# 0.5.70 (Beta)

Still attempting to fix #2557, github is acting up.


---

# 0.5.69 (Beta)

Attempting to fix #2557, but uncertain to any side effects.


---

# 0.5.68

- Many fixes to the documentation
- #2318 & co: Various fixes related to _live preview_ rendering of lists
- New/documented functions for `unique()`, `display()`, `firstvalue()`
- Added DOM information related to standalone inline fields

This is the first release done by @holroy, so thanks to him for further developing of _Dataview_. Thank you also to all the people having contributed through PRs and issues.

---

# 0.5.67

Includes several documentation fixes and several community-contributed bug fixes.

- @reply2za: Fixed inline rendering in the reading view.
- @carlesalbasboix: Adds sum(), avg(), min(), and max() to data arrays.
- @mnaoumov: Adds code mirror configuration which code highlights dataviewjs!

---

# 0.5.66

Bugfix for version comparisons to fix some other plugins having broken interactions with Dataview.

---

# 0.5.65

A maintenance update which fixes some issues with rendering embeds in Dataviews and adds a few new functions.

- Adds the `hash()` function for generating consistent uniformly-distributed values given arbitrary inputs. Primarily useful for creating "random" views which remain consistent across page refreshes. Thanks to @holroy.
- Adds the `slice()` function for slicing arrays, similar to Javascript's `Array.slice`. Thanks to @holroy.
- Fixes several issues with rendering embeds inside dataviews. Thanks to @GottZ.
- Several documentation improvements around tasks - thanks to @holroy and @RaviOnline.

---

# 0.5.64

More bug fixes for inline field rendering.


---

# 0.5.63

- More bugfixes from @RyotaUshio for rendering Markdown paragraphs and other blocks in DataviewJS.

---

# 0.5.62

Several more inline field fixes from @RyotaUshio, including more configuration options, fixing inline fields being rendered inside codeblocks, and more. Thanks!

---

# 0.5.61

- @RyotaUshio: Fix several bugs related to the new inline field rendering, including source mode and fixing date formatting.

---

# 0.5.60

- @RyotaUshio: Add explicit rendering of inline fields in live preview. They are much more visually distinct now!
- @MarioRicalde: Adds `PluginApi#evaluateInline(expression, path)` to the plugin API, which evaluate expressions as if you were on the given page.

---

# 0.5.59

- Fix an issue with the plugin failing to run on iOS due to an esoteric regex issue.

---

# 0.5.58

- Negative durations will now be properly rendered.

---

# 0.5.57

Maintenance patch which bumps many internal dependency versions and which includes approximately ~20 community-contributed PRs which add some new functions, fix some Dataview interactions with properties, and more!

---

# Unreleased

- DQL: Adds new `durationformat(duration, string)` function.
- DQL: New math rounding functions, `trunc(number)`, `floor(number)`, `ceil(number)`.

# 0.5.56

- Includes some performance fixes on recent versions of Obsidian 1.3+ due to some API changes. Thanks @kometenstaub.
- Documentation cleanups and improvements by @mocsa, @protofarer, @seanlzx, and @somidad.
- Adds the new `flat(array)` method for flattening nested arrays, as well as parsing dates using arbitrary formats using
  `date(text, "format")`. Thanks @holroy!

---

# 0.5.55

- Durations are now internationalized using luxon's new internationalization support.
- Dataviews should now properly render inside Canvas and some other contexts. Thanks @GamerGirlandCo!

---

# 0.5.54

- Regular list items are now also clickable in task views, not just task lines! Thanks to @LilaRest.

---

# 0.5.53

- Fix some documentation issues causing docs to not be updated.

---

# 0.5.52

Substantial documentation improvements thanks to @s-blu and @AB1908!

- For people concerned about dataviewjs code execution from copy-pasting, @eyuelt has made it possible to change the
  dataviewjs codeblock prefix.
- @sohanglal has added some documentation for `task.visual` for changing the visual text of a task.
- @Chouffy and @Daryl-Horton have fixed some bad documentation links!
- @vrtmrz swapped the regex used for parsing tags to better match Obsidian's own parser.
- @alexfertel has added `regextest`, which allows for matching parts of a string instead of the whole thing.
- @iamrecursion has added more metadata to file links, so they now include section metadata. This may cause some slight
  visual changes in link views.

---

# 0.5.51 (Beta)

- Allow disabling regular Dataview inline queries via configuration option.

---

# 0.5.50 (Beta)

- Expose dataview EXPRESSION and QUERY parsing to the dataview npm plugin, so others can parse dataview ASTs.
- Fix documentation issue with `join`.

---

# 0.5.49 (Beta)

- Add the `average` function to compute averages of lists (`average([list of things])`).
- Added documentation for `average`, `min`, `max`, `minby`, and `maxby` functions.
- Fixed the broken `nonnull` function and documented it.

---

# 0.5.48 (Beta)

We're back to more regular beta releases while I trial out new functionality!

- Fixed broken list behavior for `dv.markdownTaskList`.
- @GamerGirlandCo: Better handling of block IDs when checking off tasks!
- @s-blu and @AB1908: Lots of big documentation upgrades! Nice!
- @leoccyao: More block ID task checking fixes. Should work after this one.
- Add expression/query parsing to the dataview NPM package.
- @charleshan: Fix a missing header level in the dataview `dv.header` example.

---

# 0.5.47

Improves `date + duration` behavior when either the date or duration are null.

---

# 0.5.46

- Fix #1412: Fix bad `file.cday` and `file.ctime` comparisons due to wrong timezone being set. Ugh.

---

# 0.5.45

- #1400: Properly use the group by field for the group name.
- Fix bad table highlighting in some themes.

---

# 0.5.44

- #1404: Fixed dates in non-local timezones parsing incorrectly.
- Fixed some build non-determinism issues.
- Swapped to pull requests for adding new functionality, and added some more internal tests.

---

# 0.5.43

- Fix #1366: Better handling of calendar emoji (used as due dates in tasks).

---

# 0.5.42

It's been over a month since the last release! Anyway, this release bundles several nice user-contributed features:

- @AB1908: Tag queries are now case insensitive.
- @AB1908: Shift-clicking a link/task to open in a new tab now works properly on Mac.
- @AB1908: Numerous documentation fixes for clarity and more examples.
- @AnnaKornfeldSimpson: Additional emoji shorthands for more task fields (finished, due).
- @ooker777: Documentation improvements for some DataviewJS functions, and the ability to use inline emoji for the
  completion tracking feature.
- @mt-krainski: Custom date formats for task completions.
- @gentlegiantJGC: Better support for nested inline fields (i.e., less crashy).

---

# 0.5.41

- Fix a bad regex doing escaping in markdown tables.
- Improve async documentation.

---

# 0.5.40

Adds some more documentation about the new markdown functionality.

---

# 0.5.39

- Fixed an issue where checking a task in a task view would check the wrong box visually.
- Added experimental plugin APIs for querying dataview directly as markdown, and converting dataview results to properly
  formatted markdown.

---

# 0.5.38

- Some minor documentation improvements.
- Fix an issue with inline fields rendering out of order. That was a weird bug.

---

# 0.5.37

Fixes inline field rendering to once again work for highlighting/links, as well as some other rendering quirks with
inline queries in codeblocks.

---

# 0.5.36

- Fix a bug when checking if an element is an HTMLElement.
- Properly include the nice improvements to the file count in tables and lists.

---

# 0.5.35

- Fix #1196, #1176: Re-enable HTML values. This was never a featured I advertised since it was just for some internal
  hackery, but it appears people just discovered it in DataviewJS queries.
- Improved initial time to popular queries that use `file.starred`.

---

# 0.5.34

- Fix #1174: Fix indexing with a variable.
- Fix an issue with the experimental calendar view.

---

# 0.5.33

- Fix a bug with inline views that was introduced in 0.5.32.

---

# 0.5.32

The Dataview API has been noticeably revamped - there are now approximately twice as many functions available on the
plugin API as there were before, and some additional utilities have been added to both the plugin and inline API. I
will be finishing up the associated new "extension" functionality shortly, which will allow:

1. For custom Dataview + DataviewJS functions to be added via plugins.
2. For custom renderable objects (progress bars, embedded task lists, embedded tables) to be added to any Dataview view via plugins.
3. For plugins to provide alternative behavior for some dataview functionality (such as integrating task plugins with
   the dataview task query).
   
As part of the API revamp, it is now possible to programmatically execute Dataview and DataviewJS queries - either for
using the existing Dataview query language in your own plugin, or for embedding dataview. The Dataview npm library also
now exposes many useful internal Dataview types, including the AST structure for all dataview queries.

I am hoping that cleaning up the Dataview API and making it much more extensible will allow for Dataview [to](to) integrate
much better with existing plugins, and to provide the full power of the in-memory index for plugins. I have been very
carefully watching index performance in recent weeks to ensure smooth frontend performance for anyone using the API
(with a goal of <10ms for most queries).

---

# 0.5.31

Tasks now have an `outlinks` list field which includes all links in the task; this can be used for finding tasks with
links in them.

---

# 0.5.30

- Added the `typeof(any)` function in Dataview, which obtains the type of any value for comparison:
```javascript
typeof("text") = "string"
typeof(1) = "number"
typeof([1, 2, 3]) = "array"
```

- Added the modulo operator (`%`) for doing integer division remainder. I.e., `14 % 2 = 0` and `14 % 3 = 2`.
- Fixed some minor spacing issues with lists in tables.

---

# 0.5.29

Fix another subtle incompatibility between 0.4.26 and 0.5.29 - if you frequently used empty inline fields (like
`Key::` with no value), the 0.5+ behavior is now the same as 0.4 behavior and will map such fields to null instead of an
empty string.

This may fix a broad variety of "subtly wrong" queries that you may have seen after the upgrade.

---

# 0.5.28

- Fix a bug with some more string concatenations and null handling.

---

# 0.5.27

More performance + correctness bugfixes.

- The parser has been made a little more robust to prevent major indexing issues (or at least recover from them
  quickly).
- Several new strange tag variants are now supported.
- Markdown links are now properly indexed again.

Some DataviewJS performance issues should be resolved now, especially for external plugins using Dataview. This fix
does involve a slight API break w.r.t. what types are wrapped into Dataview Arrays (which provide functions like
`.where()`). Generally, only Dataview-provided implicits are wrapped in data arrays now; frontmatter and inline fields
are always now regular JS arrays - use `dv.array()` to explicitly make a data array if you want the advanced querying.

---

# 0.5.26

More small bugfixes:

- Fix a few small link rendering issues.
- Tag extraction from tasks now handles punctuation properly.
- Upgrade luxon (which is embedded in DataviewJS) to 2.4.0.

---

# 0.5.25

- Fix #1147: Fix there being a `#null` tag for files with an empty `tag` or `tags` frontmatter.

---

# 0.5.24

Several bugfixes:

- Nulls are now sorted first rather than last; it's generally good practice to explicitly check for nulls in your
  queries to avoid strange behavior.
- Dataview now properly parses space-delimited tags (like `tags: abc def ghi`).
- Dataview now supports dropping the entire file cache in case of bugs.

---

# 0.5.23

- Fix #1140: Force API objects to be arrays if they are iterables.

---

# 0.5.22

- Fix #1135: Use 'x' instead of 'X' for checkboxes.

---

# 0.5.21

A long-overdue swap from the beta branch to the stable branch. The beta branch should not include any (intended) breaking
changes, and has some nice performance improvements that come along with it! Here are the major changes:

- Most views now use React and no longer flicker when updating; this is not the case yet for DataviewJS, which will be
  getting equivalent treatment in the future.
- Dataview now caches metadata, so Dataview loads are very fast after the first time you open your vault. Dataview still
  needs to visit every file when you update the plugin version, so that should be the only times you experience slower
  load times.
- A brand new task view backend and query which allows you to filter per-task, rather than per-page! Check the
  documentation for details, but this broadly means `WHERE` statements now use task properties instead of page
  properties.
- Some additional metadata is now available for use - `file.starred`, `file.lists`, and more metadata in
  `file.tasks`.

There have been some moderate documentation touch-ups to keep things up to date; I'm still working on a walkthrough for
common Dataview use cases. This review also includes about ~30-40 bugfixes; some new bugs may arise due to internal
changes, so please flag them if you encounter them.

---

# 0.5.20 (Beta)

Slight fix to hopefully improve some strange reported cases of bad indexing at startup.

---

# 0.5.19 (Beta)

Dataview now uses IndexedDB to cache file metadata, reducing startup time to virtually nothing if you've opened the
vault before; if you have a small vault (<1000 notes), you may notice a slight improvement, but large vaults and mobile
devices will notice a very significant performance improvement to "first valid paint". Some other performance parameters
have been tuned to hopefully make the default experience better.

A few small bugs related to rendering have also been squashed, including an issue with images being scaled wrongly.

---

# 0.5.18 (Beta)

- Tasks in task views now support alternative task status characters like '!' and '/'; thanks @ebullient.
- A few documentation nit fixes.
- Added `DataArray#sortInPlace` for a more efficient mutable sort for niche use cases.

---

# 0.5.17 (Beta)

- Improved behavior when clicking on tasks in the task view; will now properly scroll to the relevant line in long
  files!
- Fixed a bug with incorrect counts being displayed in task views.
- Added `tags` as a field available on task items, so you can now do things like `TASK WHERE contains(tags, "#tag")`.

---

# 0.5.16 (Beta)

Dataview now tracks initialization and will report when all files have been indexed in the console; you can
programmatically see this via `dataview:index-ready`, or by checking `api.index.initialized`.

---

# 0.5.15 (Beta)

- Add hover highlights to tables to make seeing rows a little easier.
- Tables and task lists now include counts of the number of results in the headers.
- Further improved task selection in the task view.

---

# 0.5.14 (Beta)

- Fix task highlighting when not grouping.
- Remove some spurious console logging.
- Slightly improve task highlighting behavior when clicking on a task.

---

# 0.5.13 (Beta)

Several smaller bugfixes!

- Fix #997: Use the group by field name in the table name.
- Prevent tons of errors if you incorrectly set the inline query prefix.

---

# 0.5.12 (Beta)

Improve error messages for queries somewhat and get rid of some ugly output.

---

# 0.5.11 (Beta)

Add detection of tasks inside of block quotes, as well as correctly implement automatic checking and unchecking of these
tasks.

---

# 0.5.10 (Beta)

Adds the `Dataview: Force Refresh Views` Command (accessible via the Ctrl+P command view) to force current views to
refresh immediately.

---

# 0.5.9 (Beta)

Another fix for due-date related emoji in tasks. I hate emoji.

---

# 0.5.8 (Beta)

Fix some issues with infinite loops of tasks due to bad Obsidian metadata (potentially due to being out of date?).

---

# 0.5.7 (Beta)

Fix issues with parsing '🗓️2021-08-29' due-date annotations on tasks, as well as an issue with properly extracting
due/completed/completed times for use in queries.

---

# 0.5.6 (Beta)

Proper release of 0.5.5 plus one additional small improvement:

- Add `duration * number` and `duration / number` operations for manipulation durations numerically.

---

# 0.5.5 (Beta)

More small features:

- Fix issues with task sorting not doing anything. Sort away!
- Table headers can now be arbitrary markdown. So you can put things like links in your headers: `TABLE (1 + 2) AS
  "[[File]]".
- You can now specify the size of an image embed by providing WxH in it's display property: `![[image.png|50x50]]`.

---

# 0.5.4 (Beta)

Improved image rendering for some link types, and adds the `embed(link)` and `embed(link, false)` options to convert
links to/from their embedded equivalents.

---

# 0.5.3 (Beta)

Iterative beta which adds a few nice QoL features and fixes some more bugs:

- Internally swapped to a React-based renderer; this should not have a noticeable perf or usability impact, but makes it
  easier for me to implement complex table/list behaviors.
- Naming your fields with `AS "Name"` is now optional; Dataview will infer the name from the expression automatically.
  For example, `TABLE 8 + 4, 3 + 6 FROM ...` is now a valid table expression, and the columns will be named `8 + 4` and
  `3 + 6` respectively.
- Some issues with array and object rendering were corrected.
- Error messages on empty dataview results were improved and now show up for all views.

Inline images are now rendered correctly in Dataview tables and lists - no more hacky `app://local/` shenanigans!

---

# 0.5.2 (Beta)

- Fix #971: Objects now work properly inside DataviewQL evaluation.

---

# 0.5.1 (Beta)

- Temporarily revert the new task metadata behavior: inline fields in sublists of tasks are added to the page, instead
  of the task. This behavior is not good, but is compatible with legacy usages of task metadata, which should not break
  some existing queries.
    - This behavior will be removed in the future behind a flag.
- Added the 'visual' field to tasks - if set, tasks render 'visual' instead of their regular text.
- Fixed `DataArray#mutate()`.

---

# 0.5.0 (Beta)

Re-release of broken release 0.4.23, now hopefully with fixes that make it work on (most) machines. I'll be doing beta
releases for a little while until I can confirm the new version is stable; use BRAT
(https://github.com/TfTHacker/obsidian42-brat) to easily track Dataview beta versions if you are interested in cutting
edge features.

---

# 0.4.25

Fix #867: Create a container div per taskList to allow for multiple task views.

---

# 0.4.24

Re-release of 0.4.23f since Obsidian does not automatically update between non-semver versions.

---

# 0.4.23f

Remove some code which attempted to make tag queries case-insensitive; I'll reimplement this more generally later (it
conflicts with existing queries which check tags via `contains(file.tags, "#Tag")` and similar).

---

# 0.4.23e

More task bugfixes / improvements, and a fix that caused task metadata to be duplicated.

---

# 0.4.23d

More inline field list parsing bug fixes. Hopefully we're back to a nice working order!

---

# 0.4.23c

Bugfix which adds support for '1)' style lists, as well as a very annoying null issue due to JavaScript being a very
sad, very sad language.

---

# 0.4.23b

Bugfix for bad inlink/outlink computations; links were not being normalized properly so reverse lookups were not
working.

---

# 0.4.23

The Task Update! This release reworks how dataview handles tasks and list items so that they should be much more
intuitive to use and interact with:

1. **Subtask Support**: Queries now search over all list items, instead of only over root elements. This should make
   task filtering much more usable, especially if you tend to put tasks under other list items or care specifically
   about subtasks.
2. **Multiline Support**: Dataview now understands multi-line tasks and renders/updates them correctly.
3. **Immediately Navigate to Task**: The new task view, aside from looking a little cleaner than previous views, now
   immediately navigates to the task in it's original file on click and selects it.
4. **Grouping Support**: For DataviewJS users, `dv.taskList` now supports grouping (as produced by `groupBy` and the new
   `groupIn`) natively.

For DataviewJS users, the task and list representation has changed: `file.tasks` (and the new `file.lists`) contain
every single task (including subtasks) in the file, instead of only the root elements. You can return to previous
behavior by filtering out tasks with a non-null parent - i.e., `file.tasks.where(task => !task.parent)`. `dv.taskList`
will intelligently deal with properly nesting and de-duplicating tasks, so just filter to the tasks you want to render and
the API will do the rest.

This release also includes general backend improvements as we prepare for live-editing in Dataview views, as well as
several community-contributed API improvements:

- `DataArray#groupIn`: For grouping already grouped data, you can now use `array.groupIn(v => ...)`, which will group
  the innermost (original) data in the array instead of the top level groups. This allows for more easily grouping
  recursively, such as `dv.pages().groupBy(page => page.file.folder).groupIn(page => page.title)` producing a grouping
  of folders, then page titles.
- `substring(string, start[, end])`: The last major missing string function is now available! Take slices of strings.
- Improved `dv.el()` and other HTML functions - thanks @vitaly.
- null and undefined entries sort at the end instead of the beginning by default; sorry to those whose code sorts wrong
  because of this, but it is a better default for most people's use cases.
- All links are now properly normalized to their full paths, fixing many link comparison edge cases in DataviewJS.

Documentation additions for the new task functionality will be coming out in the next few days. The next release 0.4.24
is currently targeting expanded `FROM` query support, basic table view improvements, and general exporting functionality
for Dataview. See you then!

---

# 0.4.22

The @pjeby update! This includes several performance improvements suggested by @pjeby to dramatically improve background
Dataview performance as well as reduce some memory pressure. It also includes some minor bug-fixes and preliminary
functionality:

- Target ES2018 for better Promise support
- Allow parsing shorthands in `dv.date()`.
- Add additional metadata to inline field rendering which can be styled.
- Cleanup events & workers on plugin uninstall, improving the Dataview uninstall/disable/reload experience.
- Add preliminary `CALENDAR` queries - rendering similar to the obsidian-calendar plugin, see the documentation!

Dataview should perform much better on startup and when you have lots of tabs open - thanks again to @pjeby.

---

# 0.4.21

Bugfix release which primarily fixes issues that Dataview had with the live preview mode in upcoming Obsidian versions;
Dataview live preview should now be functional. Also includes a number of smaller bugfixes.

- Fix #646: Add `date(yesterday)` to create a date 24 hours ago.
- Fix #618: Luxon is now available on the dataview API (`dv.luxon`).
- Fix #510: Add `dv.duration()` for parsing durations.
- Fix #647: All HTML functions in the DataviewJS API now return their rendered objects.
- Fix #652: Fix parsing of invalid dates.
- Fix #629: Fix block link parsing.
- Fix #601: Timezones are now rendered properly and parsed properly in Dataview dates.
- PR #637: Add `meta(link)` which allows you to access various metadata about a link itself.
- Various minor null safety fixes.
- Dataview now reports it's exact version and build time in logs.

---

# 0.4.20

Some feature work (mostly by other contributors) while I while away at section metadata. May also fix a few bugs!

- Fix #448: You can now use the "Task Completion Tracking" option to automatically add completion metadata to tasks
  which are checked/unchecked through Dataview. Thanks to @sheeley.
- Add a search bar to documentation. Thanks to @tzhou.
- Add new date expressions for the start of the week (`date(sow)`), and the end of the week (`date(eow)`). Thanks
  @Jeamee and @v_mujunma.

Small minor bugfix / security releases may follow in the near future; otherwise, the next major release will include
section and object metadata.

---

# 0.4.19

Bugfix release which corrects emoji parsing & localization issues.

- Add `DataArray#into`, which lets you index into objects without flattening.
- Renamed 'header' to 'section' in task metadata; 'header' will remain around for a few major releases to let people
  naturally migrate.
- Fix #487: You no longer need spaces around '*' in expressions.
- Fix #559: Fix unicode issues in variable canonicalization which was causing problems with non-Latin inline field
  keys.

## Duration Parsing

You can now include multiple units in durations: `dur(8 minutes, 4 seconds)` or `dur(2yr8mo12d)`. You can separate
durations by commas, or use the abbreviated syntax with/without spaces.

---

# 0.4.18

Bugfix release which fixes bad inline field highlighting if '[' and '(' are mixed on the same line in particular orders.

---

# 0.4.17

Minor feature release to patch up more implementation holes.

## Single File Queries

You can now query from a specific file (instead of just folders and tags) by specifying the full file path:

```
TASK FROM "dataview/Test"
...
```

This is primarily useful for task queries, but will soon be useful for section and object queries in the near future as
well.

## Better Inline Field Highlighting

The CSS for inline field highlighting has been fixed and some compatibility issues improved, so it should work on all
themes now instead of only a few.

## dv.el()

DataviewJS now has `dv.el()`, which is like existing functions like `dv.paragraph` and `dv.span` but can create any
HTML element type; for example:

```js
dv.el("b", "Text!");
dv.el("i", 18);
```

---

# 0.4.16

Small performance release which substantially reduces the impact Dataview has on vault loading times (by spreading out
file loading). The Dataview Index is now also eagerly initialized, so plugin consumers of the API can immediately start
using it instead of waiting for the `dataview:api-ready` event.

---

# 0.4.15

A simple fix for #537 which properly 'awaits' value rendering in `dv.view()`. Fixes issues with values rendering out of
order.

---

# 0.4.14

Small bugfix release.

- Fixes inline field evaluation when using the new fancy highlighting.
- You can now configure whether task links should show up at the beginning or end of the task (or just disable them)
  in the "Task Link Location" setting.
- Most setting updates will immediately be applied to existing Dataviews.

---

# 0.4.13

Bugfix release which adds fancy rendering to inline-inline fields and includes a few bugfixes.

## Pretty Inline Fields

Inline fields of the form `[key:: value]` will now be rendered with fancy new HTML! By default, they are rendered with
both the key and value. You can only render the value using parenthesis instead: `(key:: value)`. You can disable
this feature in the configuration.

Full-line inline fields (that Dataview has supported for a long time) will gain similar rendering support soon; in the
meanwhile, give the new syntax a try!

### Task Linking

Tasks now render with a link to the page/section that they are defined in, making `GROUP BY` and custom task
editing easier to do:

- [ ] A Task. 🔗
- [ ] Another Task. 🔗
    - [ ] Some Random Subtask. 🔗

You can configure the symbol for the link or disable it altogether.

### Improving DataviewJS Posture

I am currently actively looking into improving DataviewJS sandboxing and general security posture. As a first small step
in this, I have made DataviewJS opt-in instead of opt-out, and added a separate control for Inline DataviewJS. You may
need to re-enable it in your settings if you use it.

More improvements and better JavaScript sandboxing will follow.

---

# 0.4.12-hotfix1

Re-release of 0.4.12 that fixes an important indexing issue.

- Fix #505: Use `completion` instead of `completed` when setting task completion time.
- Fix #509: Add `startswith` / `endswith` string functions.
- Fix #488: Add `padleft` and `padright`, and `string`.
- Fix #506, #512: Fix date comparisons due to a bizarre date zone issue.

---

# 0.4.12

Bugfix release following up 0.4.11 which includes a few minor function additions.

- Fix #512: Strange zone issue causing dates to not be equal.
- Fix #506: Same as #512.
- Fix #488: Add `padleft` / `padright` functions.
- Fix #509: Add `startswith` and `endswith` functions.
- Fix #505: Correctly read completion dates for tasks from `completion`.

This release also includes improved testing thanks to mocking Obsidian plugin APIs!

---

# 0.4.11

Fixes task behavior and adds "truly inline" fields!

## Improved Task Behavior

Task queries are now much improved from their primitive foundations - you can now filter, sort, and group them! The FROM
block is still page-based, sadly, though you can simply use `WHERE` instead if desired. For example, you can now access
task fields like `text`, `line`, or `completed`:

```
TASK WHERE contains(text, "#tag")
WHERE !completed
GROUP BY file.folder
```

The full list of all available task metadata can be found
[here](https://blacksmithgu.github.io/obsidian-dataview/data-annotation/#tasks); tasks include all the information
needed to uniquely identify them, and automatically inherit all of the metadata from their parent file as well (so you
can access `file.name`, for example). You can also annotate tasks with inline fields, as described in the section below.

There is some additional UX work to be done - primarily on more easily allowing you to navigate to where the task is
defined, as well as render tasks in views other than the `TASK` view.  The semantics of how grouping works (to make it
more intuitive/useful than it currently is) will likely also be revisited.

## Inline Inline Fields

Early support for truly inline fields have been added, where you can add metadata in the middle of a sentence. It looks
similar to existing inline field syntax, but with brackets or parenthesis:

```
I would rate this a [rating:: 6]. It was (thoughts:: acceptable).
```

Improved rendering for all inline fields is coming in an upcoming update to improve the visual look of these inline
fields.


## Issues

- Fix #496: Fix task `SORT` functionality to do something.
- Fix #492: Tasks now properly annotated with parent file information.
- Fix #498: Fix task checking/unchecking logic (which broke due to a change in the task regex...).

---

# Initial

Start of the automatic changelog.


================================================
FILE: LICENSE.txt
================================================
MIT License

Copyright (c) 2021 Michael Brenan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
# Obsidian Dataview

Treat your [Obsidian Vault](https://obsidian.md/) as a database which you can query from. Provides a JavaScript API and
pipeline-based query language for filtering, sorting, and extracting data from Markdown pages. See the Examples section
below for some quick examples, or the full [reference](https://blacksmithgu.github.io/obsidian-dataview/) for all the details.

## Examples

Show all games in the game folder, sorted by rating, with some metadata:

~~~markdown
```dataview
table time-played, length, rating
from "games"
sort rating desc
```
~~~

![Game Example](docs/docs/assets/game.png)

---

List games which are MOBAs or CRPGs.

~~~markdown
```dataview
list from #game/moba or #game/crpg
```
~~~

![Game List](docs/docs/assets/game-list.png)

---

List all markdown [tasks](https://blacksmithgu.github.io/obsidian-dataview/data-annotation/#tasks) in un-completed projects:

~~~markdown
```dataview
task from #projects/active
```
~~~

![Task List](docs/docs/assets/project-task.png)

---

Show all files in the `books` folder that you read in 2021, grouped by genre and sorted by rating:

~~~markdown
```dataviewjs
for (let group of dv.pages("#book").where(p => p["time-read"].year == 2021).groupBy(p => p.genre)) {
	dv.header(3, group.key);
	dv.table(["Name", "Time Read", "Rating"],
		group.rows
			.sort(k => k.rating, 'desc')
			.map(k => [k.file.link, k["time-read"], k.rating]))
}
```
~~~

![Books By Genre](docs/docs/assets/books-by-genre.png)

## Usage

For a full description of all features, instructions, and examples, see the [reference](https://blacksmithgu.github.io/obsidian-dataview/). For a more brief outline, let us examine the two major aspects of Dataview: *data* and *querying*.

#### **Data**

Dataview generates *data* from your vault by pulling
information from **Markdown frontmatter** and **Inline fields**.

- Markdown frontmatter is arbitrary YAML enclosed by `---` at the top of a markdown document which can store metadata
  about that document.
- Inline fields are a Dataview feature which allow you to write metadata directly inline in your markdown document via
  `Key:: Value` syntax.

Examples of both are shown below:

```yaml
---
alias: "document"
last-reviewed: 2021-08-17
thoughts:
  rating: 8
  reviewable: false
---
```
```markdown
# Markdown Page

Basic Field:: Value
**Bold Field**:: Nice!
You can also write [field:: inline fields]; multiple [field2:: on the same line].
If you want to hide the (field3:: key), you can do that too.
```

#### **Querying**

Once you've annotated documents and the like with metadata, you can then query it using any of Dataview's four query
modes:

1. **Dataview Query Language (DQL)**: A pipeline-based, vaguely SQL-looking expression language which can support basic
   use cases. See the [documentation](https://blacksmithgu.github.io/obsidian-dataview/query/queries/) for details.

   ~~~markdown
   ```dataview
   TABLE file.name AS "File", rating AS "Rating" FROM #book
   ```
   ~~~

2. **Inline Expressions**: DQL expressions which you can embed directly inside markdown and which will be evaluated in
   preview mode. See the [documentation](https://blacksmithgu.github.io/obsidian-dataview/reference/expressions/) for
   allowable queries.

   ```markdown
   We are on page `= this.file.name`.
   ```

3. **DataviewJS**: A high-powered JavaScript API which gives full access to the Dataview index and some convenient
   rendering utilities. Highly recommended if you know JavaScript, since this is far more powerful than the query
   language. Check the [documentation](https://blacksmithgu.github.io/obsidian-dataview/api/intro/) for more details.

   ~~~markdown
   ```dataviewjs
   dv.taskList(dv.pages().file.tasks.where(t => !t.completed));
   ```
   ~~~

4. **Inline JS Expressions**: The JavaScript equivalent to inline expressions, which allow you to execute arbitrary JS
   inline:

   ~~~markdown
   This page was last modified at `$= dv.current().file.mtime`.
   ~~~

#### JavaScript Queries: Security Note

JavaScript queries are very powerful, but they run at the same level of access as any other Obsidian plugin. This means
they can potentially rewrite, create, or delete files, as well as make network calls. You should generally write
JavaScript queries yourself or use scripts that you understand or that come from reputable sources. Regular Dataview
queries are sandboxed and cannot make negative changes to your vault (in exchange for being much more limited).

## Contributing

Contributions via bug reports, bug fixes, documentation, and general improvements are always welcome. For more major
feature work, make an issue about the feature idea / reach out to me so we can judge feasibility and how best to
implement it.

#### Local Development

The codebase is written in TypeScript and uses `rollup` / `node` for compilation; for a first time set up, all you
should need to do is pull, install, and build:

```console
foo@bar:~$ git clone git@github.com:blacksmithgu/obsidian-dataview.git
foo@bar:~$ cd obsidian-dataview
foo@bar:~/obsidian-dataview$ npm install
foo@bar:~/obsidian-dataview$ npm run dev
```

This will install libraries, build dataview, and deploy it to `test-vault`, which you can then open in Obsidian. This
will also put `rollup` in watch mode, so any changes to the code will be re-compiled and the test vault will automatically
reload itself.

#### Preparing for creating pull requests

If you plan on doing pull request, we would also recommend to do the following in advance of creating the pull request:

```console
foo@bar:~$ npm run dev
foo@bar:~$ npm run check-format
foo@bar:~$ npm run format
foo@bar:~$ npm run test
```

The third step of `npm run format` is only needed if the format check reports some issue.

#### Installing to Other Vaults

If you want to dogfood dataview in your real vault, you can build and install manually. Dataview is predominantly a
read-only store, so this should be safe, but watch out if you are adjusting functionality that performs file edits!

```console
foo@bar:~/obsidian-dataview$ npm run build
foo@bar:~/obsidian-dataview$ ./scripts/install-built path/to/your/vault
```

#### Building Documentation

We use `MkDocs` for documentation (found in `docs/`). You'll need to have python and pip to run it locally:

```console
foo@bar:~/obsidian-dataview$ pip3 install mkdocs mkdocs-material mkdocs-redirects
foo@bar:~/obsidian-dataview$ cd docs
foo@bar:~/obsidian-dataview/docs$ mkdocs serve
```

This will start a local web server rendering the documentation in `docs/docs`, which will live-reload on change.
Documentation changes are automatically pushed to `blacksmithgu.github.io/obsidian-dataview` once they are merged
to the main branch.

#### Using Dataview Types In Your Own Plugin

Dataview publishes TypeScript typings for all of its APIs onto NPM (as `blacksmithgu/obsidian-dataview`). For
instructions on how to set up development using Dataview, see [setup instructions](https://blacksmithgu.github.io/obsidian-dataview/plugin/develop-against-dataview/).

## Support

Have you found the Dataview plugin helpful, and want to support it? I accept donations which go towards future
development efforts. I generally do not accept payment for bug bounties/feature requests, as financial incentives add
stress/expectations which I want to avoid for a hobby project!

Support @blacksmithgu:  
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/donate?business=Y9SKV24R5A8BQ&item_name=Open+source+software+development&currency_code=USD)

Support @holroy:  
<a href="https://www.buymeacoffee.com/holroy" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 40px !important;width: 175px !important;" ></a>


================================================
FILE: __mocks__/data-import/web-worker/import-manager.ts
================================================
/** A mock for `FileImporter` which runs on the same thread. */

import { runImport } from "data-import/web-worker/import-impl";
import { CachedMetadata, MetadataCache, TFile, Vault } from "obsidian";

export class FileImporter {
    public constructor(public numWorkers: number, public vault: Vault, public metadataCache: MetadataCache) {}

    public async reload<T>(file: TFile): Promise<T> {
        let contents = await this.vault.read(file);
        let metadata = await this.metadataCache.getFileCache(file);
        return runImport(file.path, contents, file.stat, metadata as CachedMetadata) as any as T;
    }
}


================================================
FILE: __mocks__/obsidian.ts
================================================
import EventEmitter from "events";

/** Basic obsidian abstraction for any file or folder in a vault. */
export abstract class TAbstractFile {
    /**
     * @public
     */
    vault: Vault;
    /**
     * @public
     */
    path: string;
    /**
     * @public
     */
    name: string;
    /**
     * @public
     */
    parent: TFolder;
}

/** Tracks file created/modified time as well as file system size. */
export interface FileStats {
    /** @public */
    ctime: number;
    /** @public */
    mtime: number;
    /** @public */
    size: number;
}

/** A regular file in the vault. */
export class TFile extends TAbstractFile {
    stat: FileStats;
    basename: string;
    extension: string;
}

/** A folder in the vault. */
export class TFolder extends TAbstractFile {
    children: TAbstractFile[];

    isRoot(): boolean {
        return false;
    }
}

export class Vault extends EventEmitter {
    getFiles() {
        return [];
    }
    trigger(name: string, ...data: any[]): void {
        this.emit(name, ...data);
    }
}

export class Component {
    registerEvent() {}
}


================================================
FILE: cspell.json
================================================
{
  "version": "0.2",
  "ignorePaths": [],
  "dictionaryDefinitions": [],
  "dictionaries": [],
  "words": [
    "aaab",
    "akey",
    "alexfertel",
    "AnnaKornfeldSimpson",
    "apng",
    "artisticat",
    "autorelease",
    "bcbe",
    "bimap",
    "binaryop",
    "bkey",
    "blacksmithgu",
    "Brenan",
    "bryc",
    "callouts",
    "canonicalization",
    "canonicalize",
    "CANONICALIZER",
    "canonicalizes",
    "canonicalizing",
    "carlesalbasboix",
    "cday",
    "charleshan",
    "Cheatsheet",
    "Cheatsheets",
    "Chouffy",
    "clsname",
    "codemirror",
    "combinators",
    "compday",
    "comptime",
    "concat",
    "containsword",
    "crashy",
    "cres",
    "crog",
    "crpg",
    "cssclasses",
    "currencyformat",
    "cyrb",
    "dailys",
    "datapoints",
    "Datarow",
    "Dataview",
    "dataviewjs",
    "Dataviews",
    "datefield",
    "ddd",
    "DDTHH",
    "début",
    "dedup",
    "dformat",
    "dogfood",
    "Donadio",
    "dtformat",
    "duedate",
    "dueday",
    "duetime",
    "durationformat",
    "dvjs",
    "econtains",
    "elink",
    "embeddable",
    "endswith",
    "errorbox",
    "etags",
    "Evals",
    "eyuelt",
    "failable",
    "fastfood",
    "fdefault",
    "fileset",
    "Filetext",
    "Filipe",
    "frontmatter",
    "fullscan",
    "functionname",
    "GamerGirlandCo",
    "gdhjg",
    "gentlegiantJGC",
    "Gott",
    "Groot",
    "helloxx",
    "Hoeven",
    "holroy",
    "iamrecursion",
    "icontains",
    "iden",
    "ifield",
    "iitem",
    "implicits",
    "INDEXEDDB",
    "Ingrouped",
    "Inlines",
    "inlink",
    "inlinks",
    "Jeamee",
    "jfif",
    "Kanban",
    "kometenstaub",
    "ldefault",
    "leoccyao",
    "lezer",
    "Linkpath",
    "localforage",
    "localtime",
    "longkeyidontneedwhenreading",
    "lres",
    "luxon",
    "lwrap",
    "MarioRicalde",
    "matchreg",
    "maxby",
    "mday",
    "meello",
    "meep",
    "Millis",
    "minby",
    "mkdocs",
    "mnaoumov",
    "moba",
    "mobas",
    "mocsa",
    "mt-krainski",
    "mvalues",
    "nestedfield",
    "nonnull",
    "noopener",
    "Nums",
    "offref",
    "onwarn",
    "ooker777",
    "outlink",
    "outlinks",
    "padleft",
    "padright",
    "Pagerow",
    "papaparse",
    "parsimmon",
    "pathlike",
    "pjeby",
    "pjepg",
    "pleh",
    "preact",
    "protofarer",
    "proxied",
    "pymdownx",
    "RaviOnline",
    "rawlink",
    "recurkey",
    "Refreshable",
    "REGEXES",
    "regexmatch",
    "regexreplace",
    "regextest",
    "renderable",
    "Repr",
    "RyotaUshio",
    "sandboxed",
    "sandboxing",
    "seanlzx",
    "sheeley",
    "sohanglal",
    "somemetadata",
    "somidad",
    "spoopy",
    "Stardew",
    "startswith",
    "steamid",
    "steg",
    "striptime",
    "subargs",
    "subcontainer",
    "subeval",
    "subfolders",
    "sublists",
    "Subsettings",
    "subsources",
    "subtag",
    "Subtags",
    "subvalue",
    "subword",
    "succ",
    "superfences",
    "tasklist",
    "tcopy",
    "Templater",
    "Testcase",
    "toolbelt",
    "trunc",
    "typeof",
    "tzhou",
    "unindented",
    "unrendered",
    "v_mujunma",
    "vals",
    "vararg",
    "varargs",
    "vectorize",
    "vitaly",
    "vpos",
    "vrtmrz",
    "weekyear",
    "whitespaces",
    "xxhello",
    "ymdh",
    "ymdhm",
    "ymdhms",
    "zerollup",
    "Статус"
  ],
  "ignoreWords": [],
  "import": [],
  "enabled": true
}


================================================
FILE: docs/.gitignore
================================================
site/


================================================
FILE: docs/docs/annotation/add-metadata.md
================================================
# Adding Metadata to your Pages

Dataview cannot query all content of your vault. In order to be able to search, filter and display content, this content needs to be **indexed**. Some content is indexed automatically, like bullet points or task lists - so called **Implicit fields**, more on that below - and other data needs to be saved in a metadata **field** to be accessible through dataview. 

## What is a "field"?

A metadata field is a pair of a **key** and a **value**. The _value_ of a field has a data type (more on that [here](./types-of-metadata.md)) that determines how this field will behave when querying it. 

You can add any number of fields to a **note**, a **list item** or a **task**. 

## How do I add fields?

You can add fields to a **note** in three different ways. How a field look like depends on the way you add it.

On **tasks or list items**, you will have YAML Frontmatter information available, but won't be able to add them to a specific list item. If you want to add metadata to one list item or task only, use [Inline Fields](#inline-fields).

### Frontmatter

Frontmatter is a common Markdown extension which allows for YAML metadata to be added to the top of a page. It is natively supported by Obsidian and explained in its [official documentation](https://help.obsidian.md/Advanced+topics/YAML+front+matter). All YAML Frontmatter fields will be automatically available as Dataview fields.

```yaml
    ---
    alias: "document"
    last-reviewed: 2021-08-17
    thoughts:
      rating: 8
      reviewable: false
    ---
```

With this your note has metadata fields named `alias`, `last-reviewed`, and `thoughts`. Each of these have different **data types**:

- `alias` is a [text](types-of-metadata.md#text), because its wrapped in ""
- `last-reviewed` is a [date](types-of-metadata.md#date), because it follows the ISO date format
- `thoughts` is a [object](types-of-metadata.md#object) field, because it uses the YAML Frontmatter object syntax

You could query for this note with the following query:

~~~
```dataview
LIST
WHERE thoughts.rating = 8
```
~~~

### Inline Fields

For those wanting a more natural-looking annotation, Dataview supports "inline" fields via a `Key:: Value` syntax that you can use everywhere in your file. This allows you to write your queryable data right where you need it - for example in the middle of a sentence. 

If your inline field has an own line, without any content beforehand, you can write it like this: 

```markdown
# Markdown Page

Basic Field:: Some random Value
**Bold Field**:: Nice!
```

All content after the `::` is the value of the field until the next line break.

!!! hint "Mind the `::`"
    Note that you need to use a double colon `::` between key and value when using inline fields, contrary to YAML Frontmatter fields where one colon is enough. 

If you want to embed metadata inside sentences, or multiple fields on the same line, you can use the bracket syntax and wrap your field in square brackets:

```markdown
I would rate this a [rating:: 9]! It was [mood:: acceptable].
```

!!! info "Fields on list items and tasks"
    When you want to annotate a list item, e.g. a task, with metadata, you always need to use the bracket syntax (because the field is not the only information in this line)
    ```markdown
    - [ ] Send an mail to David about the deadline [due:: 2022-04-05].
    ```
    Bracketed inline fields are the only way to explicitly add fields to specific list items, YAML frontmatter always applies to the whole page (but is also available in context of list items.)

There is also the alternative parenthesis syntax, which hides the key when
rendered in Reader mode:

```markdown
This will not show the (longKeyIDontNeedWhenReading:: key).
```

will render to:

```markdown
This will not show the key.
```

You can use YAML Frontmatter and Inline fields with all syntax variants together in one file. You do not need to decide for one and can mix them to fit your workflow.

## Field names

Imagine you used all the examples for Inline fields you see above in one note, then following metadata would be available to you:

| Metadata Key | Sanitized Metadata key | Value | Data Type of Value |
| ----------- | ------------------------|----------- | ----------- |
| `Basic Field` | `basic-field`  | Some random Value | Text |
| `Bold Field` | `bold-field`  | Nice! | Text |
| `rating` | - | 9 | Number |
| `mood` | - | acceptable | Text |
| `due` | - | Date Object for 2022-04-05 | Date |
| `longKeyIDontNeedWhenReading` | `longkeyidontneedwhenreading` | key | Text |

Like you can see in the table, if you are using **spaces or capitalized letters** in your metadata key name, dataview will provide you with a **sanitized version** of the key. 

**Keys with spaces** cannot be used in a query as-is. You have two possibilities here: Either use the sanitized name, that is always all lowercase and with dashes instead of spaces or use the **row** variable syntax. Find out more [in the FAQ](../resources/faq.md).

**Keys with capitalized letters** can be used as-is, if you wish. The sanitized version allows you to query for a key independent of its capitalization and makes it easier to use: You can query the same field that's, for example, in one file named `someMetadata` and in another `someMetaData` when using the sanitized key `somemetadata`. 

In addition, the **bold field key is missing its formatting tokens**. Even though the `**` used to make it appear bold are part of the key name in the file, they are left out when indexing your note. The same goes for all other built-in formatting, like strike through or italic. This means formatted keys can only be queried without their formatting. This allows you to format the key in context of the note without worrying that you might create different keys for the same type of information. 

### Usage of emojis and non-latin characters

You are not limited to latin characters when naming your metadata fields. You can use all characters available in UTF-8:

```markdown
Noël:: Un jeu de console
クリスマス:: 家庭用ゲーム機
[🎅:: a console game]
[xmas🎄:: a console game]
```

**Using emojis as metadata keys** is possible, but it comes with some limitations. When using emojis in field names, you need to put them into square brackets so that dataview recognize them correctly. 
Also, please be aware when switching the OS (i.e. from Windows to Android), the same emoji could use another character code and you might not find your metadata when querying it.

!!! info "Task Field Shorthands"
    An exception to this are the [shorthand syntax](./metadata-tasks.md#field-shorthands) in Tasks. You can use shorthands without bracketing. Please mind though that this only counts for listed shorthands - every other field (if with emojis or not) need to use the `[key:: value]` syntax.

## Implicit fields

Even if you do not add any metadata explicitly to your note, dataview provides you with a big amount of indexed data out of the box. Some examples for implicit fields are:

- day the file was created (`file.cday`)
- links in the file (`file.outlinks`)
- tags in the file (`file.etags`)
- all list items in the file (`file.lists` and `file.tasks`)

and many more. Available implicit fields differ depending if you look at a page or a list item. Find the full list of available implicit fields on [Metadata on pages](metadata-pages.md) and [Metadata on Tasks and Lists](metadata-tasks.md).


================================================
FILE: docs/docs/annotation/metadata-pages.md
================================================
# Metadata on Pages

You can add fields to a markdown page (a note) in three different ways - via Frontmatter, Inline fields and Implicit fields. Read more about the first two possibilities in ["how to add metadata"](./add-metadata.md).

## Implicit Fields

Dataview automatically adds a large amount of metadata to each page. These implicit and automatically added fields are collected under the field `file`. Following are available:

| Field Name | Data Type | Description |
| --------------------- | --------- | ----------- |
| `file.name` | Text | The file name as seen in Obsidians sidebar. |
| `file.folder` | Text | The path of the folder this file belongs to. |
| `file.path` | Text | The full file path, including the files name. |
| `file.ext` | Text | The extension of the file type; generally `md`. |
| `file.link` | Link | A link to the file. |
| `file.size` | Number | The size (in bytes) of the file. |
| `file.ctime` | Date with Time | The date that the file was created. |
| `file.cday` | Date | The date that the file was created. |
| `file.mtime` | Date with Time | The date that the file was last modified. |
| `file.mday` | Date | The date that the file was last modified. |
| `file.tags` | List | A list of all unique tags in the note. Subtags are broken down by each level, so `#Tag/1/A` will be stored in the list as `[#Tag, #Tag/1, #Tag/1/A]`. |
| `file.etags` | List | A list of all explicit tags in the note; unlike `file.tags`, does not break subtags down, i.e. `[#Tag/1/A]` |
| `file.inlinks` | List | A list of all incoming links to this file, meaning all files that contain a link to this file. |
| `file.outlinks` | List | A list of all outgoing links from this file, meaning all links the file contains. |
| `file.aliases` | List | A list of all aliases for the note as defined via the [YAML frontmatter](https://help.obsidian.md/How+to/Add+aliases+to+note). |
| `file.tasks` | List | A list of all tasks (I.e., `| [ ] some task`) in this file. |
| `file.lists` | List | A list of all list elements in the file (including tasks); these elements are effectively tasks and can be rendered in task views. |
| `file.frontmatter` | List | Contains the raw values of all frontmatter in form of `key | value` text values; mainly useful for checking raw frontmatter values or for dynamically listing frontmatter keys. |
| `file.day` | Date | Only available if the file has a date inside its file name (of form `yyyy-mm-dd` or `yyyymmdd`), or has a `Date` field/inline field. |
| `file.starred` | Boolean | If this file has been bookmarked via the Obsidian Core Plugin "Bookmarks". |

## Example page

This is a small Markdown page which includes both user-defined ways to add metadata:

```markdown
---
genre: "action"
reviewed: false
---
# Movie X
#movies

**Thoughts**:: It was decent.
**Rating**:: 6

[mood:: okay] | [length:: 2 hours]
```

In addition to the values you see here, the page has also all keys listed above available.

### Example Query

You can query part of the above information with following query, for example:

~~~yaml
```dataview
TABLE file.ctime, length, rating, reviewed
FROM #movies
```
~~~


================================================
FILE: docs/docs/annotation/metadata-tasks.md
================================================
# Metadata on Tasks and Lists

Just like pages, you can also add **fields** on list item and task level to bind it to a specific task as context. For this you need to use the [inline field syntax](add-metadata.md#inline-fields):

```markdown
- [ ] Hello, this is some [metadata:: value]!
- [X] I finished this on [completion:: 2021-08-15].
```

Tasks and list items are the same data wise, so all your bullet points have all the information described here available, too.

## Field Shorthands

The [Tasks](https://publish.obsidian.md/tasks/Introduction) plugin introduced a different [notation by using Emoji](https://publish.obsidian.md/tasks/Reference/Task+Formats/Tasks+Emoji+Format) to configure the different dates related to a task. In the context of Dataview, this notation is called `Field Shorthands`. The current version of Dataview only support the dates shorthands as shown below. The priorities and recurrence shorthands are not supported.

=== "Example"


=== "Example"
    - [ ] Due this Saturday 🗓️2021-08-29
    - [x] Completed last Saturday ✅2021-08-22
    - [ ] I made this on ➕1990-06-14
    - [ ] Task I can start this weekend 🛫2021-08-29
    - [x] Task I finished ahead of schedule ⏳2021-08-29 ✅2021-08-22

There are two specifics to these emoji-shorthands. First, they omit the inline field syntax (no `[🗓️:: YYYY-MM-DD]` needed) and secondly, they map to a **textual** field name data-wise:

| Field name | Short hand syntax |
| ---------- | ----------------- |
| due | `🗓️YYYY-MM-DD` |
| completion |  `✅YYYY-MM-DD` |
| created | `➕YYYY-MM-DD` |
| start | `🛫YYYY-MM-DD` |
| scheduled | `⏳YYYY-MM-DD` |

This means if you want to query for all tasks that are completed 2021-08-22, you'll write:

~~~markdown
```dataview
TASK
WHERE completion = date("2021-08-22")
```
~~~

Which will list both variants - shorthands and textual annotation:

```markdown
- [x] Completed last Saturday ✅2021-08-22
- [x] Some Done Task [completion:: 2021-08-22]
```

## Implicit Fields

As with pages, Dataview adds a number of implicit fields to each task or list item:

!!! info "Inheritance of Fields"
    Tasks inherit *all fields* from their parent page - so if you have a `rating` field in your page, you can also access it on your task in a `TASK` Query.


| Field name | Data Type | Description |
| ---------- | --------- | ----------- |
| `status` |  Text | The completion status of this task, as determined by the character inside the `[ ]` brackets. Generally a space `" "` for incomplete tasks and an `"x"` for completed tasks, but allows for plugins which support alternative task statuses. |
| `checked` |  Boolean  | Whether or not this task's status is **not** empty, meaning it has some `status` character (which may or may not be `"x"`) instead of a space in its `[ ]` brackets. |
| `completed` |  Boolean  | Whether or not this *specific* task has been completed; this does not consider the completion or non-completion of any child tasks. A task is explicitly considered "completed" if it has been marked with an `"x"`. If you use a custom status, e.g. `[-]`, `checked` will be true, whereas `completed` will be false. |
| `fullyCompleted` |  Boolean  | Whether or not this task and **all** of its subtasks are completed. |
| `text` |  Text  | The plain text of this task, including any metadata field annotations. |
| `visual` | Text | The text of this task, which is rendered by Dataview. This field can be overridden in DataviewJS to allow for different task text to be rendered than the regular task text, while still allowing the task to be checked (since Dataview validation logic normally checks the text against the text in-file). |
| `line` |  Number  | The line of the file this task shows up on. |
| `lineCount` |  Number  | The number of Markdown lines that this task takes up. |
| `path` |  Text  | The full path of the file this task is in. Equals to `file.path` for [pages](./metadata-pages.md). |
| `section` | Link |  Link to the section this task is contained in. |
| `tags` | List  | Any tags inside the task text. |
| `outlinks` | List |  Any links defined in this task. |
| `link` | Link  |  Link to the closest linkable block near this task; useful for making links which go to the task. |
| `children` | List  | Any subtasks or sublists of this task. |
| `task` | Boolean  | If true, this is a task; otherwise, it is a regular list element. |
| `annotated` | Boolean  | True if the task text contains any metadata fields, false otherwise. |
| `parent` | Number |  The line number of the task above this task, if present; will be null if this is a root-level task. |
| `blockId` | Text | The block ID of this task / list element, if one has been defined with the `^blockId` syntax; otherwise null. |

With usage of the [shorthand syntax](#field-shorthands), following additional properties may be available:

- `completion`: The date a task was completed.
- `due`: The date a task is due, if it has one.
- `created`: The date a task was created.
- `start`: The date a task can be started.
- `scheduled`: The date a task is scheduled to work on.

### Accessing Implicit Fields in Queries

If you're using a [TASK](../queries/query-types.md#task) Query, your tasks are the top level information and can be used without any prefix:

~~~markdown
```dataview
TASK
WHERE !fullyCompleted
```
~~~

For every other Query type, you first need to access the implicit field `file.lists` or `file.tasks` to check for these list item specific implicit fields:

~~~markdown
```dataview
LIST
WHERE any(file.tasks, (t) => !t.fullyCompleted)
```
~~~

This will give you back all the file links that have unfinished tasks inside. We get back a list of tasks on page level and thus need to use a [list function](../reference/functions.md) to look at each element.


================================================
FILE: docs/docs/annotation/types-of-metadata.md
================================================
# Field Types

All fields in dataview have a **type**, which determines how dataview will render, sort, and operate on that field.
Read more about how to create fields on ["Adding metadata"](add-metadata.md) and which information you have automatically available on [metadata on pages](./metadata-pages.md) and [metadata on tasks and lists](./metadata-tasks.md).

## Why does the type matter?

Dataview provides [functions](../reference/functions.md) you can use to modify your metadata and allows you to write all sorts of complex queries. Specific functions need specific data types to work correctly. That means the data type of your field determines which functions you can use on these fields and how the functions behave. Furthermore, depending on the type, the output dataview renders can be different.

Most of the time you do not need to worry too much about the type of your fields, but if you want to perform calculations and other magical operations on your data, you should be aware of them.

!!! example "Different rendering based on type"
    If you have this file:
    ~~~yaml
    date1:: 2021-02-26T15:15
    date2:: 2021-04-17 18:00

    ```dataview
    TABLE date1, date2
    WHERE file = this.file
    ```
    ~~~

    You'll see the following output (depending on your Date + Time Format Setting for dataview): 

    | File (1) | date1 | date2 |
    | -------- | ----- | ----- |
    | Untitled 2 | 3:15 PM - February 26, 2021 | 2021-04-17 18:00 |

    `date1` is recognized as a **Date** while `date2` is a normal **Text** to dataview, that's why `date1` is parsed differently for you. Find out more on [Dates below](#date). 

## Available Field Types

Dataview knows several field types to cover common use cases.

### Text

The default catch-all. If a field doesn't match a more specific type, it is plain text.

```markdown
Example:: This is some normal text.
```

!!! hint "Multiline text"
    Multiline text as a value is only possible via YAML Frontmatter and the pipe operator:
    ```yaml
    ---
    poem: |
      Because I could not stop for Death,
      He kindly stopped for me;
      The carriage held but just ourselves
      And Immortality.
    author: "[[Emily Dickinson]]"
    title: "Because I could not stop for Death"
    ---
    ```
    For inline fields, a line break means the end of the value. 

### Number

Numbers like '6' and '3.6'.
```markdown
Example:: 6
Example:: 2.4
Example:: -80
```

In YAML Frontmatter, you write a number without surrounding quotes: 

```yaml
---
rating: 8
description: "A nice little horror movie"
---
```

### Boolean

Boolean only knows two values: true or false, as the programming concept.

```markdown
Example:: true
Example:: false
```

### Date

Text that matches the ISO8601 notation will be automatically transformed into a date object. [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) follows the format `YYYY-MM[-DDTHH:mm:ss.nnn+ZZ]`. Everything after the month is optional.
    
```markdown
Example:: 2021-04 
Example:: 2021-04-18
Example:: 2021-04-18T04:19:35.000
Example:: 2021-04-18T04:19:35.000+06:30
```

When querying for these dates, you can access properties that give you a certain portion of your date back:

- field.year
- field.month
- field.weekyear
- field.week
- field.weekday
- field.day
- field.hour
- field.minute
- field.second
- field.millisecond

For example, if you're interested in which month your date lies, you can access it via `datefield.month`:

~~~markdown
birthday:: 2001-06-11

```dataview
LIST birthday
WHERE birthday.month = date(now).month
```
~~~

gives you back all birthdays happening this month. Curious about `date(now)`? Read more about it under [literals](../reference/literals.md#dates).

!!! info "Displaying of date objects"
    Dataview renders date objects in a human readable format, i.e. `3:15 PM - February 26, 2021`. You can adjust how this format looks like in Dataview's Setting under "General" with "Date Format" and "Date + Time Format". If you want to adjust the format in a specific query only, use the [dateformat function](../reference/functions.md#dateformatdatedatetime-string).

### Duration

Durations are text of the form `<time> <unit>`, like `6 hours` or `4 minutes`. Common English abbreviations like
  `6hrs` or `2m` are accepted. You can specify multiple units in one field, i.e. `6hr 4min`, optionally with comma separator: `6 hours, 4 minutes`

```markdown
Example:: 7 hours
Example:: 16days
Example:: 4min
Example:: 6hr7min
Example:: 9 years, 8 months, 4 days, 16 hours, 2 minutes
Example:: 9 yrs 8 min
```

Find the complete list of values that are recognized as a duration on [literals](../reference/literals.md#durations). 

!!! hint "Calculations with dates and durations"
    Date and Duration types are compatible with each other. This means you can, for example, add durations to a date to produce a new date:
    ~~~markdown
    departure:: 2022-10-07T15:15
    length of travel:: 1 day, 3 hours

    **Arrival**: `= this.departure + this.length-of-travel`
    ~~~

    and you get back a duration when calculating with dates:
    ~~~markdown
    release-date:: 2023-02-14T12:00
      
    `= this.release-date - date(now)` until release!!
    ~~~

    Curious about `date(now)`? Read more about it under [literals](../reference/literals.md#dates).

### Link

Obsidian links like `[[Page]]` or `[[Page|Page Display]]`.

```markdown
Example:: [[A Page]]
Example:: [[Some Other Page|Render Text]]
```

!!! info "Links in YAML Frontmatter"
    If you reference a link in frontmatter, you need to quote it, as so: `key: "[[Link]]"`. This is default Obsidian-supported behavior. Unquoted links lead to a invalid YAML frontmatter that cannot be parsed anymore. 
    ```yaml
    ---
    parent: "[[parentPage]]"
    ---
    ```
    Please be aware that this is only a link for dataview, but not for Obsidian anymore - that means it won't show up in the outgoing links, won't be displayed on graph view and won't be updated on i.e. a rename.

### List

Lists are multi-value fields. In YAML, these are defined as normal YAML lists: 
```yaml
---
key3: [one, two, three]
key4:
 - four
 - five
 - six
---
```

In inline fields, they are comma-separated lists values:

```markdown
Example1:: 1, 2, 3
Example2:: "yes", "or", "no"
```

Please be aware that in Inline fields, you need to wrap **text values into quotes** to be recognized as a list (see `Example2`). `yes, or, no` is recognized as plain text.

!!! info "Duplicated metadata keys in the same file lead to lists"
    If you're using a metadata key twice or more in the same note, dataview will collect all values and give you a list. For example
    ~~~markdown
    grocery:: flour
    [...]
    grocery:: soap

    ```dataview
    LIST grocery
    WHERE file = this.file
    ```
    ~~~
    will give you a **list** out of `flour` and `soap` back.

!!! hint "Arrays are lists"
    In some places of this documentation, you'll read the term "array". Array is the term for lists in Javascript - Lists and Arrays are the same. A function that needs an array as argument needs a list as argument.

### Object

Objects are a map of multiple fields under one parent field. These can only be defined in YAML frontmatter, using the YAML object syntax:
```yaml
---
obj:
  key1: "Val"
  key2: 3
  key3: 
    - "List1"
    - "List2"
    - "List3"
---
```

  In queries, you can then access these child values via `obj.key1` etc:

~~~markdown
```dataview
TABLE obj.key1, obj.key2, obj.key3
WHERE file = this.file
```
~~~


================================================
FILE: docs/docs/api/code-examples.md
================================================
# Codeblock Examples

## Grouped Books

Group your books by genre, then create a table for each sorted by rating via a straightforward usage of
the dataview rendering API:

```js
for (let group of dv.pages("#book").groupBy(p => p.genre)) {
	dv.header(3, group.key);
	dv.table(["Name", "Time Read", "Rating"],
		group.rows
			.sort(k => k.rating, 'desc')
			.map(k => [k.file.link, k["time-read"], k.rating]))
}
```

![Grouped Books Example](../assets/grouped-book-example.png)

## Find All Direct And Indirectly Linked Pages

Use a simple set + stack depth first search to find all notes linked to the current note, or a note of your choosing:

```js
let page = dv.current().file.path;
let pages = new Set();

let stack = [page];
while (stack.length > 0) {
	let elem = stack.pop();
	let meta = dv.page(elem);
	if (!meta) continue;

	for (let inlink of meta.file.inlinks.concat(meta.file.outlinks).array()) {
		console.log(inlink);
		if (pages.has(inlink.path)) continue;
		pages.add(inlink.path);
		stack.push(inlink.path);
	}
}

// Data is now the file metadata for every page that directly OR indirectly links to the current page.
let data = dv.array(Array.from(pages)).map(p => dv.page(p));
```


================================================
FILE: docs/docs/api/code-reference.md
================================================
# Codeblock Reference

Dataview JavaScript Codeblocks are created using the `dataviewjs` language specification for a codeblock:

~~~
```dataviewjs
dv.table([], ...)
```
~~~

The API is available through the implicitly provided `dv` (or `dataview`) variable, through which you can query for
information, render HTML, and configure the view.

Asynchronous API calls are marked with `⌛`.

## Query
Query methods allow you to query the Dataview index for page metadata; to render this data, use the methods in the [render section](#render).

### `dv.current()`

Get page information (via `dv.page()`) for the page the script is currently executing on.

### `dv.pages(source)`

Take a single string argument, `source`, which is the same form as a [query language source](../reference/sources.md).
Return a [data array](data-array.md) of page objects, which are plain objects with all of the page fields as
values.

```js
dv.pages() => all pages in your vault
dv.pages("#books") => all pages with tag 'books'
dv.pages('"folder"') => all pages from folder "folder"
dv.pages("#yes or -#no") => all pages with tag #yes, or which DON'T have tag #no
dv.pages('"folder" or #tag') => all pages with tag #tag, or from folder "folder"
```

Note that folders need to be double-quoted inside the string (i.e., `dv.pages("folder")` does not work, but
`dv.pages('"folder"')` does) - this is to exactly match how sources are written in the query language.

### `dv.pagePaths(source)`

As with `dv.pages`, but just returns a [data array](data-array.md) of paths of pages that match the given source.

```js
dv.pagePaths("#books") => the paths of pages with tag 'books'
```

### `dv.page(path)`

Map a simple path or link to the full page object, which includes all of the pages fields. Automatically does link resolution,
and will figure out the extension automatically if not present.

```js
dv.page("Index") => The page object for /Index
dv.page("books/The Raisin.md") => The page object for /books/The Raisin.md
```

## Render

### `dv.el(element, text)`

Render arbitrary text in the given html element.
```js
dv.el("b", "This is some bold text");
```

You can specify custom classes to add to the element via `cls`, and additional attributes via `attr`:

```js
dv.el("b", "This is some text", { cls: "dataview dataview-class", attr: { alt: "Nice!" } });
```

### `dv.header(level, text)`

Render a header of level 1 - 6 with the given text.

```js
dv.header(1, "Big!");
dv.header(6, "Tiny");
```

### `dv.paragraph(text)`

Render arbitrary text in a paragraph.

```js
dv.paragraph("This is some text");
```

### `dv.span(text)`

Render arbitrary text in a span (no padding above/below, unlike a paragraph).

```js
dv.span("This is some text");
```

### `dv.execute(source)`

Execute an arbitrary dataview query and embed the view into the current page.

```js
dv.execute("LIST FROM #tag");
dv.execute("TABLE field1, field2 FROM #thing");
```

### `dv.executeJs(source)`

Execute an arbitrary DataviewJS query and embed the view into the current page.

```js
dv.executeJs("dv.list([1, 2, 3])");
```

### `dv.view(path, input)`

Complex function which allows for custom views. Will attempt to load a JavaScript file at the given path, passing it
`dv` and `input` and allowing it to execute. This allows for you to re-use custom view code across multiple pages. Note
that this is an asynchronous function since it involves file I/O - make sure to `await` the result!


```js
await dv.view("views/custom", { arg1: ..., arg2: ... });
```

If you want to also include custom CSS in your view, you can instead pass a path to a folder containing `view.js` and
`view.css`; the CSS will be added to the view automatically:

```
views/custom
 -> view.js
 -> view.css
```

View scripts have access to the `dv` object (the API object), and an `input` object which is exactly whatever the second
argument of `dv.view()` was.

Bear in mind, `dv.view()` cannot read from directories starting with a dot, like `.views`. Example of an incorrect usage:

```js
await dv.view(".views/view1", { arg1: 'a', arg2: 'b' });
```
Attempting this will yield the following exception:

```
Dataview: custom view not found for '.views/view1/view.js' or '.views/view1.js'.
```

Also note, directory paths always originate from the vault root.

#### Example
In this example, we have a custom script file named `view1.js` in the `scripts` directory. 

**File:** `scripts/view1.js`
```js
console.log(`Loading view1`);

function foo(...args) {
  console.log('foo is called with args', ...args);
}
foo(input)
```

And we have an Obsidian document located under `projects`. We'll call `dv.view()` from this document using the `scripts/view1.js` path.

**Document:** `projects/customViews.md`
```js
await dv.view("scripts/view1", { arg1: 'a', arg2: 'b' }) 
```

When the above script is executed, it will print the following:

```
Loading view1
foo is called with args {arg1: 'a', arg2: 'b'}
```

## Dataviews

### `dv.list(elements)`

Render a dataview list of elements; accept both vanilla arrays and data arrays.

```js
dv.list([1, 2, 3]) => list of 1, 2, 3
dv.list(dv.pages().file.name) => list of all file names
dv.list(dv.pages().file.link) => list of all file links
dv.list(dv.pages("#book").where(p => p.rating > 7)) => list of all books with rating greater than 7
```

### `dv.taskList(tasks, groupByFile)`

Render a dataview list of `Task` objects, as obtained by `page.file.tasks`. By default, this view will automatically
group the tasks by their origin file. If you provide `false` as a second argument explicitly, it will instead render them
as a single unified list.

```js
// List all tasks from pages marked '#project'
dv.taskList(dv.pages("#project").file.tasks)

// List all *uncompleted* tasks from pages marked #project
dv.taskList(dv.pages("#project").file.tasks
    .where(t => !t.completed))

// List all tasks tagged with '#tag' from pages marked #project
dv.taskList(dv.pages("#project").file.tasks
    .where(t => t.text.includes("#tag")))

// List all tasks from pages marked '#project', without grouping.
dv.taskList(dv.pages("#project").file.tasks, false)
```

### `dv.table(headers, elements)`

Renders a dataview table. `headers` is an array of column headers. `elements` is an array of rows. Each row is itself an array of columns. Inside a row, every column which is an array will be rendered with bullet points.

```js
dv.table(
	["Col1", "Col2", "Col3"],
		[
			["Row1", "Dummy", "Dummy"],
			["Row2", 
				["Bullet1",
				 "Bullet2",
				 "Bullet3"],
			 "Dummy"],
			["Row3", "Dummy", "Dummy"]
		]
	);
```

An example of how to render a simple table of book info sorted by rating.

```js
dv.table(["File", "Genre", "Time Read", "Rating"], dv.pages("#book")
    .sort(b => b.rating)
    .map(b => [b.file.link, b.genre, b["time-read"], b.rating]))
```

## Markdown Dataviews

Functions which render to plain Markdown strings which you can then render or manipulate as desired.

### `dv.markdownTable(headers, values)`

Equivalent to `dv.table()`, which renders a table with the given list of headers and 2D array of elements, but
returns plain Markdown.

```js
// Render a simple table of book info sorted by rating.
const table = dv.markdownTable(["File", "Genre", "Time Read", "Rating"], dv.pages("#book")
    .sort(b => b.rating)
    .map(b => [b.file.link, b.genre, b["time-read"], b.rating]))

dv.paragraph(table);
```

### `dv.markdownList(values)`

Equivalent to `dv.list()`, which renders a list of the given elements, but returns plain Markdown.

```js
const markdown = dv.markdownList([1, 2, 3]);
dv.paragraph(markdown);
```

### `dv.markdownTaskList(tasks)`

Equivalent to `dv.taskList()`, which renders a task list, but returns plain Markdown.

```js
const markdown = dv.markdownTaskList(dv.pages("#project").file.tasks);
dv.paragraph(markdown);
```
 
## Utility

### `dv.array(value)`

Convert a given value or array into a Dataview [data array](data-array.md). If the value is already a data array, returns
it unchanged.

```js
dv.array([1, 2, 3]) => dataview data array [1, 2, 3]
```

### `dv.isArray(value)`

Returns true if the given value is an array or dataview array.

```js
dv.isArray(dv.array([1, 2, 3])) => true
dv.isArray([1, 2, 3]) => true
dv.isArray({ x: 1 }) => false
```

### `dv.fileLink(path, [embed?], [display-name])`

Converts a textual path into a Dataview `Link` object; you can optionally also specify if the link is embedded as well
as it's display name.

```js
dv.fileLink("2021-08-08") => link to file named "2021-08-08"
dv.fileLink("book/The Raisin", true) => embed link to "The Raisin"
dv.fileLink("Test", false, "Test File") => link to file "Test" with display name "Test File"
```

### `dv.sectionLink(path, section, [embed?], [display?])`

Converts a textual path + section name into a Dataview `Link` object; you can optionally also specify if the link is embedded and
it's display name.

```js
dv.sectionLink("Index", "Books") => [[Index#Books]]
dv.sectionLink("Index", "Books", false, "My Books") => [[Index#Books|My Books]]
```

### `dv.blockLink(path, blockId, [embed?], [display?])`

Converts a textual path + block ID into a Dataview `Link` object; you
can optionally also specify if the link is embedded and it's display name.

```js
dv.blockLink("Notes", "12gdhjg3") => [[Index#^12gdhjg3]]
```

### `dv.date(text)`

Coerce text and links to luxon `DateTime`; if provided with a `DateTime`, return it unchanged.

```js
dv.date("2021-08-08") => DateTime for August 8th, 2021
dv.date(dv.fileLink("2021-08-07")) => dateTime for August 8th, 2021
```

### `dv.duration(text)`

Coerce text to a luxon `Duration`; uses the same parsing rules as Dataview duration types.

```js
dv.duration("8 minutes") => Duration { 8 minutes }
dv.duration("9 hours, 2 minutes, 3 seconds") => Duration { 9 hours, 2 minutes, 3 seconds }
```

### `dv.compare(a, b)`

Compare two arbitrary JavaScript values according to dataview's default comparison rules; useful if you are writing a
custom comparator and want to fall back to the default behavior. Returns a negative value if `a < b`, 0 if `a = b`, and
a positive value if `a > b`.

```js
dv.compare(1, 2) = -1
dv.compare("yes", "no") = 1
dv.compare({ what: 0 }, { what: 0 }) = 0
```

### `dv.equal(a, b)`

Compare two arbitrary JavaScript values and return true if they are equal according to Dataview's default comparison
rules.

```js
dv.equal(1, 2) = false
dv.equal(1, 1) = true
```

### `dv.clone(value)`

Deep clone any Dataview value, including dates, arrays, and links.

```js
dv.clone(1) = 1
dv.clone({ a: 1 }) = { a: 1 }
```

### `dv.parse(value)`

Parse an arbitrary string object into a complex Dataview type
(mainly supporting links, dates, and durations).

```js
dv.parse("[[A]]") = Link { path: A }
dv.parse("2020-08-14") = DateTime { 2020-08-14 }
dv.parse("9 seconds") = Duration { 9 seconds }
```

## File I/O

These utility methods are all contained in the `dv.io` sub-API, and are all *asynchronous* (marked by ⌛).

### ⌛ `dv.io.csv(path, [origin-file])`

Load a CSV from the given path (a link or string). Relative paths will be resolved relative to the optional origin file (defaulting to the current file if not provided). Return a dataview array, each element containing an object of the CSV values; if the file does not exist, return `undefined`.

```js
await dv.io.csv("hello.csv") => [{ column1: ..., column2: ...}, ...]
```

### ⌛ `dv.io.load(path, [origin-file])`

Load the contents of the given path (a link or string) asynchronously. Relative paths will be resolved relative to the
optional origin file (defaulting to the current file if not provided). Returns the string contents of the file, or
`undefined` if the file does not exist.

```js
await dv.io.load("File") => "# File\nThis is an example file..."
```

### `dv.io.normalize(path, [origin-file])`

Convert a relative link or path into an absolute path. If `origin-file` is provided, then the resolution is doing as if
you were resolving the link from that file; if not, the path is resolved relative to the current file.

```js
dv.io.normalize("Test") => "dataview/test/Test.md", if inside "dataview/test"
dv.io.normalize("Test", "dataview/test2/Index.md") => "dataview/test2/Test.md", irrespective of the current file
```

## Query Evaluation

### ⌛ `dv.query(source, [file, settings])`

Execute a Dataview query and return the results as a structured return.
The return type of this function varies by the query type being executed,
though will always be an object with a `type` denoting the return type. This version of `query` returns a result type - you may want `tryQuery`, which instead throws an error on failed query execution.

```javascript
await dv.query("LIST FROM #tag") =>
    { successful: true, value: { type: "list", values: [value1, value2, ...] } }

await dv.query(`TABLE WITHOUT ID file.name, value FROM "path"`) =>
    { successful: true, value: { type: "table", headers: ["file.name", "value"], values: [["A", 1], ["B", 2]] } }

await dv.query("TASK WHERE due") =>
    { successful: true, value: { type: "task", values: [task1, task2, ...] } }
```

`dv.query` accepts two additional, optional arguments:
1. `file`: The file path to resolve the query from (in case of references to `this`). Defaults to the current file.
2. `settings`: Execution settings for running the query. This is largely an advanced use case (where I recommend you
   directly check the API implementation to see all available options).

### ⌛ `dv.tryQuery(source, [file, settings])`

Exactly the same as `dv.query`, but more convenient in short scripts as
execution failures will be raised as JavaScript exceptions instead of a
result type.

### ⌛ `dv.queryMarkdown(source, [file], [settings])`

Equivalent to `dv.query()`, but returns rendered Markdown.

```js
await dv.queryMarkdown("LIST FROM #tag") =>
    { successful: true, value: { "- [[Page 1]]\n- [[Page 2]]" } }
```

### ⌛ `dv.tryQueryMarkdown(source, [file], [settings])`

Exactly the same as `dv.queryMarkdown()`, but throws an error on parse failure.

### `dv.tryEvaluate(expression, [context])`

Evaluate an arbitrary dataview expression (like `2 + 2` or `link("text")` or `x * 9`); throws an `Error` on parse or
evaluation failure. `this` is an always-available implicit variable which refers to the current file.

```js
dv.tryEvaluate("2 + 2") => 4
dv.tryEvaluate("x + 2", {x: 3}) => 5
dv.tryEvaluate("length(this.file.tasks)") => number of tasks in the current file
```

### `dv.evaluate(expression, [context])`

Evaluate an arbitrary dataview expression (like `2 + 2` or `link("text")` or `x * 9`), returning a `Result` object of
the result. You can unwrap the result type by checking `result.successful` (and then fetching either `result.value`
or `result.error`). If you want a simpler API that throws an error on a failed evaluation, use `dv.tryEvaluate`.

```js
dv.evaluate("2 + 2") => Successful { value: 4 }
dv.evaluate("2 +") => Failure { error: "Failed to parse ... " }
```


================================================
FILE: docs/docs/api/data-array.md
================================================
# Data Arrays

The general representation of result lists in Dataview is the `DataArray`, which is a [proxied](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) version of the JavaScript array with expanded
functionality. Data arrays support indexing and iteration (via `for` and `for ... of` loops), like normal arrays do, but
also include many data manipulation operators like `sort`, `groupBy`, `distinct`, `where`, and so on to make
manipulating tabular data easier.

## Creation

Data arrays are returned by most Dataview APIs that can return multiple results, such as `dv.pages()`. You can also
explicitly convert a normal JavaScript array into a Dataview array using `dv.array(<array>)`. If you want to convert a
Data array back to a normal array, use `DataArray#array()`.

## Indexing and Swizzling

Data arrays support regular indexing just like normal arrays (like `array[0]`), but importantly, they also support
query-language-style "swizzling": if you index into a data array with a field name (like `array.field`), it
automatically maps every element in the array to `field`, flattening `field` if it itself is also an array.

For example, `dv.pages().file.name` will return a data array of all file names in your vault;
`dv.pages("#books").genres` will return a flattened list of all genres in your books.

## Raw Interface

The full interface for the data array implementation is provided below for reference:

```ts
/** A function which maps an array element to some value. */
export type ArrayFunc<T, O> = (elem: T, index: number, arr: T[]) => O;

/** A function which compares two types. */
export type ArrayComparator<T> = (a: T, b: T) => number;

/**
 * Proxied interface which allows manipulating array-based data. All functions on a data array produce a NEW array
 * (i.e., the arrays are immutable).
 */
export interface DataArray<T> {
    /** The total number of elements in the array. */
    length: number;

    /** Filter the data array down to just elements which match the given predicate. */
    where(predicate: ArrayFunc<T, boolean>): DataArray<T>;
    /** Alias for 'where' for people who want array semantics. */
    filter(predicate: ArrayFunc<T, boolean>): DataArray<T>;

    /** Map elements in the data array by applying a function to each. */
    map<U>(f: ArrayFunc<T, U>): DataArray<U>;
    /** Map elements in the data array by applying a function to each, then flatten the results to produce a new array. */
    flatMap<U>(f: ArrayFunc<T, U[]>): DataArray<U>;
    /** Mutably change each value in the array, returning the same array which you can further chain off of. */
    mutate(f: ArrayFunc<T, any>): DataArray<any>;

    /** Limit the total number of entries in the array to the given value. */
    limit(count: number): DataArray<T>;
    /**
     * Take a slice of the array. If `start` is undefined, it is assumed to be 0; if `end` is undefined, it is assumed
     * to be the end of the array.
     */
    slice(start?: number, end?: number): DataArray<T>;
    /** Concatenate the values in this data array with those of another iterable / data array / array. */
    concat(other: Iterable<T>): DataArray<T>;

    /** Return the first index of the given (optionally starting the search) */
    indexOf(element: T, fromIndex?: number): number;
    /** Return the first element that satisfies the given predicate. */
    find(pred: ArrayFunc<T, boolean>): T | undefined;
    /** Find the index of the first element that satisfies the given predicate. Returns -1 if nothing was found. */
    findIndex(pred: ArrayFunc<T, boolean>, fromIndex?: number): number;
    /** Returns true if the array contains the given element, and false otherwise. */
    includes(element: T): boolean;

    /**
     * Return a string obtained by converting each element in the array to a string, and joining it with the
     * given separator (which defaults to ', ').
     */
    join(sep?: string): string;

    /**
     * Return a sorted array sorted by the given key; an optional comparator can be provided, which will
     * be used to compare the keys in lieu of the default dataview comparator.
     */
    sort<U>(key: ArrayFunc<T, U>, direction?: "asc" | "desc", comparator?: ArrayComparator<U>): DataArray<T>;

    /**
     * Return an array where elements are grouped by the given key; the resulting array will have objects of the form
     * { key: <key value>, rows: DataArray }.
     */
    groupBy<U>(key: ArrayFunc<T, U>, comparator?: ArrayComparator<U>): DataArray<{ key: U; rows: DataArray<T> }>;

    /**
     * Return distinct entries. If a key is provided, then rows with distinct keys are returned.
     */
    distinct<U>(key?: ArrayFunc<T, U>, comparator?: ArrayComparator<U>): DataArray<T>;

    /** Return true if the predicate is true for all values. */
    every(f: ArrayFunc<T, boolean>): boolean;
    /** Return true if the predicate is true for at least one value. */
    some(f: ArrayFunc<T, boolean>): boolean;
    /** Return true if the predicate is FALSE for all values. */
    none(f: ArrayFunc<T, boolean>): boolean;

    /** Return the first element in the data array. Returns undefined if the array is empty. */
    first(): T;
    /** Return the last element in the data array. Returns undefined if the array is empty. */
    last(): T;

    /** Map every element in this data array to the given key, and then flatten it.*/
    to(key: string): DataArray<any>;
    /**
     * Recursively expand the given key, flattening a tree structure based on the key into a flat array. Useful for handling
     * hierarchical data like tasks with 'subtasks'.
     */
    expand(key: string): DataArray<any>;

    /** Run a lambda on each element in the array. */
    forEach(f: ArrayFunc<T, void>): void;

    /** Calculate the sum of the elements in the array. */
    sum(): number;

    /** Calculate the average of the elements in the array. */
    avg(): number;

    /** Calculate the minimum of the elements in the array. */
    min(): number;

    /** Calculate the maximum of the elements in the array. */
    max(): number;

    /** Convert this to a plain javascript array. */
    array(): T[];

    /** Allow iterating directly over the array. */
    [Symbol.iterator](): Iterator<T>;

    /** Map indexes to values. */
    [index: number]: any;
    /** Automatic flattening of fields. Equivalent to implicitly calling `array.to("field")` */
    [field: string]: any;
}
```


================================================
FILE: docs/docs/api/intro.md
================================================
# Overview

The Dataview JavaScript API allows for executing arbitrary JavaScript with access to the dataview indices and query
engine, which is good for complex views or interop with other plugins. The API comes in two flavors: plugin facing, and
user facing (or 'inline API usage').

## Inline Access

You can create a "DataviewJS" block via:

~~~
```dataviewjs
dv.pages("#thing")...
```
~~~

Code executed in such codeblocks have access to the `dv` variable, which provides the entirety of the codeblock-relevant
dataview API (like `dv.table()`, `dv.pages()`, and so on). For more information, check out the [codeblock API
reference](code-reference.md).

## Plugin Access

You can access the Dataview Plugin API (from other plugins or the console) through `app.plugins.plugins.dataview.api`;
this API is similar to the codeblock reference, with slightly different arguments due to the lack of an implicit file
to execute the queries in. For more information, check out the [Plugin API reference](code-reference.md).


================================================
FILE: docs/docs/changelog.md
================================================
# 0.5.70 (Beta)

Still attempting to fix #2557, github is acting up.


---

# 0.5.69 (Beta)

Attempting to fix #2557, but uncertain to any side effects.


---

# 0.5.68

- Many fixes to the documentation
- #2318 & co: Various fixes related to _live preview_ rendering of lists
- New/documented functions for `unique()`, `display()`, `firstvalue()`
- Added DOM information related to standalone inline fields

This is the first release done by @holroy, so thanks to him for further developing of _Dataview_. Thank you also to all the people having contributed through PRs and issues.

---

# 0.5.67

Includes several documentation fixes and several community-contributed bug fixes.

- @reply2za: Fixed inline rendering in the reading view.
- @carlesalbasboix: Adds sum(), avg(), min(), and max() to data arrays.
- @mnaoumov: Adds code mirror configuration which code highlights dataviewjs!

---

# 0.5.66

Bugfix for version comparisons to fix some other plugins having broken interactions with Dataview.

---

# 0.5.65

A maintenance update which fixes some issues with rendering embeds in Dataviews and adds a few new functions.

- Adds the `hash()` function for generating consistent uniformly-distributed values given arbitrary inputs. Primarily useful for creating "random" views which remain consistent across page refreshes. Thanks to @holroy.
- Adds the `slice()` function for slicing arrays, similar to Javascript's `Array.slice`. Thanks to @holroy.
- Fixes several issues with rendering embeds inside dataviews. Thanks to @GottZ.
- Several documentation improvements around tasks - thanks to @holroy and @RaviOnline.

---

# 0.5.64

More bug fixes for inline field rendering.


---

# 0.5.63

- More bugfixes from @RyotaUshio for rendering Markdown paragraphs and other blocks in DataviewJS.

---

# 0.5.62

Several more inline field fixes from @RyotaUshio, including more configuration options, fixing inline fields being rendered inside codeblocks, and more. Thanks!

---

# 0.5.61

- @RyotaUshio: Fix several bugs related to the new inline field rendering, including source mode and fixing date formatting.

---

# 0.5.60

- @RyotaUshio: Add explicit rendering of inline fields in live preview. They are much more visually distinct now!
- @MarioRicalde: Adds `PluginApi#evaluateInline(expression, path)` to the plugin API, which evaluate expressions as if you were on the given page.

---

# 0.5.59

- Fix an issue with the plugin failing to run on iOS due to an esoteric regex issue.

---

# 0.5.58

- Negative durations will now be properly rendered.

---

# 0.5.57

Maintenance patch which bumps many internal dependency versions and which includes approximately ~20 community-contributed PRs which add some new functions, fix some Dataview interactions with properties, and more!

---

# Unreleased

- DQL: Adds new `durationformat(duration, string)` function.
- DQL: New math rounding functions, `trunc(number)`, `floor(number)`, `ceil(number)`.

# 0.5.56

- Includes some performance fixes on recent versions of Obsidian 1.3+ due to some API changes. Thanks @kometenstaub.
- Documentation cleanups and improvements by @mocsa, @protofarer, @seanlzx, and @somidad.
- Adds the new `flat(array)` method for flattening nested arrays, as well as parsing dates using arbitrary formats using
  `date(text, "format")`. Thanks @holroy!

---

# 0.5.55

- Durations are now internationalized using luxon's new internationalization support.
- Dataviews should now properly render inside Canvas and some other contexts. Thanks @GamerGirlandCo!

---

# 0.5.54

- Regular list items are now also clickable in task views, not just task lines! Thanks to @LilaRest.

---

# 0.5.53

- Fix some documentation issues causing docs to not be updated.

---

# 0.5.52

Substantial documentation improvements thanks to @s-blu and @AB1908!

- For people concerned about dataviewjs code execution from copy-pasting, @eyuelt has made it possible to change the
  dataviewjs codeblock prefix.
- @sohanglal has added some documentation for `task.visual` for changing the visual text of a task.
- @Chouffy and @Daryl-Horton have fixed some bad documentation links!
- @vrtmrz swapped the regex used for parsing tags to better match Obsidian's own parser.
- @alexfertel has added `regextest`, which allows for matching parts of a string instead of the whole thing.
- @iamrecursion has added more metadata to file links, so they now include section metadata. This may cause some slight
  visual changes in link views.

---

# 0.5.51 (Beta)

- Allow disabling regular Dataview inline queries via configuration option.

---

# 0.5.50 (Beta)

- Expose dataview EXPRESSION and QUERY parsing to the dataview npm plugin, so others can parse dataview ASTs.
- Fix documentation issue with `join`.

---

# 0.5.49 (Beta)

- Add the `average` function to compute averages of lists (`average([list of things])`).
- Added documentation for `average`, `min`, `max`, `minby`, and `maxby` functions.
- Fixed the broken `nonnull` function and documented it.

---

# 0.5.48 (Beta)

We're back to more regular beta releases while I trial out new functionality!

- Fixed broken list behavior for `dv.markdownTaskList`.
- @GamerGirlandCo: Better handling of block IDs when checking off tasks!
- @s-blu and @AB1908: Lots of big documentation upgrades! Nice!
- @leoccyao: More block ID task checking fixes. Should work after this one.
- Add expression/query parsing to the dataview NPM package.
- @charleshan: Fix a missing header level in the dataview `dv.header` example.

---

# 0.5.47

Improves `date + duration` behavior when either the date or duration are null.

---

# 0.5.46

- Fix #1412: Fix bad `file.cday` and `file.ctime` comparisons due to wrong timezone being set. Ugh.

---

# 0.5.45

- #1400: Properly use the group by field for the group name.
- Fix bad table highlighting in some themes.

---

# 0.5.44

- #1404: Fixed dates in non-local timezones parsing incorrectly.
- Fixed some build non-determinism issues.
- Swapped to pull requests for adding new functionality, and added some more internal tests.

---

# 0.5.43

- Fix #1366: Better handling of calendar emoji (used as due dates in tasks).

---

# 0.5.42

It's been over a month since the last release! Anyway, this release bundles several nice user-contributed features:

- @AB1908: Tag queries are now case insensitive.
- @AB1908: Shift-clicking a link/task to open in a new tab now works properly on Mac.
- @AB1908: Numerous documentation fixes for clarity and more examples.
- @AnnaKornfeldSimpson: Additional emoji shorthands for more task fields (finished, due).
- @ooker777: Documentation improvements for some DataviewJS functions, and the ability to use inline emoji for the
  completion tracking feature.
- @mt-krainski: Custom date formats for task completions.
- @gentlegiantJGC: Better support for nested inline fields (i.e., less crashy).

---

# 0.5.41

- Fix a bad regex doing escaping in markdown tables.
- Improve async documentation.

---

# 0.5.40

Adds some more documentation about the new markdown functionality.

---

# 0.5.39

- Fixed an issue where checking a task in a task view would check the wrong box visually.
- Added experimental plugin APIs for querying dataview directly as markdown, and converting dataview results to properly
  formatted markdown.

---

# 0.5.38

- Some minor documentation improvements.
- Fix an issue with inline fields rendering out of order. That was a weird bug.

---

# 0.5.37

Fixes inline field rendering to once again work for highlighting/links, as well as some other rendering quirks with
inline queries in codeblocks.

---

# 0.5.36

- Fix a bug when checking if an element is an HTMLElement.
- Properly include the nice improvements to the file count in tables and lists.

---

# 0.5.35

- Fix #1196, #1176: Re-enable HTML values. This was never a featured I advertised since it was just for some internal
  hackery, but it appears people just discovered it in DataviewJS queries.
- Improved initial time to popular queries that use `file.starred`.

---

# 0.5.34

- Fix #1174: Fix indexing with a variable.
- Fix an issue with the experimental calendar view.

---

# 0.5.33

- Fix a bug with inline views that was introduced in 0.5.32.

---

# 0.5.32

The Dataview API has been noticeably revamped - there are now approximately twice as many functions available on the
plugin API as there were before, and some additional utilities have been added to both the plugin and inline API. I
will be finishing up the associated new "extension" functionality shortly, which will allow:

1. For custom Dataview + DataviewJS functions to be added via plugins.
2. For custom renderable objects (progress bars, embedded task lists, embedded tables) to be added to any Dataview view via plugins.
3. For plugins to provide alternative behavior for some dataview functionality (such as integrating task plugins with
   the dataview task query).
   
As part of the API revamp, it is now possible to programmatically execute Dataview and DataviewJS queries - either for
using the existing Dataview query language in your own plugin, or for embedding dataview. The Dataview npm library also
now exposes many useful internal Dataview types, including the AST structure for all dataview queries.

I am hoping that cleaning up the Dataview API and making it much more extensible will allow for Dataview [to](to) integrate
much better with existing plugins, and to provide the full power of the in-memory index for plugins. I have been very
carefully watching index performance in recent weeks to ensure smooth frontend performance for anyone using the API
(with a goal of <10ms for most queries).

---

# 0.5.31

Tasks now have an `outlinks` list field which includes all links in the task; this can be used for finding tasks with
links in them.

---

# 0.5.30

- Added the `typeof(any)` function in Dataview, which obtains the type of any value for comparison:
```javascript
typeof("text") = "string"
typeof(1) = "number"
typeof([1, 2, 3]) = "array"
```

- Added the modulo operator (`%`) for doing integer division remainder. I.e., `14 % 2 = 0` and `14 % 3 = 2`.
- Fixed some minor spacing issues with lists in tables.

---

# 0.5.29

Fix another subtle incompatibility between 0.4.26 and 0.5.29 - if you frequently used empty inline fields (like
`Key::` with no value), the 0.5+ behavior is now the same as 0.4 behavior and will map such fields to null instead of an
empty string.

This may fix a broad variety of "subtly wrong" queries that you may have seen after the upgrade.

---

# 0.5.28

- Fix a bug with some more string concatenations and null handling.

---

# 0.5.27

More performance + correctness bugfixes.

- The parser has been made a little more robust to prevent major indexing issues (or at least recover from them
  quickly).
- Several new strange tag variants are now supported.
- Markdown links are now properly indexed again.

Some DataviewJS performance issues should be resolved now, especially for external plugins using Dataview. This fix
does involve a slight API break w.r.t. what types are wrapped into Dataview Arrays (which provide functions like
`.where()`). Generally, only Dataview-provided implicits are wrapped in data arrays now; frontmatter and inline fields
are always now regular JS arrays - use `dv.array()` to explicitly make a data array if you want the advanced querying.

---

# 0.5.26

More small bugfixes:

- Fix a few small link rendering issues.
- Tag extraction from tasks now handles punctuation properly.
- Upgrade luxon (which is embedded in DataviewJS) to 2.4.0.

---

# 0.5.25

- Fix #1147: Fix there being a `#null` tag for files with an empty `tag` or `tags` frontmatter.

---

# 0.5.24

Several bugfixes:

- Nulls are now sorted first rather than last; it's generally good practice to explicitly check for nulls in your
  queries to avoid strange behavior.
- Dataview now properly parses space-delimited tags (like `tags: abc def ghi`).
- Dataview now supports dropping the entire file cache in case of bugs.

---

# 0.5.23

- Fix #1140: Force API objects to be arrays if they are iterables.

---

# 0.5.22

- Fix #1135: Use 'x' instead of 'X' for checkboxes.

---

# 0.5.21

A long-overdue swap from the beta branch to the stable branch. The beta branch should not include any (intended) breaking
changes, and has some nice performance improvements that come along with it! Here are the major changes:

- Most views now use React and no longer flicker when updating; this is not the case yet for DataviewJS, which will be
  getting equivalent treatment in the future.
- Dataview now caches metadata, so Dataview loads are very fast after the first time you open your vault. Dataview still
  needs to visit every file when you update the plugin version, so that should be the only times you experience slower
  load times.
- A brand new task view backend and query which allows you to filter per-task, rather than per-page! Check the
  documentation for details, but this broadly means `WHERE` statements now use task properties instead of page
  properties.
- Some additional metadata is now available for use - `file.starred`, `file.lists`, and more metadata in
  `file.tasks`.

There have been some moderate documentation touch-ups to keep things up to date; I'm still working on a walkthrough for
common Dataview use cases. This review also includes about ~30-40 bugfixes; some new bugs may arise due to internal
changes, so please flag them if you encounter them.

---

# 0.5.20 (Beta)

Slight fix to hopefully improve some strange reported cases of bad indexing at startup.

---

# 0.5.19 (Beta)

Dataview now uses IndexedDB to cache file metadata, reducing startup time to virtually nothing if you've opened the
vault before; if you have a small vault (<1000 notes), you may notice a slight improvement, but large vaults and mobile
devices will notice a very significant performance improvement to "first valid paint". Some other performance parameters
have been tuned to hopefully make the default experience better.

A few small bugs related to rendering have also been squashed, including an issue with images being scaled wrongly.

---

# 0.5.18 (Beta)

- Tasks in task views now support alternative task status characters like '!' and '/'; thanks @ebullient.
- A few documentation nit fixes.
- Added `DataArray#sortInPlace` for a more efficient mutable sort for niche use cases.

---

# 0.5.17 (Beta)

- Improved behavior when clicking on tasks in the task view; will now properly scroll to the relevant line in long
  files!
- Fixed a bug with incorrect counts being displayed in task views.
- Added `tags` as a field available on task items, so you can now do things like `TASK WHERE contains(tags, "#tag")`.

---

# 0.5.16 (Beta)

Dataview now tracks initialization and will report when all files have been indexed in the console; you can
programmatically see this via `dataview:index-ready`, or by checking `api.index.initialized`.

---

# 0.5.15 (Beta)

- Add hover highlights to tables to make seeing rows a little easier.
- Tables and task lists now include counts of the number of results in the headers.
- Further improved task selection in the task view.

---

# 0.5.14 (Beta)

- Fix task highlighting when not grouping.
- Remove some spurious console logging.
- Slightly improve task highlighting behavior when clicking on a task.

---

# 0.5.13 (Beta)

Several smaller bugfixes!

- Fix #997: Use the group by field name in the table name.
- Prevent tons of errors if you incorrectly set the inline query prefix.

---

# 0.5.12 (Beta)

Improve error messages for queries somewhat and get rid of some ugly output.

---

# 0.5.11 (Beta)

Add detection of tasks inside of block quotes, as well as correctly implement automatic checking and unchecking of these
tasks.

---

# 0.5.10 (Beta)

Adds the `Dataview: Force Refresh Views` Command (accessible via the Ctrl+P command view) to force current views to
refresh immediately.

---

# 0.5.9 (Beta)

Another fix for due-date related emoji in tasks. I hate emoji.

---

# 0.5.8 (Beta)

Fix some issues with infinite loops of tasks due to bad Obsidian metadata (potentially due to being out of date?).

---

# 0.5.7 (Beta)

Fix issues with parsing '🗓️2021-08-29' due-date annotations on tasks, as well as an issue with properly extracting
due/completed/completed times for use in queries.

---

# 0.5.6 (Beta)

Proper release of 0.5.5 plus one additional small improvement:

- Add `duration * number` and `duration / number` operations for manipulation durations numerically.

---

# 0.5.5 (Beta)

More small features:

- Fix issues with task sorting not doing anything. Sort away!
- Table headers can now be arbitrary markdown. So you can put things like links in your headers: `TABLE (1 + 2) AS
  "[[File]]".
- You can now specify the size of an image embed by providing WxH in it's display property: `![[image.png|50x50]]`.

---

# 0.5.4 (Beta)

Improved image rendering for some link types, and adds the `embed(link)` and `embed(link, false)` options to convert
links to/from their embedded equivalents.

---

# 0.5.3 (Beta)

Iterative beta which adds a few nice QoL features and fixes some more bugs:

- Internally swapped to a React-based renderer; this should not have a noticeable perf or usability impact, but makes it
  easier for me to implement complex table/list behaviors.
- Naming your fields with `AS "Name"` is now optional; Dataview will infer the name from the expression automatically.
  For example, `TABLE 8 + 4, 3 + 6 FROM ...` is now a valid table expression, and the columns will be named `8 + 4` and
  `3 + 6` respectively.
- Some issues with array and object rendering were corrected.
- Error messages on empty dataview results were improved and now show up for all views.

Inline images are now rendered correctly in Dataview tables and lists - no more hacky `app://local/` shenanigans!

---

# 0.5.2 (Beta)

- Fix #971: Objects now work properly inside DataviewQL evaluation.

---

# 0.5.1 (Beta)

- Temporarily revert the new task metadata behavior: inline fields in sublists of tasks are added to the page, instead
  of the task. This behavior is not good, but is compatible with legacy usages of task metadata, which should not break
  some existing queries.
    - This behavior will be removed in the future behind a flag.
- Added the 'visual' field to tasks - if set, tasks render 'visual' instead of their regular text.
- Fixed `DataArray#mutate()`.

---

# 0.5.0 (Beta)

Re-release of broken release 0.4.23, now hopefully with fixes that make it work on (most) machines. I'll be doing beta
releases for a little while until I can confirm the new version is stable; use BRAT
(https://github.com/TfTHacker/obsidian42-brat) to easily track Dataview beta versions if you are interested in cutting
edge features.

---

# 0.4.25

Fix #867: Create a container div per taskList to allow for multiple task views.

---

# 0.4.24

Re-release of 0.4.23f since Obsidian does not automatically update between non-semver versions.

---

# 0.4.23f

Remove some code which attempted to make tag queries case-insensitive; I'll reimplement this more generally later (it
conflicts with existing queries which check tags via `contains(file.tags, "#Tag")` and similar).

---

# 0.4.23e

More task bugfixes / improvements, and a fix that caused task metadata to be duplicated.

---

# 0.4.23d

More inline field list parsing bug fixes. Hopefully we're back to a nice working order!

---

# 0.4.23c

Bugfix which adds support for '1)' style lists, as well as a very annoying null issue due to JavaScript being a very
sad, very sad language.

---

# 0.4.23b

Bugfix for bad inlink/outlink computations; links were not being normalized properly so reverse lookups were not
working.

---

# 0.4.23

The Task Update! This release reworks how dataview handles tasks and list items so that they should be much more
intuitive to use and interact with:

1. **Subtask Support**: Queries now search over all list items, instead of only over root elements. This should make
   task filtering much more usable, especially if you tend to put tasks under other list items or care specifically
   about subtasks.
2. **Multiline Support**: Dataview now understands multi-line tasks and renders/updates them correctly.
3. **Immediately Navigate to Task**: The new task view, aside from looking a little cleaner than previous views, now
   immediately navigates to the task in it's original file on click and selects it.
4. **Grouping Support**: For DataviewJS users, `dv.taskList` now supports grouping (as produced by `groupBy` and the new
   `groupIn`) natively.

For DataviewJS users, the task and list representation has changed: `file.tasks` (and the new `file.lists`) contain
every single task (including subtasks) in the file, instead of only the root elements. You can return to previous
behavior by filtering out tasks with a non-null parent - i.e., `file.tasks.where(task => !task.parent)`. `dv.taskList`
will intelligently deal with properly nesting and de-duplicating tasks, so just filter to the tasks you want to render and
the API will do the rest.

This release also includes general backend improvements as we prepare for live-editing in Dataview views, as well as
several community-contributed API improvements:

- `DataArray#groupIn`: For grouping already grouped data, you can now use `array.groupIn(v => ...)`, which will group
  the innermost (original) data in the array instead of the top level groups. This allows for more easily grouping
  recursively, such as `dv.pages().groupBy(page => page.file.folder).groupIn(page => page.title)` producing a grouping
  of folders, then page titles.
- `substring(string, start[, end])`: The last major missing string function is now available! Take slices of strings.
- Improved `dv.el()` and other HTML functions - thanks @vitaly.
- null and undefined entries sort at the end instead of the beginning by default; sorry to those whose code sorts wrong
  because of this, but it is a better default for most people's use cases.
- All links are now properly normalized to their full paths, fixing many link comparison edge cases in DataviewJS.

Documentation additions for the new task functionality will be coming out in the next few days. The next release 0.4.24
is currently targeting expanded `FROM` query support, basic table view improvements, and general exporting functionality
for Dataview. See you then!

---

# 0.4.22

The @pjeby update! This includes several performance improvements suggested by @pjeby to dramatically improve background
Dataview performance as well as reduce some memory pressure. It also includes some minor bug-fixes and preliminary
functionality:

- Target ES2018 for better Promise support
- Allow parsing shorthands in `dv.date()`.
- Add additional metadata to inline field rendering which can be styled.
- Cleanup events & workers on plugin uninstall, improving the Dataview uninstall/disable/reload experience.
- Add preliminary `CALENDAR` queries - rendering similar to the obsidian-calendar plugin, see the documentation!

Dataview should perform much better on startup and when you have lots of tabs open - thanks again to @pjeby.

---

# 0.4.21

Bugfix release which primarily fixes issues that Dataview had with the live preview mode in upcoming Obsidian versions;
Dataview live preview should now be functional. Also includes a number of smaller bugfixes.

- Fix #646: Add `date(yesterday)` to create a date 24 hours ago.
- Fix #618: Luxon is now available on the dataview API (`dv.luxon`).
- Fix #510: Add `dv.duration()` for parsing durations.
- Fix #647: All HTML functions in the DataviewJS API now return their rendered objects.
- Fix #652: Fix parsing of invalid dates.
- Fix #629: Fix block link parsing.
- Fix #601: Timezones are now rendered properly and parsed properly in Dataview dates.
- PR #637: Add `meta(link)` which allows you to access various metadata about a link itself.
- Various minor null safety fixes.
- Dataview now reports it's exact version and build time in logs.

---

# 0.4.20

Some feature work (mostly by other contributors) while I while away at section metadata. May also fix a few bugs!

- Fix #448: You can now use the "Task Completion Tracking" option to automatically add completion metadata to tasks
  which are checked/unchecked through Dataview. Thanks to @sheeley.
- Add a search bar to documentation. Thanks to @tzhou.
- Add new date expressions for the start of the week (`date(sow)`), and the end of the week (`date(eow)`). Thanks
  @Jeamee and @v_mujunma.

Small minor bugfix / security releases may follow in the near future; otherwise, the next major release will include
section and object metadata.

---

# 0.4.19

Bugfix release which corrects emoji parsing & localization issues.

- Add `DataArray#into`, which lets you index into objects without flattening.
- Renamed 'header' to 'section' in task metadata; 'header' will remain around for a few major releases to let people
  naturally migrate.
- Fix #487: You no longer need spaces around '*' in expressions.
- Fix #559: Fix unicode issues in variable canonicalization which was causing problems with non-Latin inline field
  keys.

## Duration Parsing

You can now include multiple units in durations: `dur(8 minutes, 4 seconds)` or `dur(2yr8mo12d)`. You can separate
durations by commas, or use the abbreviated syntax with/without spaces.

---

# 0.4.18

Bugfix release which fixes bad inline field highlighting if '[' and '(' are mixed on the same line in particular orders.

---

# 0.4.17

Minor feature release to patch up more implementation holes.

## Single File Queries

You can now query from a specific file (instead of just folders and tags) by specifying the full file path:

```
TASK FROM "dataview/Test"
...
```

This is primarily useful for task queries, but will soon be useful for section and object queries in the near future as
well.

## Better Inline Field Highlighting

The CSS for inline field highlighting has been fixed and some compatibility issues improved, so it should work on all
themes now instead of only a few.

## dv.el()

DataviewJS now has `dv.el()`, which is like existing functions like `dv.paragraph` and `dv.span` but can create any
HTML element type; for example:

```js
dv.el("b", "Text!");
dv.el("i", 18);
```

---

# 0.4.16

Small performance release which substantially reduces the impact Dataview has on vault loading times (by spreading out
file loading). The Dataview Index is now also eagerly initialized, so plugin consumers of the API can immediately start
using it instead of waiting for the `dataview:api-ready` event.

---

# 0.4.15

A simple fix for #537 which properly 'awaits' value rendering in `dv.view()`. Fixes issues with values rendering out of
order.

---

# 0.4.14

Small bugfix release.

- Fixes inline field evaluation when using the new fancy highlighting.
- You can now configure whether task links should show up at the beginning or end of the task (or just disable them)
  in the "Task Link Location" setting.
- Most setting updates will immediately be applied to existing Dataviews.

---

# 0.4.13

Bugfix release which adds fancy rendering to inline-inline fields and includes a few bugfixes.

## Pretty Inline Fields

Inline fields of the form `[key:: value]` will now be rendered with fancy new HTML! By default, they are rendered with
both the key and value. You can only render the value using parenthesis instead: `(key:: value)`. You can disable
this feature in the configuration.

Full-line inline fields (that Dataview has supported for a long time) will gain similar rendering support soon; in the
meanwhile, give the new syntax a try!

### Task Linking

Tasks now render with a link to the page/section that they are defined in, making `GROUP BY` and custom task
editing easier to do:

- [ ] A Task. 🔗
- [ ] Another Task. 🔗
    - [ ] Some Random Subtask. 🔗

You can configure the symbol for the link or disable it altogether.

### Improving DataviewJS Posture

I am currently actively looking into improving DataviewJS sandboxing and general security posture. As a first small step
in this, I have made DataviewJS opt-in instead of opt-out, and added a separate control for Inline DataviewJS. You may
need to re-enable it in your settings if you use it.

More improvements and better JavaScript sandboxing will follow.

---

# 0.4.12-hotfix1

Re-release of 0.4.12 that fixes an important indexing issue.

- Fix #505: Use `completion` instead of `completed` when setting task completion time.
- Fix #509: Add `startswith` / `endswith` string functions.
- Fix #488: Add `padleft` and `padright`, and `string`.
- Fix #506, #512: Fix date comparisons due to a bizarre date zone issue.

---

# 0.4.12

Bugfix release following up 0.4.11 which includes a few minor function additions.

- Fix #512: Strange zone issue causing dates to not be equal.
- Fix #506: Same as #512.
- Fix #488: Add `padleft` / `padright` functions.
- Fix #509: Add `startswith` and `endswith` functions.
- Fix #505: Correctly read completion dates for tasks from `completion`.

This release also includes improved testing thanks to mocking Obsidian plugin APIs!

---

# 0.4.11

Fixes task behavior and adds "truly inline" fields!

## Improved Task Behavior

Task queries are now much improved from their primitive foundations - you can now filter, sort, and group them! The FROM
block is still page-based, sadly, though you can simply use `WHERE` instead if desired. For example, you can now access
task fields like `text`, `line`, or `completed`:

```
TASK WHERE contains(text, "#tag")
WHERE !completed
GROUP BY file.folder
```

The full list of all available task metadata can be found
[here](https://blacksmithgu.github.io/obsidian-dataview/data-annotation/#tasks); tasks include all the information
needed to uniquely identify them, and automatically inherit all of the metadata from their parent file as well (so you
can access `file.name`, for example). You can also annotate tasks with inline fields, as described in the section below.

There is some additional UX work to be done - primarily on more easily allowing you to navigate to where the task is
defined, as well as render tasks in views other than the `TASK` view.  The semantics of how grouping works (to make it
more intuitive/useful than it currently is) will likely also be revisited.

## Inline Inline Fields

Early support for truly inline fields have been added, where you can add metadata in the middle of a sentence. It looks
similar to existing inline field syntax, but with brackets or parenthesis:

```
I would rate this a [rating:: 6]. It was (thoughts:: acceptable).
```

Improved rendering for all inline fields is coming in an upcoming update to improve the visual look of these inline
fields.


## Issues

- Fix #496: Fix task `SORT` functionality to do something.
- Fix #492: Tasks now properly annotated with parent file information.
- Fix #498: Fix task checking/unchecking logic (which broke due to a change in the task regex...).

---

# Initial

Start of the automatic changelog.


================================================
FILE: docs/docs/friends.md
================================================
# Friends of Dataview

A list of plugins which may be helpful for Dataview related workflows:

 - [MetaEdit](https://github.com/chhoumann/MetaEdit) - Add or update yaml properties and Dataview fields easily

Another non-exhaustive list of plugins which use Dataview for some of the heavy-lifting required for their features:

 - [Kanban](https://github.com/mgmeyers/obsidian-kanban) - Create markdown-backed Kanban boards in Obsidian
 - [Breadcrumbs](http://publish.obsidian.md/breadcrumbs-docs) - Gives you a way to visualize a custom-built hierarchy in your Obsidian vault
 - [Supercharged Links](https://github.com/mdelobelle/obsidian_supercharged_links) - Allows you to style links in your Obsidian vault based on note metadata

A full list can be found using GitHub's [Dependents](https://github.com/blacksmithgu/obsidian-dataview/network/dependents) feature.


================================================
FILE: docs/docs/index.md
================================================
# Overview

Dataview is a live index and query engine over your personal knowledge base. You can [**add metadata**](annotation/add-metadata.md) to your notes and **query** them with the [**Dataview Query Language**](queries/structure.md) to list, filter, sort or group your data. Dataview keeps your queries always up to date and makes data aggregation a breeze.

You could

- Track your sleep by recording it in daily notes, and automatically create weekly tables of your sleep schedule.
- Automatically collect links to books in your notes, and render them all sorted by rating.
- Automatically collect pages associated with today's date and show them in your daily note.
- Find pages with no tags for follow-up, or show pretty views of specifically-tagged pages.
- Create dynamic views which show upcoming birthdays or events recorded in your notes

and many more things.

!!! hint "Dataview gives you a fast way to search, display and operate on indexed data in your vault!"

Dataview is highly generic and high performance, scaling up to hundreds of thousands of annotated notes without issue. 

If the built in [query language](queries/structure.md) is insufficient for your purpose, you can run arbitrary
JavaScript against the [dataview API](api/intro.md) and build whatever utility you might need yourself, right in your notes.

!!! info "Dataview is about displaying, not editing"
    Dataview is meant for displaying and calculating data. It is not meant to edit your notes/metadata and will always leave them untouched (... except if you're checking a [Task](queries/query-types.md#task) through Dataview.)

## How to Use Dataview

Dataview consists of two big building blocks: **Data Indexing** and **Data Querying**. 

!!! info "More details on the linked documentation pages"
    The following sections should give you a general overview about what you can do with dataview and how. Be sure to visit the linked pages to find out more about the individual parts.

### Data Indexing

Dataview operates on metadata in your Markdown files. It cannot read everything in your vault, but only specific data. Some of your content, like tags and bullet points (including tasks), are [available automatically](annotation/add-metadata.md#implicit-fields) in Dataview. You can add other data through **fields**, either on top of your file [per YAML Frontmatter](annotation/add-metadata.md#frontmatter) or in the middle of your content with [Inline Fields](annotation/add-metadata.md#inline-fields) via the `[key:: value]` syntax. Dataview _indexes_ these data to make it available for you to query. 

!!! hint "Dataview indexes [certain information](annotation/add-metadata.md#implicit-fields) like tags and list items and the data you add via fields. Only indexed data is available in a Dataview query!"

For example, a file might look like this:

```markdown
---
author: "Edgar Allan Poe"
published: 1845
tags: poems
---

# The Raven

Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
```

Or like this:

```markdown
#poems

# The Raven

From [author:: Edgar Allan Poe], written in (published:: 1845)

Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
```

In terms of indexed metadata (or what you can query), they are identical, and only differ in their annotation style. How you want to [annotate your  metadata](annotation/add-metadata.md) is up to you and your personal preference. With this file, you'd have the **metadata field** `author` available and everything Dataview provides you [automatically as implicit fields](annotation/metadata-pages.md), like the tag or note title. 

!!! attention "Data needs to be indexed"
    In the above example, you _do not_ have the poem itself available in Dataview: It is a paragraph, not a metadata field and not something Dataview indexes automatically. It is not part of Dataviews index, so you won't be able to query it.

### Data Querying

You can access **indexed data** with the help of **Queries**.

There are **three different ways** you can write a Query: With help of the [Dataview Query Language](queries/dql-js-inline.md#dataview-query-language-dql), as an [inline statement](queries/dql-js-inline.md#inline-dql) or in the most flexible but most complex way: as a [Javascript Query](queries/dql-js-inline.md#dataview-js). 

The **Dataview Query Language** (**DQL**) gives you a broad and powerful toolbelt to query, display and operate on your data. An [**inline query**](queries/dql-js-inline.md#inline-dql) gives you the possibility to display exactly one indexed value anywhere in your note. You can also do calculations this way. With **DQL** at your hands, you'll be probably fine without any Javascript through your data journey.

A DQL Query consists of several parts:

- Exactly one [**Query Type**](queries/query-types.md) that determines what your Query Output looks like
- None or one [**FROM statement**](queries/data-commands.md#from) to pick a specific tag or folder (or another [source](reference/sources.md)) to look at
- None to multiple [**other Data Commands**](queries/data-commands.md) that help you filter, group and sort your wanted output

For example, a Query can look like this:

~~~markdown
```dataview
LIST
```
~~~

which list all files in your vault. 

!!! info "Everything but the Query Type is optional"
    The only thing you need for a valid DQL Query is the Query Type (and on [CALENDAR](queries/query-types.md#calendar)s, a date field.)

 A more restricted Query might look like this:

~~~markdown
```dataview
LIST
FROM #poems
WHERE author = "Edgar Allan Poe"
```
~~~

which lists all files in your vault that have the tag `#poems` and a [field](annotation/add-metadata.md) named `author` with the value `Edgar Allan Poe`. This query would find our example page from above. 

`LIST` is only one out of four [Query Types](queries/query-types.md) you can use. For example, with a `TABLE`, we could add some more information to our output: 


~~~markdown
```dataview
TABLE author, published, file.inlinks AS "Mentions"
FROM #poems
```
~~~

This'll give you back a result like:

| File (3) |	author |	published	| Mentions |
| -------- | ------- | ---------- | -------- |
| The Bells |	Edgar Allan Poe |	1849 |  |	
| The New Colossus |	Emma Lazarus | 1883	| - [[Favorite Poems]] |	
| The Raven |	Edgar Allan Poe |	1845 | - [[Favorite Poems]] |	

That's not where the capabilities of dataview end, though. You can also **operate on your data** with help of [**functions**](reference/functions.md). Mind that these operations are only made inside your query - your **data in your files stays untouched**.

~~~markdown
```dataview
TABLE author, date(now).year - published AS "Age in Yrs", length(file.inlinks) AS "Counts of Mentions"
FROM #poems
```
~~~

gives you back

| File (3) |	author |	Age in Yrs	| Count of Mentions |
| -------- | ------- | ---------- | -------- |
| The Bells	|  Edgar Allan Poe |	173 | 0 |
| The New Colossus	| Emma Lazarus |	139 |	1 |
| The Raven |	Edgar Allan Poe |	177 | 1 |	

!!! info "Find more examples [here](resources/examples.md)."

As you can see, dataview doesn't only allow you to aggregate your data swiftly and always up to date, it also can help you with operations to give you new insights on your dataset. Browse through the documentation to find out more on how to interact with your data.

 Have fun exploring your vault in new ways! 

## Resources and Help

This documentation is not the only place that can help you out on your data journey. Take a look at [Resources and Support](./resources/resources-and-support.md) for a list of helpful pages and videos.


================================================
FILE: docs/docs/queries/data-commands.md
================================================
# Data Commands

The different commands that dataview queries can be made up of. Commands are
executed in order, and you can have duplicate commands (so multiple `WHERE`
blocks or multiple `GROUP BY` blocks, for example).

## FROM

The `FROM` statement determines what pages will initially be collected and passed onto the other commands for further
filtering. You can select from any [source](../reference/sources.md), which currently means by folder, by tag, or by incoming/outgoing links.

- **Tags**: To select from a tag (and all its subtags), use `FROM #tag`.
- **Folders**: To select from a folder (and all its subfolders), use `FROM "folder"`.
- **Single Files**: To select from a single file, use `FROM "path/to/file"`.
- **Links**: You can either select links TO a file, or all links FROM a file.
  - To obtain all pages which link TO `[[note]]`, use `FROM [[note]]`.
  - To obtain all pages which link FROM `[[note]]` (i.e., all the links in that file), use `FROM outgoing([[note]])`.

You can compose these filters in order to get more advanced sources using `and` and `or`.

- For example, `#tag and "folder"` will return all pages in `folder` and with `#tag`.
- `[[Food]] or [[Exercise]]` will give any pages which link to `[[Food]]` OR `[[Exercise]]`.

You can also "negate" sources to obtain anything that does NOT match a source using `-`:

- `-#tag` will exclude files which have the given tag.
- `#tag and -"folder"` will only include files tagged `#tag` which are NOT in `"folder"`.

## WHERE

Filter pages on fields. Only pages where the clause evaluates to `true` will be yielded.

```
WHERE <clause>
```

1. Obtain all files which were modified in the last 24 hours:

    ```sql
    LIST WHERE file.mtime >= date(today) - dur(1 day)
    ```

2. Find all projects which are not marked complete and are more than a month old:

    ```sql
    LIST FROM #projects
    WHERE !completed AND file.ctime <= date(today) - dur(1 month)
    ```

## SORT

Sorts all results by one or more fields.

```
SORT date [ASCENDING/DESCENDING/ASC/DESC]
```

You can also give multiple fields to sort by. Sorting will be done based on the first field. Then, if a tie occurs, the second field will be used to sort the tied fields. If there is still a tie, the third sort will resolve it, and so on.

```
SORT field1 [ASCENDING/DESCENDING/ASC/DESC], ..., fieldN [ASC/DESC]
```

## GROUP BY

Group all results on a field. Yields one row per unique field value, which has 2 properties: one corresponding to the field being grouped on, and a `rows` array field which contains all of the pages that matched.

```
GROUP BY field
GROUP BY (computed_field) AS name
```

In order to make working with the `rows` array easier, Dataview supports field "swizzling". If you want the field `test` from every object in the `rows` array, then `rows.test` will automatically fetch the `test` field from every object in `rows`, yielding a new array.
You can then apply aggregation operators like `sum()` or `flat()` over the resulting array.

## FLATTEN

Flatten an array in every row, yielding one result row per entry in the array.

```
FLATTEN field
FLATTEN (computed_field) AS name
```

For example, flatten the `authors` field in each literature note to give one row per author:

=== "Query"
    ```sql
    TABLE authors FROM #LiteratureNote
    FLATTEN authors
    ```
=== "Output"
    |File|authors|
    |-|-|
    |stegEnvironmentalPsychologyIntroduction2018 SN|Steg, L.|
    |stegEnvironmentalPsychologyIntroduction2018 SN|Van den Berg, A. E.|
    |stegEnvironmentalPsychologyIntroduction2018 SN|De Groot, J. I. M.|
    |Soap Dragons SN|Robert Lamb|
    |Soap Dragons SN|Joe McCormick|
    |smithPainAssaultSelf2007 SN|Jonathan A. Smith|
    |smithPainAssaultSelf2007 SN|Mike Osborn|

A good use of this would be when there is a deeply nested list that you want to use more easily.
For example, `file.lists` or `file.tasks`.
Note the simpler query though the end results are slightly different (grouped vs non-grouped).
You can use a `GROUP BY file.link` to achieve identical results but would need to use `rows.T.text` as described earlier.

```
table T.text as "Task Text"
from "Scratchpad"
flatten file.tasks as T
where T.text
```

```
table filter(file.tasks.text, (t) => t) as "Task Text"
from "Scratchpad"
where file.tasks.text
```

`FLATTEN` makes it easier to operate on nested lists since you can then use simpler where conditions on them as opposed to using functions like `map()` or `filter()`.

## LIMIT

Restrict the results to at most N values.

```
LIMIT 5
```

Commands are processed in the order they are written, so the following sorts the results *after* they have already been limited:

```
LIMIT 5
SORT date ASCENDING
```


================================================
FILE: docs/docs/queries/differences-to-sql.md
================================================
<!--
 * @Author: chinesehamburger 2576226012@qq.com
 * @Date: 2024-12-12 14:24:45
 * @LastEditors: chinesehamburger 2576226012@qq.com
 * @LastEditTime: 2024-12-13 16:40:43
 * @FilePath: \obsidian-dataview\docs\docs\queries\differences-to-sql.md
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
# Dataview Query Language (DQL) and SQL

If you are familiar with SQL and experienced in writing SQL queries, you might approach writing a DQL query in a similar way. However, DQL is significantly different from SQL.

A DQL query is **executed from top to bottom**, line-by-line. It is more like a computer program than a typical SQL query.

When a line is evaluated, it produces a result set and **passes the whole set on to the next DQL line** which will manipulate the set that it received from the previous line. This is why in DQL it is possible, for example, to have multiple WHERE clauses. But in DQL it is not a 'clause' but a 'data command'. Every line of a DQL query (except the 1st and 2nd lines) is a 'data command'.

## Anatomy of a DQL query

Instead of starting with SELECT, a DQL query starts with a word determining the Query Type, which determines how your final result will be rendered on screen (a table, a list, a task list, or a calendar). Then follows the list of fields, which is actually very similar to the column list you put after a SELECT statement.

The next line starts with FROM which is not followed by a table name but by a complex expression, similar to an SQL WHERE clause. Here you can filter on many things, like tags in files, file names, path names, etc. In the background, this command already produces a result set which will be our initial set for further data manipulation by 'data commands' on subsequent lines.

You can have as many following lines as you want. Each will start with a [data command](data-commands.md) and will re-shape the result set it received from the previous line. For example:

- The WHERE data command will only keep those lines from the result set which match a given condition. This means that, unless all data in the result set matches the condition, this command will pass on a smaller result set to the next line than it received from the previous line. Unlike in SQL, you can have as many WHERE commands as you like.
- The FLATTEN data command is not found in common SQL but in DQL you can use it to reduce the depth of the result set.
- DQL, similarly to SQL, has a GROUP BY command but this can also be used multiple times, which is not possible in common SQL. You can even do several SORT or GROUP BY commands one after the other.


================================================
FILE: docs/docs/queries/dql-js-inline.md
================================================
# DQL, JS and Inlines

Once you've added [useful data to relevant pages](../annotation/add-metadata.md), you'll want to actually display it somewhere or operate on it. Dataview
allows this in four different ways, all of which are written in codeblocks directly in your Markdown and live-reloaded
when your vault changes.

## Dataview Query Language (DQL)

The [**Dataview Query Language**](structure.md) (for short **DQL**) is a SQL-like language and Dataviews core functionality. It supports [four Query Types](./query-types.md) to produce different outputs, [data commands](./data-commands.md) to refine, resort or group your result and [plentiful functions](../reference/functions.md) which allow numerous operations and adjustments to achieve your wanted output.

!!! warning Differences to SQL
    If you are familiar with SQL, please read [Differences to SQL](differences-to-sql.md) to avoid confusing DQL with SQL.

You create a **DQL** query with a codeblock that uses `dataview` as type:

~~~
```dataview
TABLE rating AS "Rating", summary AS "Summary" FROM #games
SORT rating DESC
```
~~~

!!! attention "Use backticks"
    A valid codeblock needs to use backticks (\`) on start and end (three each). Do not confuse the backtick with the similar looking apostrophe ' !

Find a explanation how to write a DQL Query under the [query language
reference](structure.md). If you learn better by example, take a look at the [query examples](../resources/examples.md).

## Inline DQL

A Inline DQL uses a inline block format instead of a code block and a configurable prefix to mark this inline code block as a DQL block.

~~~
`= this.file.name`
~~~

!!! info "Change of DQL prefix"
    You can change the `=` to another token (like `dv:` or `~`) in Dataviews' settings under "Codeblock Settings" > "Inline Query Prefix"

Inline DQL Queries display **exactly one value** somewhere in the middle of your note. They seamlessly blend into the content of your note:

~~~markdown
Today is `= date(today)` - `= [[exams]].deadline - date(today)` until exams!
~~~

would, for example, render to

~~~markdown
Today is November 07, 2022 - 2 months, 5 days until exams!
~~~

**Inline DQL** queries always display exactly one value, not a list (or table) of values. You can access the properties of the **current page** via prefix `this.` or a different page via `[[linkToPage]].`.

~~~markdown
`= this.file.name`
`= this.file.mtime`
`= this.someMetadataField`
`= [[secondPage]].file.name`
`= [[secondPage]].file.mtime`
`= [[secondPage]].someMetadataField`
~~~

You can use everything available as [expressions](../reference/expressions.md) and [literals](../reference/literals.md) in an Inline DQL Query, including [functions](../reference/functions.md). Query Types and Data Commands, on the other hand, are **not available in Inlines.**

~~~markdown
Assignment due in `= this.due - date(today)`
Final paper due in `= [[Computer Science Theory]].due - date(today)`

🏃‍♂️ Goal reached? `= choice(this.steps > 10000, "YES!", "**No**, get moving!")`

You have `= length(filter(link(dateformat(date(today), "yyyy-MM-dd")).file.tasks, (t) => !t.completed))` tasks to do. `= choice(date(today).weekday > 5, "Take it easy!", "Time to get work done!")`
~~~

## Dataview JS

The dataview [JavaScript API](../api/intro.md) gives you the full power of JavaScript and provides a DSL for pulling
Dataview data and executing queries, allowing you to create arbitrarily complex queries and views. Similar to the query
language, you create Dataview JS blocks via a `dataviewjs`-annotated codeblock:

~~~java
```dataviewjs
let pages = dv.pages("#books and -#books/finished").where(b => b.rating >= 7);
for (let group of pages.groupBy(b => b.genre)) {
   dv.header(3, group.key);
   dv.list(group.rows.file.name);
}
```
~~~

Inside of a JS dataview block, you have access to the full dataview API via the `dv` variable. For an explanation of
what you can do with it, see the [API documentation](../api/code-reference.md), or the [API
examples](../api/code-examples.md).

!!! attention "Advanced usage"
    Writing Javascript queries is a advanced technique that requires understanding in programming and JS. Please be aware that JS Queries have access to your file system and be cautious when using other peoples' JS Queries, especially when they are not publicly shared through the Obsidian Community.

## Inline Dataview JS

Similar to the query language, you can write JS inline queries, which let you embed a computed JS value directly. You
create JS inline queries via inline code blocks:

```
`$= dv.current().file.mtime`
```

In inline DataviewJS, you have access to the `dv` variable, as in `dataviewjs` codeblocks, and can make all of the same calls. The result
should be something which evaluates to a JavaScript value, which Dataview will automatically render appropriately.

Unlike Inline DQL queries, Inline JS queries do have access to everything a Dataview JS Query has available and can hence query and output multiple pages.

!!! info "Change of Inline JS prefix"
    You can change the `$=` to another token (like `dvjs:` or `$~`) in Dataviews' settings under "Codeblock Settings" > "Javascript Inline Query Prefix"


================================================
FILE: docs/docs/queries/query-types.md
================================================
# Query Types

The **Query Type** determines how the output of your dataview query looks like. It is the **first and only mandatory** specification you give to a dataview query. There are four available: `LIST`, `TABLE`, `TASK` and `CALENDAR`.

The Query Type also determines which **information level** a query is executed on. `LIST`, `TABLE` and `CALENDAR` operate at **page level** whereas `TASK` queries operate at the `file.tasks` level. More on that in the `TASK` Query Type.

You can combine **every Query Type with all available [Data Commands](data-commands.md)** to refine your result set. Read more about the interconnection between Query Types and Data Commands on [How to Use Dataview](../index.md#how-to-use-dataview) and the [structure page](structure.md).

!!! summary "Query Type"
    The Query Type determines the output format of a query. It's the only mandatory information for a query.

## LIST

`LIST` queries output a bullet point list consisting of your file links or the group name, if you decided to [group](data-commands.md#group-by). You can specify up to **one additional information** to output alongside your file or group information.

!!! summary "Query Type `LIST`"
    `LIST` outputs a bullet point list of page links or Group keys. You can specify one additional information to show for each result.

The simplest LIST query outputs a bullet point list of all files in your vault:

~~~
```dataview
LIST
```
~~~

**Output**


- [Classic Cheesecake](#)
- [Git Basics](#)
- [How to fix Git Cheatsheet](#)
- [League of Legends](#)
- [Pillars of Eternity 2](#)
- [Stardew Valley](#)
- [Dashboard](#)


but you can, of course, use [data commands](data-commands.md) to restrict which pages you want to have listed:

~~~
```dataview
LIST
FROM #games/mobas OR #games/crpg
```
~~~

**Output**

- [League of Legends](#)
- [Pillars of Eternity 2](#)

### Output an additional information

To add a **additional information** to your query, specify it right after the `LIST` command and before possibly available data commands:

~~~
```dataview
LIST file.folder
```
~~~

**Output**


- [Classic Cheesecake](#): Baking/Recipes
- [Git Basics](#): Coding
- [How to fix Git Cheatsheet](#): Coding/Cheatsheets
- [League of Legends](#): Games
- [Pillars of Eternity 2](#): Games
- [Stardew Valley](#): Games/finished
- [Dashboard](#):

You can only add **one** additional information, not multiple. But you can **specify a computed value** instead of a plain meta data field, which can contain information of multiple fields:

~~~
```dataview
LIST "File Path: " + file.folder + " _(created: " + file.cday + ")_"
FROM "Games"
```
~~~

**Output**

- [League of Legends](#): File Path: Games _(created: May 13, 2021)_
- [Pillars of Eternity 2](#): File Path: Games _(created: February 02, 2022)_
- [Stardew Valley](#): File Path: Games/finished _(created: April 04, 2021)_

### Grouping

A **grouped list** shows their group keys, and only the group keys, by default:

~~~
```dataview
LIST
GROUP BY type
```
~~~

**Output**

- game
- knowledge
- moc
- recipe
- summary

A common use-case on grouped `LIST` queries is to add the file links to the output by specifying them as the additional information:

~~~
```dataview
LIST rows.file.link
GROUP BY type
```
~~~

- game:
    - [Stardew Valley](#)
    - [League of Legends](#)
    - [Pillars of Eternity 2](#)
- knowledge:
    - [Git Basics](#)
- moc:
    - [Dashboard](#)
- recipe:
    - [Classic Cheesecake](#)
- summary:
    - [How to fix Git Cheatsheet](#)

### LIST WITHOUT ID

If you don't want the file name or group key included in the list view, you can use `LIST WITHOUT ID`. `LIST WITHOUT ID` works the same as `LIST`, but it does not output the file link or group name if you add an additional information.

~~~
```dataview
LIST WITHOUT ID
```
~~~

**Output**


- [Classic Cheesecake](#)
- [Git Basics](#)
- [How to fix Git Cheatsheet](#)
- [League of Legends](#)
- [Pillars of Eternity 2](#)
- [Stardew Valley](#)
- [Dashboard](#)

It's the same as `LIST`, because it does not contain an additional information!

~~~
```dataview
LIST WITHOUT ID type
```
~~~

**Output**

- moc
- recipe
- summary
- knowledge
- game
- game
- game

`LIST WITHOUT ID` can be handy if you want to output computed values, for example.

~~~
```dataview
LIST WITHOUT ID length(rows) + " pages of type " + key
GROUP BY type
```
~~~

**Output**

- 3 pages of type game
- 1 pages of type knowledge
- 1 pages of type moc
- 1 pages of type recipe
- 1 pages of type summary

## TABLE

The `TABLE` query types outputs page data as a tabular view. You can add zero to multiple meta data fields to your `TABLE` query by adding them as a **comma separated list**. You can not only use plain meta data fields as columns, but specify **calculations** as well. Optionally, you can specify a **table header** via the `AS <header>` syntax. Like all other query types, you can refine your result set for your query with [data commands](data-commands.md).

!!! summary "`TABLE` Query Type"
    `TABLE` queries render a tabular view of any number of meta data values or calculations. It is possible to specify column headers via `AS <header>`.

~~~
```dataview
TABLE
```
~~~

**Output**

| File (7) |
| ----- |
| [Classic Cheesecake](#) |
| [Git Basics](#) |
| [How to fix Git Cheatsheet](#) |
| [League of Legends](#) |
| [Pillars of Eternity 2](#) |
| [Stardew Valley](#) |
| [Dashboard](#) |

!!! hint "Changing the first column header name"
    You can change the name of the first column header (by default "File" or "Group") via the Dataview Settings under Table Settings -> Primary Column Name / Group Column Name.
    If you want to change the name only for one specific `TABLE` query, have a look at `TABLE WITHOUT ID`.

!!! info "Disabling Result count"
    The first column always shows the result count. If you do not want to get it displayed, you can disable it in Dataview's settings ("Display result count", available since 0.5.52).

Of course, a `TABLE` is made for specifying one to multiple additional information:

~~~
```dataview
TABLE started, file.folder, file.etags
FROM #games
```
~~~

**Output**

| File (3) | started | file.folder | file.etags |
| --- | --- | --- | --- |
| [League of Legends](#)  | 	May 16, 2021 | 	Games	 | - #games/moba  |
| [Pillars of Eternity 2](#)  | 	April 21, 2022 | 	Games	 | - #games/crpg |
| [Stardew Valley](#) | 	April 04, 2021 | 	Games/finished	 |  - #games/simulation |

!!! hint "Implicit fields"
    Curious about `file.folder` and `file.etags`? Learn more about [implicit fields on pages](../annotation/metadata-pages.md).

### Custom Column Headers

You can specify **custom headings** for your columns by using the `AS` syntax:

~~~
```dataview
TABLE started, file.folder AS Path, file.etags AS "File Tags"
FROM #games
```
~~~

**Output**

| File (3) | started | Path | File Tags |
| --- | --- | --- | --- |
| [League of Legends](#) | 	May 16, 2021 | 	Games	 | - #games/moba  |
| [Pillars of Eternity 2](#)  | 	April 21, 2022 | 	Games	 | - #games/crpg |
| [Stardew Valley](#) | 	April 04, 2021 | 	Games/finished	 |  - #games/simulation |

!!! info "Custom headers with spaces"
    If you want to use a custom header with spaces, like `File Tags`, you need to wrap it into double quotes: `"File Tags"`.

This is especially useful when you want to use **calculations or expressions as column values**:

~~~
```dataview
TABLE
default(finished, date(today)) - started AS "Played for",
file.folder AS Path,
file.etags AS "File Tags"
FROM #games
```
~~~

**Output**

| File (3) | Played for | Path | File Tags |
| --- | --- | --- | --- |
| [League of Legends](#) | 	1 years, 6 months, 1 weeks | 	Games	 | - #games/moba  |
| [Pillars of Eternity 2](#)  | 	7 months, 2 days | 	Games	 | - #games/crpg |
| [Stardew Valley](#) | 	4 months, 3 weeks, 3 days | 	Games/finished	 |  - #games/simulation |

!!! hint "Calculations and expressions"
    Learn more about the capability of computing expressions and calculations under [expressions](../reference/expressions.md) and [functions](../reference/functions.md).

### TABLE WITHOUT ID

If you don't want the first column ("File" or "Group" by default), you can use `TABLE WITHOUT ID`. `TABLE WITHOUT ID` works the same as `TABLE`, but it does not output the file link or group name as a first column if you add additional information.

You can use this if you, for example, output another identifying value:

~~~
```dataview
TABLE WITHOUT ID
steamid,
file.etags AS "File Tags"
FROM #games
```
~~~

**Output**

| steamid (3)  | File Tags |
| --- | --- |
| 560130 |  - #games/crog  |
| - |  - #games/moba |
| 413150 |   - #games/simulation |

Also, you can use `TABLE WITHOUT ID` if you want to **rename the first column for one specific query**.

~~~
```dataview
TABLE WITHOUT ID
file.link AS "Game",
file.etags AS "File Tags"
FROM #games
```
~~~

**Output**

| Game (3) | File Tags |
| --- | --- |
| [League of Legends](#) |  - #games/moba  |
| [Pillars of Eternity 2](#)  | - #games/crpg |
| [Stardew Valley](#) |  - #games/simulation |

!!! info "Renaming the first column in general"
    If you want to rename the first column in all cases, change the name in Dataviews settings under Table Settings.

## TASK

The `TASK` Query outputs **an interactive list of all tasks in your vault** that match the given [data commands](data-commands.md) (if any). `TASK` queries are special compared to the other Query Types because they do give back **Tasks as results and not pages**. This implies that all [data commands](data-commands.md) operate on **Task level** and makes it possible to granularly filter your tasks i.e. for their status or meta data specified on the task itself.

Also, `TASK` Queries are the only possibility to **manipulate your files through DQL**. Normally, Dataview does not touch the content of your files; however, if you check a task through a dataview query, it'll get **checked in its original file, too**. In the Dataview Settings under "Task Settings", you can opt-in to automatically set a `completion` meta data field when checking a task in dataview. Mind though that this only works if you check the task inside a dataview block.

!!! summary "`TASK` Query Type"
    `TASK` queries render an interactive list of all tasks in your vault. `TASK` Queries are executed on **task level**, not page level, allowing for task-specific filtering. This is the only command in dataview that modifies your original files if interacted with.

~~~
```dataview
TASK
```
~~~

**Output**

- [ ] Buy new shoes #shopping
- [ ] Mail Paul about training schedule
- [ ] Finish the math assignment
    - [x] Finish Paper 1 [due:: 2022-08-13]
    - [ ] Read again through chapter 3 [due:: 2022-09-01]
    - [x] Write a cheatsheet [due:: 2022-08-02]
    - [ ] Write a summary of chapter 1-4 [due:: 2022-09-12]
- [x] Hand in physics
- [ ] Get new pillows for mom #shopping
- [x] Buy some working pencils #shopping

You can use [data commands](data-commands.md) like for all other Query Types. Data Commands are executed on task level, making [implicit fields on tasks](../annotation/metadata-tasks.md) directly available.

~~~
```dataview
TASK
WHERE !completed AND contains(tags, "#shopping")
```
~~~

**Output**

- [ ] Buy new shoes #shopping
- [ ] Get new pillows for mom #shopping

A common use case for tasks is to **group tasks by their originating file**:

~~~
```dataview
TASK
WHERE !completed
GROUP BY file.link
```
~~~

**Output**

[2022-07-30](#) (1)

- [ ] Finish the math assignment
    - [ ] Read again through chapter 3 [due:: 2022-09-01]
    - [ ] Write a summary of chapter 1-4 [due:: 2022-09-12]

[2022-09-21](#) (2)

- [ ] Buy new shoes #shopping
- [ ] Mail Paul about training schedule

[2022-09-27](#) (1)

- [ ] Get new pillows for mom #shopping

!!! hint "Counting tasks with subtask"
    Noticing the (1) on the header of `2022-07-30`? Child tasks belong to their parent task and are not counted separately. Also, they **behave differently** on filtering.

### Child Tasks

A task is considered a **child task** if it is **indented by a tab** and is below an unindented task.

- [ ] clean up the house
	- [ ] kitchen
	- [x] living room
	- [ ] Bedroom [urgent:: true]


!!! info "Children of a bullet point item"
    While indented tasks under a bulleted list item are, strictly speaking, also child tasks, Dataview will handle them like normal tasks in most cases.

Child Tasks **belong to their parent**. This means if you're querying for tasks, you'll get child tasks as part of their parent back.

~~~
```dataview
TASK
```
~~~

**Output**

- [ ] clean up the house
	- [ ] kitchen
	- [x] living room
	- [ ] Bedroom [urgent:: true]
- [ ] Call the insurance about the car
- [x] Find out the transaction number

This specifically means that child task will be part of your result set **as long as the parent matches the query** - even if the child task itself doesn't.

~~~
```dataview
TASK
WHERE !completed
```
~~~

**Output**

- [ ] clean up the house
	- [ ] kitchen
	- [x] living room
	- [ ] Bedroom [urgent:: true]
- [ ] Call the insurance about the car

Here, `living room` does **not match** the query, but is included anyway, because its parent `clean up the house` does match.

Mind that you'll get individual children tasks back, if the child matches your predicate but the parent doesn't:

~~~
```dataview
TASK
WHERE urgent
```
~~~

**Output**

- [ ] Bedroom [urgent:: true]

## CALENDAR

The `CALENDAR` Query outputs a monthly based calendar where every result is depicted as a dot on it referring date. The `CALENDAR` is the only Query Type that requires an additional information. This additional information needs to be a [date](../annotation/types-of-metadata.md#date) (or unset) on all queried pages.

!!! summary "`CALENDAR` Query Type"
    The `CALENDAR` Query Types renders a calendar view where every result is represented by a dot on the given meta data field date.



~~~
```dataview
CALENDAR file.ctime
```
~~~

**Output**

![](../assets/calendar_query_type.png)

While it is possible to use `SORT` and `GROUP BY` in combination with `CALENDAR`, it has **no effect**. Additionally, the calendar query does not render if the given meta data field contains something else than a valid [date](../annotation/types-of-metadata.md#date) (but the field can be empty). To make sure you're only taking valid pages into account, you can filter for valid meta data values:

~~~
```dataview
CALENDAR due
WHERE typeof(due) = "date"
```
~~~


================================================
FILE: docs/docs/queries/structure.md
================================================
# Structure of a Query

Dataview offers [multiple ways](dql-js-inline.md) to write queries and the syntax differs for each.

This page provides information on how to write a **Dataview Query Language** (**DQL**) query. If you're interested in how to write Inline Queries, refer to the [inline section on DQL, JS and Inlines](dql-js-inline.md#inline-dql). You'll find more information about **Javascript Queries** on the [Javascript Reference](../api/intro.md).

**DQL** is a SQL like query language for creating different views or calculations on your data. It
supports:

- Choosing an **output format** of your output (the [Query Type](./query-types.md))
- Fetch pages **from a certain [source](../reference/sources.md)**, i.e. a tag, folder or link
- **Filtering pages/data** by simple operations on fields, like comparison, existence checks, and so on
- **Transforming fields** for displaying, i.e. with calculations or splitting up multi-value fields
- **Sorting** results based on fields
- **Grouping** results based on fields
- **Limiting** your result count

!!! warning Differences to SQL
    If you are familiar with SQL, please read [Differences to SQL](differences-to-sql.md) to avoid confusing DQL with SQL.

Let's have a look at how we can put DQL to use.

## General Format of a DQL Query

Every query follows the same structure and consists of

- exactly one **Query Type** with zero, one or many [fields](../annotation/add-metadata.md), depending on query type
- zero or one **FROM** data commands with one to many [sources](../reference/sources.md)
- zero to many other **data commands** with one to many [expressions](../reference/expressions.md) and/or other infos depending on the data command

At a high level, a query conforms to the following pattern:

~~~
```dataview
<QUERY-TYPE> <fields>
FROM <source>
<DATA-COMMAND> <expression>
<DATA-COMMAND> <expression>
          ...
```
~~~

!!! hint "Only the Query Type is mandatory."

The following sections will explain the theory in further detail.

## Choose a Output Format

The output format of a query is determined by its **Query Type**. There are four available:

1. **TABLE**: A table of results with one row per result and one or many columns of field data.
2. **LIST**: A bullet point list of pages which match the query. You can output one field for each page alongside their file links.
3. **TASK**: An interactive task list of tasks that match the given query.
4. **CALENDAR**: A calendar view displaying each hit via a dot on its referred date.

The Query Type is the **only mandatory command in a query**. Everything else is optional.

!!! attention "Possibly memory intense examples"
    Depending on the size of your vault, executing the following examples can take long and even freeze Obsidian in extreme cases. It's recommended that you specify a `FROM` to restrict the query execution to a specific subset of your vaults' files. See next section.

~~~
Lists all pages in your vault as a bullet point list
```dataview
LIST
```

Lists all tasks (completed or not) in your vault
```dataview
TASK
```

Renders a Calendar view where each page is represented as a dot on its creation date.
```dataview
CALENDAR file.cday
```

Shows a table with all pages of your vault, their field value of due, the files' tags and an average of the values of multi-value field working-hours
```dataview
TABLE due, file.tags AS "tags", average(working-hours)
```
~~~

!!! info "Read more about the available Query Types and how to use them [here](./query-types.md)."

## Choose your source

Additionally to the Query Types, you have several **Data Commands** available that help you restrict, refine, sort or group your query. One of these query commands is the **FROM** statement. `FROM` takes a [source](../reference/sources.md) or a combination of [sources](../reference/sources.md) as an argument and restricts the query to a set of pages that match your source.

It behaves differently from the other Data Commands: You can add **zero or one** `FROM` data command to your query, right after your Query Type. You cannot add multiple FROM statements and you cannot add it after other Data Commands.

~~~
Lists all pages inside the folder Books and its sub folders
```dataview
LIST
FROM "Books"
```

Lists all pages that include the tag #status/open or #status/wip
```dataview
LIST
FROM #status/open OR #status/wip
```

Lists all pages that have either the tag #assignment and are inside folder "30 School" (or its sub folders), or are inside folder "30 School/32 Homeworks" and are linked on the page School Dashboard Current To Dos
```dataview
LIST
FROM (#assignment AND "30 School") OR ("30 School/32 Homeworks" AND outgoing([[School Dashboard Current To Dos]]))
```

~~~

!!! info "Read more about `FROM` [here](./data-commands.md#from)."

## Filter, sort, group or limit results

In addition to the Query Types and the **Data command** `FROM` that's explained above, you have several other **Data Commands** available that help you restrict, refine, sort or group your query results.

All data commands except the `FROM` command can be used **multiple times in any order** (as long as they come after the Query Type and `FROM`, if `FROM` is used at all). They'll be executed in the order they are written.

Available are:

1. **FROM** like explained [above](#choose-your-source).
2. **WHERE**: Filter notes based on information **inside** notes, the meta data fields.
3. **SORT**: Sorts your results depending on a field and a direction.
4. **GROUP BY**: Bundles up several results into one result row per group.
5. **LIMIT**: Limits the result count of your query to the given number.
6. **FLATTEN**: Splits up one result into multiple results based on a field or calculation.

~~~

Lists all pages that have a metadata field `due` and where `due` is before today
```dataview
LIST
WHERE due AND due < date(today)
```

Lists the 10 most recently created pages in your vault that have the tag #status/open
```dataview
LIST
FROM #status/open
SORT file.ctime DESC
LIMIT 10
```

Lists the 10 oldest and incomplete tasks of your vault as an interactive task list, grouped by their containing file and sorted from oldest to newest file.
```dataview
TASK
WHERE !completed
SORT created ASC
LIMIT 10
GROUP BY file.link
SORT rows.file.ctime ASC
```

~~~

!!! info "Find out more about available [data commands](./data-commands.md)."

## Examples

Following are some example queries. Find more examples [here](../resources/examples.md).

~~~
```dataview
TASK
```
~~~

~~~
```dataview
TABLE recipe-type AS "type", portions, length
FROM #recipes
```
~~~

~~~
```dataview
LIST
FROM #assignments
WHERE status = "open"
```
~~~

~~~
```dataview
TABLE file.ctime, appointment.type, appointment.time, follow-ups
FROM "30 Protocols/32 Management"
WHERE follow-ups
SORT appointment.time
```
~~~

~~~
```dataview
TABLE L.text AS "My lists"
FROM "dailys"
FLATTEN file.lists AS L
WHERE contains(L.author, "Surname")
```
~~~

~~~
```dataview
LIST rows.c
WHERE typeof(contacts) = "array" AND contains(contacts, [[Mr. L]])
SORT length(contacts)
FLATTEN contacts as c
SORT link(c).age ASC
```
~~~


================================================
FILE: docs/docs/reference/expressions.md
================================================
# Expressions

Dataview query language **expressions** are anything that yields a value:

- all [fields](../annotation/add-metadata.md)
- all [literals](./literals.md) 
- and computed values, like `field - 9` of [function calls](./functions.md). 

Basically, everything that is not a [Query Type](../queries/query-types.md), nor a [data command](../queries/data-commands.md) is an expression.

For a very high level summary, following is considered an **expression** in DQL:

```
# Literals
1                   (number)
true/false          (boolean)
"text"              (text)
date(2021-04-18)    (date)
dur(1 day)          (duration)
[[Link]]            (link)
[1, 2, 3]           (list)
{ a: 1, b: 2 }      (object)

# Lambdas
(x1, x2) => ...     (lambda)

# References
field               (directly refer to a field)
simple-field        (refer to fields with spaces/punctuation in them like "Simple Field!")
a.b                 (if a is an object, retrieve field named 'b')
a[expr]             (if a is an object or array, retrieve field with name specified by expression 'expr')
f(a, b, ...)        (call a function called `f` on arguments a, b, ...)

# Arithmetic
a + b               (addition)
a - b               (subtraction)
a * b               (multiplication)
a / b               (division)
a % b               (modulo / remainder of division)

# Comparison
a > b               (check if a is greater than b)
a < b               (check if a is less than b)
a = b               (check if a equals b)
a != b              (check if a does not equal b)
a <= b              (check if a is less than or equal to b)
a >= b              (check if a is greater than or equal to b)

# Strings

a + b               (string concatenation)
a * num             (repeat string <num> times)

# Special Operations
[[Link]].value      (fetch `value` from page `Link`)
```

More detailed explanations of each follow.

## Expression Types

### Fields as Expressions

The simplest expression is one that just directly refers to a field. If you have a field called "duedate", then you can
refer to it directly by name - `duedate`. 

~~~
```dataview
TABLE duedate, class, field-with-space
```
~~~

!!! info "Field names with spaces and punctuations"
    If the field name has spaces, punctuation, or other non-letter/number characters, then you can refer to it using Dataview's simplified name, which is all lower case with spaces replaced with "-". For example, `this is a field` becomes `this-is-a-field`; `Hello!` becomes `hello`, and so on. Read more under [Field names](../annotation/add-metadata.md#field-names)

### Literals

Constant values - things like `1` or `"hello"` or `date(som)` ("start of month"). There are literals for each data type
that dataview supports; read more about them [here](./literals.md).

~~~
```dataview
LIST
WHERE file.name = "Scribble"
```
~~~

### Arithmetic

You can use standard arithmetic operators to combine fields: addition (`+`), subtraction (`-`), multiplication (`*`),
and division (`/`). For example `field1 + field2` is an expression which computes the sum of the two fields.

~~~
```dataview
TABLE start, end, (end - start) - dur(8 h) AS "Overtime" 
FROM #work
```

```dataview
TABLE hrs / 24 AS "days"
FROM "30 Projects"
```
~~~

### Comparisons

You can compare most values using the various comparison operators: `<`, `>`, `<=`, `>=`, `=`, `!=`. This yields a
boolean true or false value which can be used in `WHERE` blocks in queries.

~~~
```dataview
LIST
FROM "Games"
WHERE price > 10
```

```dataview
TASK
WHERE due <= date(today)
```

```dataview
LIST
FROM #homework
WHERE status != "done"
```
~~~

!!! hint "Comparing different types"
    Comparing different [data types](../annotation/types-of-metadata.md) with each other can lead to unexpected results. Take the second example: If `due` is not set (neither on page nor task level), it is `null` and `null <= date(today)` returns true, including tasks without any due date. If this is not wanted, add a type check to make sure you're always comparing the same types:
    ~~~
    ```dataview
    TASK
    WHERE typeof(due) = "date" AND due <= date(today)
    ```
    ~~~
    Most often, it is sufficient to check if the meta data is available via `WHERE due AND due <= date(today)`, but checking the type is the safer way to get foreseeable results. 

### List/Object Indexing

You can retrieve data from [lists/arrays](../annotation/types-of-metadata.md#list) via the index operator `list[<index>]`, where `<index>` is any computed expression.
Lists are 0-indexed, so the first element is index 0, the second element is index 1, and so on.
For example `list("A", "B", "C")[0] = "A"`.

A similar notation style works for [objects](../annotation/types-of-metadata.md#object).
You can use `field["nestedfield"]` to reference fields inside an object or otherwise similarly nested.
For example, in the YAML defined below, we can reference `previous` via `episode_metadata["previous"]`.
```yaml
---
aliases:
  - "ABC"
current_episode: "S01E03"
episode_metadata:
  previous: "S01E02"
  next: "S01E04"
---
```

You can also retrieve data from objects (which map text to data values) also using the index operator, where indexes are now strings/text instead of numbers.
You can also use the shorthand `object.<name>`, where `<name>` is the name of the value to retrieve.
For the previous frontmatter example, we could also use `episode_metadata.previous` to obtain the same value.

Index expressions also work on objects which have fields that are not directly supported by the query language.
A good example is `where`, since it is a keyword.
If your frontmatter/metadata contains a field `where`, you can reference it via the `row` syntax: `row["where"]`.
See the [note in the FAQ](../resources/faq.md#how-do-i-use-fields-with-the-same-name-as-keywords-like-from-where) and [the corresponding issue](https://github.com/blacksmithgu/obsidian-dataview/issues/1164) for further information.

~~~
```dataview
TABLE id, episode_metadata.next, aliases[0]
```
~~~

### Function Calls

Dataview supports various functions for manipulating data, which are described in full in the [functions
documentation](functions.md). They have the general syntax `function(arg1, arg2, ...)` - i.e., `lower(file.name)` or
`regexmatch("A.+", file.folder)`.

~~~
```dataview
LIST
WHERE contains(file.name, "WIP")
```

```dataview
LIST
WHERE string(file.day.year) = split(this.file.name, "-W")[0]
```
~~~

### Lambdas

Lambdas are advanced literals which let you define a function that takes some number of inputs, and produces an output.
They have the general form:

```
(arg1, arg2, arg3, ...) => <expression using args>
```

Lambdas are used in several advanced operators like `reduce` and `map` to allow for complex transformations of data. A
few examples:

```
(x) => x.field                  (return field of x, often used for map)
(x, y) => x + y                 (sum x and y)
(x) => 2 * x                    (double x)
(value) => length(value) = 4    (return true if value is length 4)
```

~~~
```dataview
CALENDAR file.day
FLATTEN all(map(file.tasks, (x) => x.completed)) AS "allCompleted"
WHERE !allCompleted
```
~~~

---

## Type-specific Interactions & Values

Most dataview types have special interactions with operators, or have additional fields that can be retrieved using the
index operator. This is true for [dates](../annotation/types-of-metadata.md#date) and [durations](../annotation/types-of-metadata.md#duration) and as well for links. Read more about date and durations on their respective section in [Types of Metadata](../annotation/types-of-metadata.md).

### Links

You can "index through" a link to get values on the corresponding page. For example `[[Assignment Math]].duedate` would get the value
`duedate` from page `Assignment Math`.

!!! note "Link Indexing in Expressions"
    If your link is a field that you defined in an inline field or in front-matter, like `Class:: [[Math]]` and you want to get the field `timetable`, then you
    index into it by writing `Class.timetable`.
    Using `[[Class]].timetable` would look up the page literally called `Class`, and not `Math`!


================================================
FILE: docs/docs/reference/functions.md
================================================
# Functions

Dataview functions provide more advanced ways to manipulate data. You can use functions **in [data commands](../queries/data-commands.md)** (except FROM) to filter or group or use them **as [additional information](../queries/query-types.md)** like TABLE columns or extra output for LIST queries to see your data in a new light.

## How functions work

Functions are another form of [expression](expressions.md) and can be used everywhere you can use an expression. A function always gives you back a new value and follows this format:

```
functionname(parameter1, parameter2)
```

Parameters are again [expressions](expressions.md) and you can use literals, meta data fields, or even another function as parameter. You'll find out which [data type](../annotation/types-of-metadata.md) your parameters need to have on the documentation of this page. Pay attention to the information inside the function brackets. Parameters in square brackets, i.e. `link(path, [display])` means they are *optional* and can be omitted. Find out more about the default behavior of each function on their explanation.

## Calling functions on lists of values

Most functions can be applied either to single values (like `number`, `string`, `date`, etc.) OR to lists of those
values. If a function is applied to a list, it also returns a list after the function is applied to each element
in the list. For example:

```js
lower("YES") = "yes"
lower(["YES", "NO"]) = ["yes", "no"]

replace("yes", "e", "a") = "yas"
replace(["yes", "ree"], "e", "a") = ["yas", "raa"]
```

This so-called "function vectorization" will not be mentioned explicitly on the following definitions and is possible for a wide range of these functionalities implicitly.

## Constructors

Constructors which create values.

### `object(key1, value1, ...)`

Creates a new object with the given keys and values. Keys and values should alternate in the call, and keys should
always be strings/text.

```js
object() => empty object
object("a", 6) => object which maps "a" to 6
object("a", 4, "c", "yes") => object which maps a to 4, and c to "yes"
```

### `list(value1, value2, ...)`

Creates a new list with the given values in it. `array` can be used an alias for `list`.

```js
list() => empty list
list(1, 2, 3) => list with 1, 2, and 3
array("a", "b", "c") => list with "a", "b", and "c"
```

### `date(any)`

Parses a date from the provided string, date, or link object, if possible, returning null otherwise.

```js
date("2020-04-18") = <date object representing April 18th, 2020>
date([[2021-04-16]]) = <date object for the given page, referring to file.day>
```

### `date(text, format)`

Parses a date from text to luxon `DateTime` with the specified format. Note localized formats might not work.
Uses [Luxon tokens](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).

```js
date("12/31/2022", "MM/dd/yyyy") => DateTime for December 31th, 2022
date("210313", "yyMMdd") => DateTime for March 13th, 2021
date("946778645000", "x") => DateTime for "2000-01-02T03:04:05"
```

### `dur(any)`

Parses a duration from the provided string or duration, returning null on failure.

```js
dur(8 minutes) = <8 minutes>
dur("8 minutes, 4 seconds") = <8 minutes, 4 seconds>
dur(dur(8 minutes)) = dur(8 minutes) = <8 minutes>
```

### `number(string)`

Pulls the first number out of the given string, returning it if possible. Returns null if there are no numbers in the
string.

```js
number("18 years") = 18
number(34) = 34
number("hmm") = null
```

### `string(any)`

Converts any value into a "reasonable" string representation. This sometimes produces less pretty results than just directly using
the value in a query - it is mostly useful for coercing dates, durations, numbers, and so on into strings for
manipulation.

```js
string(18) = "18"
string(dur(8 hours)) = "8 hours"
string(date(2021-08-15)) = "August 15th, 2021"
```

### `link(path, [display])`

Construct a link object from the given file path or name. If provided with two arguments, the second argument is the
display name for the link.

```js
link("Hello") => link to page named 'Hello'
link("Hello", "Goodbye") => link to page named 'Hello', displays as 'Goodbye'
```

### `embed(link, [embed?])`

Convert a link object into an embedded link; support for embedded links is somewhat spotty in Dataview views, though
embedding of images should work.

```js
embed(link("Hello.png")) => embedded link to the "Hello.png" image, which will render as an actual image.
```

### `elink(url, [display])`

Construct a link to an external url (like `www.google.com`). If provided with two arguments, the second
argument is the display name for the link.

```js
elink("www.google.com") => link element to google.com
elink("www.google.com", "Google") => link element to google.com, displays as "Google"
```

### `typeof(any)`

Get the type of any object for inspection. Can be used in conjunction with other operators to change behavior based on type.

```js
typeof(8) => "number"
typeof("text") => "string"
typeof([1, 2, 3]) => "array"
typeof({ a: 1, b: 2 }) => "object"
typeof(date(2020-01-01)) => "date"
typeof(dur(8 minutes)) => "duration"
```

---

## Numeric Operations

### `round(number, [digits])`

Round a number to a given number of digits. If the second argument is not specified, rounds to the nearest whole number;
otherwise, rounds to the given number of digits.

```js
round(16.555555) = 17
round(16.555555, 2) = 16.56
```

### `trunc(number)`

Truncates ("cuts off") the decimal point from a number.

```js
trunc(12.937) = 12
trunc(-93.33333) = -93
trunc(-0.837764) = 0
```

### `floor(number)`

Always rounds down and returns the largest integer less than or equal to a given number.
This means that negative numbers become more negative.

```js
floor(12.937) = 12
floor(-93.33333) = -94
floor(-0.837764) = -1
```

### `ceil(number)`

Always rounds up and returns the smallest integer greater than or equal to a given number.
This means negative numbers become less negative.

```js
ceil(12.937) = 13
ceil(-93.33333) = -93
ceil(-0.837764) = 0
```

### `min(a, b, ..)`

Compute the minimum value of a list of arguments, or an array.

```js
min(1, 2, 3) = 1
min([1, 2, 3]) = 1

min("a", "ab", "abc") = "a"
```

### `max(a, b, ...)`

Compute the maximum value of a list of arguments, or an array.

```js
max(1, 2, 3) = 3
max([1, 2, 3]) = 3

max("a", "ab", "abc") = "abc"
```

### `sum(array)`

Sums all numeric values in the array. If you have null values in your sum, you can eliminate them via the `nonnull` function.

```js
sum([1, 2, 3]) = 6
sum([]) = null

sum(nonnull([null, 1, 8])) = 9
```

### `product(array)`

Calculates the product of a list of numbers. If you have null values in your average, you can eliminate them via the `nonnull` function.

```js
product([1,2,3]) = 6
product([]) = null

product(nonnull([null, 1, 2, 4])) = 8
```

### `reduce(array, operand)`

A generic function to reduce a list into a single value, valid operands are `"+"`, `"-"`, `"*"`, `"/"` and the boolean operands `"&"` and `"|"`. Note that using `"+"` and `"*"` equals the `sum()` and `product()` functions, and using `"&"` and `"|"` matches `all()` and `any()`.

```js
reduce([100, 20, 3], "-") = 77
reduce([200, 10, 2], "/") = 10
reduce(values, "*") = Multiplies every element of values, same as product(values)
reduce(values, this.operand) = Applies the local field operand to each of the values
reduce(["⭐", 3], "*") = "⭐⭐⭐", same as "⭐" * 3

reduce([1]), "+") = 1, has the side effect of reducing the list into a single element
```

### `average(array)`

Computes the numeric average of numeric values. If you have null values in your average, you can eliminate them via the
`nonnull` function.

```js
average([1, 2, 3]) = 2
average([]) = null

average(nonnull([null, 1, 2])) = 1.5
```

### `minby(array, function)`

Compute the minimum value of an array, using the provided function.

```js
minby([1, 2, 3], (k) => k) = 1
minby([1, 2, 3], (k) => 0 - k) => 3

minby(this.file.tasks, (k) => k.due) => (earliest due)
```

### `maxby(array, function)`

Compute the maximum value of an array, using the provided function.

```js
maxby([1, 2, 3], (k) => k) = 3
maxby([1, 2, 3], (k) => 0 - k) => 1

maxby(this.file.tasks, (k) => k.due) => (latest due)
```

--

## Objects, Arrays, and String Operations

Operations that manipulate values inside of container objects.

### `contains()` and friends

For a quick summary, here are some examples:

```js
contains("Hello", "Lo") = false
contains("Hello", "lo") = true

icontains("Hello", "Lo") = true
icontains("Hello", "lo") = true

econtains("Hello", "Lo") = false
econtains("Hello", "lo") = true
econtains(["this","is","example"], "ex") = false
econtains(["this","is","example"], "is") = true
```

#### `contains(object|list|string, value)`

Checks if the given container type has the given value in it. This function behave slightly differently based on whether
the first argument is an object, a list, or a string.
This function is case-sensitive.

- For objects, checks if the object has a key with the given name. For example,
    ```
    contains(file, "ctime") = true
    contains(file, "day") = true (if file has a date in its title, false otherwise)
    ```
- For lists, checks if any of the array elements equals the given value. For example,
    ```
    contains(list(1, 2, 3), 3) = true
    contains(list(), 1) = false
    ```
- For strings, checks if the given value is a substring (i.e., inside) the string.
    ```
    contains("hello", "lo") = true
    contains("yes", "no") = false
    ```

#### `icontains(object|list|string, value)`

Case insensitive version of `contains()`.

#### `econtains(object|list|string, value)`

"Exact contains" checks if the exact match is found in the string/list.
This function is case sensitive.

- For strings, it behaves exactly like [`contains()`](#containsobjectliststring-value).
    ```
    econtains("Hello", "Lo") = false
    econtains("Hello", "lo") = true
    ```

- For lists, it checks if the exact word is in the list.
    ```
    econtains(["These", "are", "words"], "word") = false
    econtains(["These", "are", "words"], "words") = true
    ```

- For objects, it checks if the exact key name is present in the object. It does **not** do recursive checks.
    ```
    econtains({key:"value", pairs:"here"}, "here") = false
    econtains({key:"value", pairs:"here"}, "key") = true
    econtains({key:"value", recur:{recurkey: "val"}}, "value") = false
    econtains({key:"value", recur:{recurkey: "val"}}, "Recur") = false
    econtains({key:"value", recur:{recurkey: "val"}}, "recurkey") = false
    ```

### `containsword(list|string, value)`

Checks if `value` has an exact word match in `string` or `list`.
This is case insensitive.
The outputs are different for different types of input, see examples.

- For strings, it checks if the word is present in the given string.
    ```
    containsword("word", "word") = true
    containsword("word", "Word") = true
    containsword("words", "Word") = false
    containsword("Hello there!", "hello") = true
    containsword("Hello there!", "HeLLo") = true
    containsword("Hello there chaps!", "chap") = false
    containsword("Hello there chaps!", "chaps") = true
    ```

- For lists, it returns a list of booleans indicating if the word's exact case insensitive match was found.
    ```
    containsword(["I have no words.", "words"], "Word") = [false, false]
    containsword(["word", "Words"], "Word") = [true, false]
    containsword(["Word", "Words in word"], "WORD") = [true, true]
    ```

### `extract(object, key1, key2, ...)`

Pulls multiple fields out of an object, creating a new object with just those fields.

```
extract(file, "ctime", "mtime") = object("ctime", file.ctime, "mtime", file.mtime)
extract(object("test", 1)) = object()
```

### `sort(list)`

Sorts a list, returning a new list in sorted order.

```
sort(list(3, 2, 1)) = list(1, 2, 3)
sort(list("a", "b", "aa")) = list("a", "aa", "b")
```

### `reverse(list)`

Reverses a list, returning a new list in reversed order.

```
reverse(list(1, 2, 3)) = list(3, 2, 1)
reverse(list("a", "b", "c")) = list("c", "b", "a")
```

### `length(object|array)`

Returns the number of fields in an object, or the number of entries in an array.

```
length([]) = 0
length([1, 2, 3]) = 3
length(object("hello", 1, "goodbye", 2)) = 2
```

### `nonnull(array)`

Return a new array with all null values removed.

```
nonnull([]) = []
nonnull([null, false]) = [false]
nonnull([1, 2, 3]) = [1, 2, 3]
```

### `firstvalue(array)`

Return the first non-null value from the 
Download .txt
gitextract_umn6h50l/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── bug_report_mobile.yml
│   │   ├── config.yml
│   │   ├── documentation.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── documentation.yml
│       └── test.yml
├── .gitignore
├── .prettierrc.json
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── __mocks__/
│   ├── data-import/
│   │   └── web-worker/
│   │       └── import-manager.ts
│   └── obsidian.ts
├── cspell.json
├── docs/
│   ├── .gitignore
│   ├── docs/
│   │   ├── annotation/
│   │   │   ├── add-metadata.md
│   │   │   ├── metadata-pages.md
│   │   │   ├── metadata-tasks.md
│   │   │   └── types-of-metadata.md
│   │   ├── api/
│   │   │   ├── code-examples.md
│   │   │   ├── code-reference.md
│   │   │   ├── data-array.md
│   │   │   └── intro.md
│   │   ├── changelog.md
│   │   ├── friends.md
│   │   ├── index.md
│   │   ├── queries/
│   │   │   ├── data-commands.md
│   │   │   ├── differences-to-sql.md
│   │   │   ├── dql-js-inline.md
│   │   │   ├── query-types.md
│   │   │   └── structure.md
│   │   ├── reference/
│   │   │   ├── expressions.md
│   │   │   ├── functions.md
│   │   │   ├── literals.md
│   │   │   └── sources.md
│   │   └── resources/
│   │       ├── develop-against-dataview.md
│   │       ├── examples.md
│   │       ├── faq.md
│   │       └── resources-and-support.md
│   ├── mkdocs.yml
│   └── overrides/
│       └── main.html
├── jest.config.js
├── manifest-beta.json
├── manifest.json
├── package.json
├── rollup.config.js
├── scripts/
│   ├── beta-release
│   ├── install-built
│   └── release
├── src/
│   ├── api/
│   │   ├── data-array.ts
│   │   ├── extensions.ts
│   │   ├── inline-api.ts
│   │   ├── plugin-api.ts
│   │   └── result.ts
│   ├── data-import/
│   │   ├── common.ts
│   │   ├── csv.ts
│   │   ├── inline-field.ts
│   │   ├── markdown-file.ts
│   │   ├── persister.ts
│   │   └── web-worker/
│   │       ├── import-entry.ts
│   │       ├── import-impl.ts
│   │       └── import-manager.ts
│   ├── data-index/
│   │   ├── index.ts
│   │   ├── resolver.ts
│   │   └── source.ts
│   ├── data-model/
│   │   ├── markdown.ts
│   │   ├── serialized/
│   │   │   └── markdown.ts
│   │   ├── transferable.ts
│   │   └── value.ts
│   ├── expression/
│   │   ├── binaryop.ts
│   │   ├── context.ts
│   │   ├── field.ts
│   │   ├── functions.ts
│   │   └── parse.ts
│   ├── index.ts
│   ├── main.ts
│   ├── query/
│   │   ├── engine.ts
│   │   ├── parse.ts
│   │   └── query.ts
│   ├── settings.ts
│   ├── test/
│   │   ├── api/
│   │   │   └── data-array.test.ts
│   │   ├── common.ts
│   │   ├── data/
│   │   │   ├── index-map.test.ts
│   │   │   ├── transferable.test.ts
│   │   │   └── values.test.ts
│   │   ├── function/
│   │   │   ├── aggregation.test.ts
│   │   │   ├── coerce.test.ts
│   │   │   ├── constructors.test.ts
│   │   │   ├── eval.test.ts
│   │   │   ├── functions.test.ts
│   │   │   ├── meta.test.ts
│   │   │   ├── string.test.ts
│   │   │   └── vectorization.test.ts
│   │   ├── markdown/
│   │   │   └── parse.file.test.ts
│   │   ├── parse/
│   │   │   ├── parse.expression.test.ts
│   │   │   ├── parse.inline.test.ts
│   │   │   └── parse.query.test.ts
│   │   └── util/
│   │       ├── normalize.test.ts
│   │       └── paths.test.ts
│   ├── typings/
│   │   ├── obsidian-ex.d.ts
│   │   └── workers.d.ts
│   ├── ui/
│   │   ├── export/
│   │   │   └── markdown.ts
│   │   ├── lp-render.ts
│   │   ├── markdown.tsx
│   │   ├── refreshable-view.ts
│   │   ├── render.ts
│   │   └── views/
│   │       ├── calendar-view.ts
│   │       ├── inline-field-live-preview.ts
│   │       ├── inline-field.tsx
│   │       ├── inline-view.ts
│   │       ├── js-view.ts
│   │       ├── list-view.tsx
│   │       ├── table-view.tsx
│   │       └── task-view.tsx
│   └── util/
│       ├── hash.ts
│       ├── locale.ts
│       ├── media.ts
│       └── normalize.ts
├── styles.css
├── test-vault/
│   ├── .obsidian/
│   │   └── community-plugins.json
│   ├── Books.md
│   ├── Home.md
│   ├── blog/
│   │   ├── 2020-08-08-an-earlier-post.md
│   │   └── 2021-08-08-a-post.md
│   ├── books/
│   │   ├── Catcher in the Rye.md
│   │   ├── Origin of Species.md
│   │   └── The Great Gatsby.md
│   ├── example calendars.md
│   ├── example lists.md
│   ├── example tables.md
│   ├── recipes/
│   │   ├── pbj.md
│   │   └── toast.md
│   ├── tasks/
│   │   ├── Annotated Tasks.md
│   │   ├── Completed Tasks.md
│   │   ├── Grouped Sorted Tasks.md
│   │   ├── Sorted Tasks.md
│   │   ├── Tasks Completed on specific Date.md
│   │   ├── Tasks in a specific section.md
│   │   ├── Uncompleted Tasks.md
│   │   ├── checklist.md
│   │   └── example tasks.md
│   └── untracked/
│       └── README.md
├── tsconfig-lib.json
├── tsconfig.json
└── versions.json
Download .txt
SYMBOL INDEX (682 symbols across 57 files)

FILE: __mocks__/data-import/web-worker/import-manager.ts
  class FileImporter (line 6) | class FileImporter {
    method constructor (line 7) | public constructor(public numWorkers: number, public vault: Vault, pub...
    method reload (line 9) | public async reload<T>(file: TFile): Promise<T> {

FILE: __mocks__/obsidian.ts
  type FileStats (line 24) | interface FileStats {
  class TFile (line 34) | class TFile extends TAbstractFile {
  class TFolder (line 41) | class TFolder extends TAbstractFile {
    method isRoot (line 44) | isRoot(): boolean {
  class Vault (line 49) | class Vault extends EventEmitter {
    method getFiles (line 50) | getFiles() {
    method trigger (line 53) | trigger(name: string, ...data: any[]): void {
  class Component (line 58) | class Component {
    method registerEvent (line 59) | registerEvent() {}

FILE: rollup.config.js
  constant BASE_CONFIG (line 7) | const BASE_CONFIG = {
  constant DEV_PLUGIN_CONFIG (line 25) | const DEV_PLUGIN_CONFIG = {
  constant PROD_PLUGIN_CONFIG (line 45) | const PROD_PLUGIN_CONFIG = {
  constant LIBRARY_CONFIG (line 58) | const LIBRARY_CONFIG = {

FILE: src/api/data-array.ts
  type ArrayFunc (line 5) | type ArrayFunc<T, O> = (elem: T, index: number, arr: T[]) => O;
  type ArrayComparator (line 8) | type ArrayComparator<T> = (a: T, b: T) => number;
  type LowestKey (line 11) | type LowestKey<T> = T extends { key: any; rows: any } ? LowestKey<T["row...
  type Ingrouped (line 14) | type Ingrouped<U, T> = T extends { key: any; rows: any }
  type DataArray (line 22) | interface DataArray<T> {
  class DataArrayImpl (line 143) | class DataArrayImpl<T> implements DataArray<T> {
    method wrap (line 197) | public static wrap<T>(
    method constructor (line 211) | private constructor(
    method lwrap (line 219) | private lwrap<U>(values: U[]): DataArray<U> {
    method where (line 223) | public where(predicate: ArrayFunc<T, boolean>): DataArray<T> {
    method filter (line 227) | public filter(predicate: ArrayFunc<T, boolean>): DataArray<T> {
    method map (line 231) | public map<U>(f: ArrayFunc<T, U>): DataArray<U> {
    method flatMap (line 235) | public flatMap<U>(f: ArrayFunc<T, U[]>): DataArray<U> {
    method mutate (line 247) | public mutate(f: ArrayFunc<T, void>): DataArray<T> {
    method limit (line 255) | public limit(count: number): DataArray<T> {
    method slice (line 259) | public slice(start?: number, end?: number): DataArray<T> {
    method concat (line 263) | public concat(other: DataArray<T>): DataArray<T> {
    method indexOf (line 268) | public indexOf(element: T, fromIndex?: number): number {
    method find (line 273) | public find(pred: ArrayFunc<T, boolean>): T | undefined {
    method findIndex (line 279) | public findIndex(pred: ArrayFunc<T, boolean>, fromIndex?: number): num...
    method includes (line 287) | public includes(element: T): boolean {
    method join (line 291) | public join(sep?: string): string {
    method sort (line 297) | public sort<U>(key?: ArrayFunc<T, U>, direction?: "asc" | "desc", comp...
    method sortInPlace (line 315) | public sortInPlace<U>(
    method groupBy (line 334) | public groupBy<U>(
    method groupIn (line 363) | public groupIn<U>(key: ArrayFunc<LowestKey<T>, U>, comparator?: ArrayC...
    method distinct (line 376) | public distinct<U>(key?: ArrayFunc<T, U>, comparator?: ArrayComparator...
    method every (line 396) | public every(f: ArrayFunc<T, boolean>): boolean {
    method some (line 400) | public some(f: ArrayFunc<T, boolean>): boolean {
    method none (line 404) | public none(f: ArrayFunc<T, boolean>): boolean {
    method first (line 408) | public first(): T {
    method last (line 411) | public last(): T {
    method to (line 415) | public to(key: string): DataArray<any> {
    method into (line 428) | public into(key: string): DataArray<any> {
    method expand (line 440) | public expand(key: string): DataArray<any> {
    method forEach (line 459) | public forEach(f: ArrayFunc<T, void>) {
    method sum (line 465) | public sum() {
    method avg (line 469) | public avg() {
    method min (line 473) | public min() {
    method max (line 477) | public max() {
    method array (line 481) | public array(): T[] {
    method toString (line 489) | public toString(): string {
  method [Symbol.iterator] (line 485) | public [Symbol.iterator](): Iterator<T> {
  function wrap (line 497) | function wrap<T>(raw: T[] | DataArray<T>, settings: QuerySettings): Data...
  function from (line 503) | function from<T>(raw: Iterable<T>, settings: QuerySettings): DataArray<T> {
  function isDataArray (line 512) | function isDataArray(obj: any): obj is DataArray<any> {

FILE: src/api/extensions.ts
  type TaskStatusSelector (line 4) | type TaskStatusSelector = (task: STask) => Promise<string>;
  class Extension (line 10) | class Extension {
    method constructor (line 14) | public constructor(public plugin: string) {
    method taskStatusSelector (line 19) | public taskStatusSelector(name: string, selector: TaskStatusSelector):...

FILE: src/api/inline-api.ts
  class DataviewInlineIOApi (line 20) | class DataviewInlineIOApi {
    method constructor (line 21) | public constructor(public api: DataviewIOApi, public currentFile: stri...
    method csv (line 24) | public async csv(path: string, originFile?: string): Promise<DataArray...
    method load (line 29) | public async load(path: Link | string, originFile?: string): Promise<s...
    method normalize (line 34) | public normalize(path: Link | string, originFile?: string): string {
  class DataviewInlineApi (line 39) | class DataviewInlineApi {
    method constructor (line 85) | constructor(api: DataviewApi, component: Component, container: HTMLEle...
    method pagePaths (line 111) | public pagePaths(query?: string): DataArray<string> {
    method page (line 116) | public page(path: string | Link): DataObject | undefined {
    method pages (line 121) | public pages(query?: string): DataArray<any> {
    method current (line 126) | public current(): Record<string, any> | undefined {
    method query (line 135) | public async query(
    method tryQuery (line 144) | public async tryQuery(source: string, originFile?: string, settings?: ...
    method queryMarkdown (line 149) | public async queryMarkdown(
    method tryQueryMarkdown (line 158) | public async tryQueryMarkdown(source: string, originFile?: string, set...
    method evaluate (line 177) | public evaluate(expression: string, context?: DataObject): Result<Lite...
    method tryEvaluate (line 185) | public tryEvaluate(expression: string, context?: DataObject): Literal {
    method execute (line 190) | public async execute(source: string) {
    method executeJs (line 195) | public async executeJs(code: string) {
    method array (line 207) | public array(raw: any): DataArray<any> {
    method isArray (line 212) | public isArray(raw: any): raw is DataArray<any> | Array<any> {
    method isDataArray (line 217) | public isDataArray(raw: unknown): raw is DataArray<any> {
    method fileLink (line 222) | public fileLink(path: string, embed: boolean = false, display?: string...
    method sectionLink (line 227) | public sectionLink(path: string, section: string, embed: boolean = fal...
    method blockLink (line 232) | public blockLink(path: string, blockId: string, embed: boolean = false...
    method date (line 237) | public date(pathlike: string | Link | DateTime): DateTime | null {
    method duration (line 242) | public duration(dur: string | Duration): Duration | null {
    method parse (line 247) | public parse(value: string): Literal {
    method literal (line 252) | public literal(value: any): Literal {
    method clone (line 257) | public clone(value: Literal): Literal {
    method compare (line 265) | public compare(a: any, b: any): number {
    method equal (line 270) | public equal(a: any, b: any): boolean {
    method el (line 279) | public el<K extends keyof HTMLElementTagNameMap>(
    method header (line 296) | public header(level: number, text: any, options?: DomElementInfo): HTM...
    method paragraph (line 304) | public paragraph(text: any, options?: DomElementInfo): HTMLParagraphEl...
    method span (line 309) | public span(text: any, options?: DomElementInfo): HTMLSpanElement {
    method view (line 317) | public async view(viewName: string, input: any) {
    method list (line 372) | public list(values?: any[] | DataArray<any>) {
    method table (line 377) | public table(headers: string[], values?: any[][] | DataArray<any>) {
    method taskList (line 382) | public taskList(tasks: Grouping<SListItem>, groupByFile: boolean = tru...
    method markdownTable (line 391) | public markdownTable(
    method markdownList (line 400) | public markdownList(values?: any[] | DataArray<any> | undefined, setti...
    method markdownTaskList (line 405) | public markdownTaskList(values: Grouping<SListItem>, settings?: Partia...
  function evalInContext (line 413) | function evalInContext(script: string, context: any): any {
  function asyncEvalInContext (line 422) | async function asyncEvalInContext(script: string, context: any): Promise...

FILE: src/api/plugin-api.ts
  class DataviewIOApi (line 40) | class DataviewIOApi {
    method constructor (line 41) | public constructor(public api: DataviewApi) {}
    method csv (line 44) | public async csv(path: Link | string, originFile?: string): Promise<Da...
    method load (line 55) | public async load(path: Link | string, originFile?: string): Promise<s...
    method normalize (line 67) | public normalize(path: Link | string, originFile?: string): string {
  class DataviewApi (line 77) | class DataviewApi {
    method constructor (line 91) | public constructor(
    method current (line 110) | get current() {
    method pagePaths (line 123) | public pagePaths(query?: string, originFile?: string): DataArray<strin...
    method page (line 138) | public page(path: string | Link, originFile?: string): Record<string, ...
    method pages (line 154) | public pages(query?: string, originFile?: string): DataArray<Record<st...
    method _addDataArrays (line 162) | private _addDataArrays(pageObject: SMarkdownPage): SMarkdownPage {
    method array (line 179) | public array(raw: unknown): DataArray<any> {
    method isArray (line 186) | public isArray(raw: unknown): raw is DataArray<any> | Array<any> {
    method isDataArray (line 191) | public isDataArray(raw: unknown): raw is DataArray<any> {
    method fileLink (line 196) | public fileLink(path: string, embed: boolean = false, display?: string) {
    method sectionLink (line 201) | public sectionLink(path: string, section: string, embed: boolean = fal...
    method blockLink (line 206) | public blockLink(path: string, blockId: string, embed: boolean = false...
    method date (line 211) | public date(pathlike: string | Link | DateTime): DateTime | null {
    method duration (line 216) | public duration(str: string | Duration): Duration | null {
    method parse (line 221) | public parse(value: string): Literal {
    method literal (line 228) | public literal(value: any): Literal {
    method clone (line 233) | public clone(value: Literal): Literal {
    method compare (line 241) | public compare(a: any, b: any): number {
    method equal (line 246) | public equal(a: any, b: any): boolean {
    method query (line 265) | public async query(
    method tryQuery (line 315) | public async tryQuery(source: string, originFile?: string, settings?: ...
    method queryMarkdown (line 320) | public async queryMarkdown(
    method tryQueryMarkdown (line 341) | public async tryQueryMarkdown(
    method evaluate (line 362) | public evaluate(expression: string, context?: DataObject, originFile?:...
    method tryEvaluate (line 374) | public tryEvaluate(expression: string, context?: DataObject, originFil...
    method evaluateInline (line 379) | public evaluateInline(expression: string, origin: string): Result<Lite...
    method execute (line 398) | public async execute(
    method executeJs (line 455) | public async executeJs(
    method list (line 471) | public async list(
    method table (line 493) | public async table(
    method taskList (line 517) | public async taskList(
    method renderValue (line 539) | public async renderValue(
    method markdownTable (line 554) | public markdownTable(
    method markdownList (line 567) | public markdownList(values: any[] | DataArray<any> | undefined, settin...
    method markdownTaskList (line 575) | public markdownTaskList(values: Grouping<SListItem>, settings?: Partia...
  type TableResult (line 585) | type TableResult = { type: "table"; headers: string[]; values: Literal[]...
  type ListResult (line 587) | type ListResult = { type: "list"; values: Literal[]; primaryMeaning: Ide...
  type TaskResult (line 589) | type TaskResult = { type: "task"; values: Grouping<SListItem> };
  type CalendarResult (line 591) | type CalendarResult = {
  type QueryResult (line 601) | type QueryResult = TableResult | ListResult | TaskResult | CalendarResult;
  type QueryApiSettings (line 604) | type QueryApiSettings = {
  function isDataviewDisabled (line 610) | function isDataviewDisabled(sourcePath: string): boolean {

FILE: src/api/result.ts
  class Success (line 2) | class Success<T, E> {
    method constructor (line 5) | public constructor(public value: T) {
    method map (line 9) | public map<U>(f: (a: T) => U): Result<U, E> {
    method flatMap (line 13) | public flatMap<U>(f: (a: T) => Result<U, E>): Result<U, E> {
    method mapErr (line 17) | public mapErr<U>(f: (e: E) => U): Result<T, U> {
    method bimap (line 21) | public bimap<T2, E2>(succ: (a: T) => T2, _fail: (b: E) => E2): Result<...
    method orElse (line 25) | public orElse(_value: T): T {
    method cast (line 29) | public cast<U>(): Result<U, E> {
    method orElseThrow (line 33) | public orElseThrow(_message?: (e: E) => string): T {
  class Failure (line 39) | class Failure<T, E> {
    method constructor (line 42) | public constructor(public error: E) {
    method map (line 46) | public map<U>(_f: (a: T) => U): Result<U, E> {
    method flatMap (line 50) | public flatMap<U>(_f: (a: T) => Result<U, E>): Result<U, E> {
    method mapErr (line 54) | public mapErr<U>(f: (e: E) => U): Result<T, U> {
    method bimap (line 58) | public bimap<T2, E2>(_succ: (a: T) => T2, fail: (b: E) => E2): Result<...
    method orElse (line 62) | public orElse(value: T): T {
    method cast (line 66) | public cast<U>(): Result<U, E> {
    method orElseThrow (line 70) | public orElseThrow(message?: (e: E) => string): T {
  type Result (line 76) | type Result<T, E> = Success<T, E> | Failure<T, E>;
  function success (line 81) | function success<T, E>(value: T): Result<T, E> {
  function failure (line 86) | function failure<T, E>(error: E): Result<T, E> {
  function flatMap2 (line 91) | function flatMap2<T1, T2, O, E>(
  function map2 (line 105) | function map2<T1, T2, O, E>(

FILE: src/data-import/common.ts
  constant POTENTIAL_TAG_MATCHER (line 5) | const POTENTIAL_TAG_MATCHER = /#[^\s,;\.:!\?'"`()\[\]\{\}]+/giu;
  function extractTags (line 8) | function extractTags(source: string): Set<string> {

FILE: src/data-import/csv.ts
  function parseCsv (line 7) | function parseCsv(content: string): DataObject[] {

FILE: src/data-import/inline-field.ts
  type InlineField (line 9) | interface InlineField {
  constant INLINE_FIELD_WRAPPERS (line 25) | const INLINE_FIELD_WRAPPERS: Readonly<Record<string, string>> = Object.f...
  function findClosing (line 34) | function findClosing(
  function findSeparator (line 70) | function findSeparator(line: string, start: number): { key: string; valu...
  function findSpecificInlineField (line 78) | function findSpecificInlineField(line: string, start: number): InlineFie...
  function parseInlineValue (line 103) | function parseInlineValue(value: string): Literal {
  function extractInlineFields (line 122) | function extractInlineFields(line: string, includeTaskFields: boolean = ...
  constant FULL_LINE_KEY_PART (line 152) | const FULL_LINE_KEY_PART: P.Parser<string> = P.alt(
  constant FULL_LINE_KEY_PARSER (line 159) | const FULL_LINE_KEY_PARSER: P.Parser<string> = P.regexp(/[^0-9\w\p{Lette...
  function extractFullLineField (line 164) | function extractFullLineField(text: string): InlineField | undefined {
  constant CREATED_DATE_REGEX (line 182) | const CREATED_DATE_REGEX = /\u{2795}\s*(\d{4}-\d{2}-\d{2})/u;
  constant DUE_DATE_REGEX (line 183) | const DUE_DATE_REGEX = /(?:\u{1F4C5}|\u{1F4C6}|\u{1F5D3}\u{FE0F}?)\s*(\d...
  constant DONE_DATE_REGEX (line 184) | const DONE_DATE_REGEX = /\u{2705}\s*(\d{4}-\d{2}-\d{2})/u;
  constant SCHEDULED_DATE_REGEX (line 185) | const SCHEDULED_DATE_REGEX = /[\u{23F3}\u{231B}]\s*(\d{4}-\d{2}-\d{2})/u;
  constant START_DATE_REGEX (line 186) | const START_DATE_REGEX = /\u{1F6EB}\s*(\d{4}-\d{2}-\d{2})/u;
  constant EMOJI_REGEXES (line 188) | const EMOJI_REGEXES = [
  function extractSpecialTaskFields (line 197) | function extractSpecialTaskFields(line: string): InlineField[] {
  function setInlineField (line 218) | function setInlineField(source: string, key: string, value?: string): st...
  function setEmojiShorthandCompletionField (line 240) | function setEmojiShorthandCompletionField(source: string, value?: string...

FILE: src/data-import/markdown-file.ts
  function parsePage (line 13) | function parsePage(path: string, contents: string, stat: FileStats, meta...
  function extractTags (line 90) | function extractTags(metadata: FrontMatterCache): string[] {
  function extractAliases (line 100) | function extractAliases(metadata: FrontMatterCache): string[] {
  function splitFrontmatterTagOrAlias (line 116) | function splitFrontmatterTagOrAlias(data: any, on: RegExp): string[] {
  function parseMarkdown (line 134) | function parseMarkdown(
  constant LIST_ITEM_REGEX (line 183) | const LIST_ITEM_REGEX = /^[\s>]*(\d+\.|\d+\)|\*|-|\+)\s*(\[.{0,1}\])?\s*...
  function parseLists (line 189) | function parseLists(
  function findDate (line 308) | function findDate(file: string, fields: Map<string, Literal>): DateTime ...
  function parseFrontmatter (line 327) | function parseFrontmatter(value: any): Literal {
  function addRawInlineField (line 372) | function addRawInlineField(field: InlineField, output: Map<string, Liter...
  function addInlineField (line 377) | function addInlineField(key: string, value: Literal, output: Map<string,...
  function finalizeInlineFields (line 383) | function finalizeInlineFields(fields: Map<string, Literal[]>): Map<strin...
  function mergeFieldGroups (line 410) | function mergeFieldGroups(target: Map<string, Literal[]>, source: Map<st...
  function findPreviousHeader (line 418) | function findPreviousHeader(line: number, headers: HeadingCache[]): stri...

FILE: src/data-import/persister.ts
  type Cached (line 6) | interface Cached<T> {
  class LocalStorageCache (line 16) | class LocalStorageCache {
    method constructor (line 19) | public constructor(public appId: string, public version: string) {
    method recreate (line 28) | public async recreate() {
    method loadFile (line 39) | public async loadFile(path: string): Promise<Cached<Partial<PageMetada...
    method storeFile (line 48) | public async storeFile(path: string, data: Partial<PageMetadata>): Pro...
    method synchronize (line 57) | public async synchronize(existing: string[] | Set<string>): Promise<Se...
    method allKeys (line 68) | public async allKeys(): Promise<string[]> {
    method allFiles (line 73) | public async allFiles(): Promise<string[]> {
    method fileKey (line 78) | public fileKey(path: string): string {

FILE: src/data-import/web-worker/import-entry.ts
  function failableImport (line 7) | function failableImport(path: string, contents: string, stat: FileStats,...

FILE: src/data-import/web-worker/import-impl.ts
  function runImport (line 6) | function runImport(

FILE: src/data-import/web-worker/import-manager.ts
  type FileCallback (line 8) | type FileCallback = (p: any) => void;
  class FileImporter (line 11) | class FileImporter extends Component {
    method constructor (line 24) | public constructor(public numWorkers: number, public vault: Vault, pub...
    method reload (line 47) | public reload<T>(file: TFile): Promise<T> {
    method finish (line 69) | private finish(path: string, data: any, index: number) {
    method send (line 93) | private send(file: TFile, workerId: number) {
    method nextAvailableWorker (line 107) | private nextAvailableWorker(): number | undefined {

FILE: src/data-index/index.ts
  class FullIndex (line 13) | class FullIndex extends Component {
    method create (line 15) | public static create(app: App, indexVersion: string, onChange: () => v...
    method constructor (line 56) | private constructor(public app: App, public indexVersion: string, publ...
    method trigger (line 84) | private trigger(...args: any[]): void {
    method touch (line 89) | public touch() {
    method initialize (line 95) | public initialize() {
    method reinitialize (line 123) | public async reinitialize() {
    method _initialize (line 135) | private async _initialize(files: TFile[]) {
    method rename (line 166) | public rename(file: TAbstractFile, oldPath: string) {
    method reload (line 187) | public async reload(file: TFile): Promise<{ cached: boolean; skipped: ...
    method import (line 216) | private async import(file: TFile): Promise<void> {
    method finish (line 224) | private finish(file: TFile, parsed: Partial<PageMetadata>) {
  class PrefixIndex (line 242) | class PrefixIndex extends Component {
    method create (line 243) | public static create(vault: Vault, updateRevision: () => void): Prefix...
    method constructor (line 247) | constructor(public vault: Vault, public updateRevision: () => void) {
    method walk (line 251) | private *walk(folder: TFolder, filter?: (path: string) => boolean): Ge...
    method get (line 262) | public get(prefix: string, filter?: (path: string) => boolean): Set<st...
    method pathExists (line 268) | public pathExists(path: string): boolean {
    method nodeExists (line 273) | public nodeExists(prefix: string): boolean {
    method resolveRelative (line 280) | public resolveRelative(path: string, origin?: string): string {
  function csv (line 292) | function csv(path: string): boolean {
  function markdown (line 296) | function markdown(path: string): boolean {
  class CsvCache (line 306) | class CsvCache extends Component {
    method constructor (line 314) | public constructor(public vault: Vault) {
    method get (line 334) | public async get(path: string): Promise<Result<DataObject[], string>> {
    method loadInternal (line 348) | private async loadInternal(path: string): Promise<Result<DataObject[],...
    method clearOldEntries (line 374) | private clearOldEntries() {
  type StarredEntry (line 386) | type StarredEntry =
  class StarredCache (line 393) | class StarredCache extends Component {
    method constructor (line 402) | public constructor(public app: App, public onUpdate: () => void) {
    method starred (line 413) | public starred(path: string): boolean {
    method reload (line 417) | private reload() {
    method fetch (line 426) | private static fetch(app: App): Set<string> {
  class IndexMap (line 453) | class IndexMap {
    method constructor (line 460) | public constructor() {
    method get (line 466) | public get(key: string): Set<string> {
    method getInverse (line 476) | public getInverse(value: string): Readonly<Set<string>> {
    method set (line 481) | public set(key: string, values: Set<string>): this {
    method delete (line 503) | public delete(key: string): boolean {
    method rename (line 516) | public rename(oldKey: string, newKey: string): boolean {
    method clear (line 526) | public clear() {
  class ValueCaseInsensitiveIndexMap (line 535) | class ValueCaseInsensitiveIndexMap {
    method constructor (line 537) | public constructor(public delegate: IndexMap = new IndexMap()) {}
    method get (line 540) | public get(key: string): Set<string> {
    method getInverse (line 545) | public getInverse(value: string): Readonly<Set<string>> {
    method set (line 550) | public set(key: string, values: Set<string>): this {
    method delete (line 556) | public delete(key: string): boolean {
    method rename (line 561) | public rename(oldKey: string, newKey: string): boolean {
    method clear (line 566) | public clear() {

FILE: src/data-index/resolver.ts
  type Datarow (line 9) | type Datarow<T> = { id: Literal; data: T };
  function matchingSourcePaths (line 12) | function matchingSourcePaths(
  function resolvePathData (line 94) | async function resolvePathData(path: string, index: FullIndex): Promise<...
  function resolveCsvData (line 101) | async function resolveCsvData(path: string, index: FullIndex): Promise<R...
  function resolveMarkdownData (line 114) | function resolveMarkdownData(path: string, index: FullIndex): Result<Dat...
  function resolveSource (line 127) | async function resolveSource(

FILE: src/data-index/source.ts
  type Source (line 4) | type Source = TagSource | CsvSource | FolderSource | LinkSource | EmptyS...
  type SourceOp (line 6) | type SourceOp = "&" | "|";
  type TagSource (line 9) | interface TagSource {
  type CsvSource (line 16) | interface CsvSource {
  type FolderSource (line 23) | interface FolderSource {
  type LinkSource (line 30) | interface LinkSource {
  type NegatedSource (line 42) | interface NegatedSource {
  type EmptySource (line 49) | interface EmptySource {
  type BinaryOpSource (line 54) | interface BinaryOpSource {
  function tag (line 64) | function tag(tag: string): TagSource {
  function csv (line 69) | function csv(path: string): CsvSource {
  function folder (line 74) | function folder(prefix: string): FolderSource {
  function link (line 79) | function link(file: string, incoming: boolean): LinkSource {
  function binaryOp (line 84) | function binaryOp(left: Source, op: SourceOp, right: Source): Source {
  function and (line 89) | function and(left: Source, right: Source): Source {
  function or (line 94) | function or(left: Source, right: Source): Source {
  function negate (line 99) | function negate(child: Source): NegatedSource {
  function empty (line 103) | function empty(): EmptySource {

FILE: src/data-model/markdown.ts
  class PageMetadata (line 10) | class PageMetadata {
    method constructor (line 36) | public constructor(path: string, init?: Partial<PageMetadata>) {
    method canonicalize (line 50) | public static canonicalize(data: Partial<PageMetadata>, linkNormalizer...
    method name (line 89) | public name(): string {
    method folder (line 94) | public folder(): string {
    method extension (line 99) | public extension(): string {
    method fullTags (line 104) | public fullTags(): Set<string> {
    method fileLinks (line 114) | public fileLinks(): Link[] {
    method serialize (line 122) | public serialize(index: FullIndex, cache?: ListSerializationCache): SM...
  class ListItem (line 164) | class ListItem {
    method constructor (line 205) | public constructor(init?: Partial<ListItem>) {
    method id (line 214) | public id(): string {
    method file (line 218) | public file(): Link {
    method markdown (line 222) | public markdown(): string {
    method created (line 227) | public created(): Literal | undefined {
    method due (line 231) | public due(): Literal | undefined {
    method completed (line 235) | public completed(): Literal | undefined {
    method start (line 242) | public start(): Literal | undefined {
    method scheduled (line 246) | public scheduled(): Literal | undefined {
    method serialize (line 251) | public serialize(cache: ListSerializationCache): SListItem {
  class ListSerializationCache (line 309) | class ListSerializationCache {
    method constructor (line 314) | public constructor(listItems: ListItem[]) {
    method get (line 322) | public get(lineno: number): SListItem | undefined {
  function addFields (line 340) | function addFields(fields: Map<string, Literal[]>, target: DataObject): ...

FILE: src/data-model/serialized/markdown.ts
  type SMarkdownPage (line 7) | interface SMarkdownPage {
  type SListItem (line 40) | type SListItem = SListEntry | STask;
  type SListItemBase (line 43) | interface SListItemBase {
  type SListEntry (line 95) | interface SListEntry extends SListItemBase {
  type STask (line 100) | interface STask extends SListItemBase {

FILE: src/data-model/transferable.ts
  function transferable (line 7) | function transferable(value: any): any {
  function value (line 50) | function value(transferable: any): any {

FILE: src/data-model/value.ts
  type DataObject (line 6) | type DataObject = { [key: string]: Literal };
  type LiteralType (line 8) | type LiteralType =
  type Literal (line 22) | type Literal =
  type GroupElement (line 37) | type GroupElement<T> = { key: Literal; rows: Grouping<T> };
  type Grouping (line 38) | type Grouping<T> = T[] | GroupElement<T>[];
  type LiteralRepr (line 41) | type LiteralRepr<T extends LiteralType> = T extends "boolean"
  type WrappedLiteral (line 68) | type WrappedLiteral =
  type LiteralWrapper (line 82) | interface LiteralWrapper<T extends LiteralType> {
  function toString (line 89) | function toString(
  function wrapValue (line 139) | function wrapValue(val: Literal): WrappedLiteral | undefined {
  function mapLeaves (line 156) | function mapLeaves(val: Literal, func: (t: Literal) => Literal): Literal {
  function compareValue (line 171) | function compareValue(val1: Literal, val2: Literal, linkNormalizer?: (li...
  function typeOf (line 268) | function typeOf(val: any): LiteralType | undefined {
  function isTruthy (line 273) | function isTruthy(field: Literal): boolean {
  function deepCopy (line 304) | function deepCopy<T extends Literal>(field: T): T {
  function isString (line 318) | function isString(val: any): val is string {
  function isNumber (line 322) | function isNumber(val: any): val is number {
  function isDate (line 326) | function isDate(val: any): val is DateTime {
  function isDuration (line 330) | function isDuration(val: any): val is Duration {
  function isNull (line 334) | function isNull(val: any): val is null | undefined {
  function isArray (line 338) | function isArray(val: any): val is any[] {
  function isBoolean (line 342) | function isBoolean(val: any): val is boolean {
  function isLink (line 346) | function isLink(val: any): val is Link {
  function isWidget (line 350) | function isWidget(val: any): val is Widget {
  function isHtml (line 354) | function isHtml(val: any): val is HTMLElement {
  function isObject (line 363) | function isObject(val: any): val is Record<string, any> {
  function isFunction (line 377) | function isFunction(val: any): val is Function {
  function isElementGroup (line 388) | function isElementGroup<T>(entry: T | GroupElement<T>): entry is GroupEl...
  function isGrouping (line 393) | function isGrouping<T>(entry: Grouping<T>): entry is GroupElement<T>[] {
  function count (line 400) | function count<T>(elements: Grouping<T>): number {
  class Link (line 416) | class Link {
    method file (line 429) | public static file(path: string, embed: boolean = false, display?: str...
    method infer (line 439) | public static infer(linkpath: string, embed: boolean = false, display?...
    method header (line 450) | public static header(path: string, header: string, embed?: boolean, di...
    method block (line 462) | public static block(path: string, blockId: string, embed?: boolean, di...
    method fromObject (line 472) | public static fromObject(object: Record<string, any>) {
    method constructor (line 476) | private constructor(fields: Partial<Link>) {
    method equals (line 481) | public equals(other: Link): boolean {
    method toString (line 488) | public toString(): string {
    method toObject (line 493) | public toObject(): Record<string, any> {
    method withPath (line 499) | public withPath(path: string) {
    method withDisplay (line 504) | public withDisplay(display?: string) {
    method withHeader (line 509) | public withHeader(header: string) {
    method toFile (line 514) | public toFile() {
    method toEmbed (line 519) | public toEmbed(): Link {
    method fromEmbed (line 530) | public fromEmbed(): Link {
    method markdown (line 541) | public markdown(): string {
    method obsidianLink (line 556) | public obsidianLink(): string {
    method fileName (line 564) | public fileName(): string {
  method constructor (line 579) | public constructor(public $widget: string) {}
  class ListPairWidget (line 591) | class ListPairWidget extends Widget {
    method constructor (line 592) | public constructor(public key: Literal, public value: Literal) {
    method markdown (line 596) | public override markdown(): string {
  class ExternalLinkWidget (line 602) | class ExternalLinkWidget extends Widget {
    method constructor (line 603) | public constructor(public url: string, public display?: string) {
    method markdown (line 607) | public override markdown(): string {
  function listPair (line 614) | function listPair(key: Literal, value: Literal): ListPairWidget {
  function externalLink (line 619) | function externalLink(url: string, display?: string): ExternalLinkWidget {
  function isListPair (line 624) | function isListPair(widget: Widget): widget is ListPairWidget {
  function isExternalLink (line 628) | function isExternalLink(widget: Widget): widget is ExternalLinkWidget {
  function isBuiltin (line 633) | function isBuiltin(widget: Widget): boolean {

FILE: src/expression/binaryop.ts
  type LiteralTypeOrAll (line 9) | type LiteralTypeOrAll = LiteralType | "*";
  type LiteralReprAll (line 12) | type LiteralReprAll<T extends LiteralTypeOrAll> = T extends "*"
  type BinaryOpImpl (line 19) | type BinaryOpImpl<A extends Literal, B extends Literal> = (first: A, sec...
  type CompareImpl (line 21) | type CompareImpl<T extends Literal> = (first: T, second: T, ctx: Context...
  class BinaryOpHandler (line 24) | class BinaryOpHandler {
    method create (line 27) | public static create() {
    method constructor (line 31) | public constructor() {
    method register (line 35) | public register<T extends LiteralTypeOrAll, U extends LiteralTypeOrAll>(
    method registerComm (line 45) | public registerComm<T extends LiteralTypeOrAll, U extends LiteralTypeO...
    method compare (line 55) | public compare<T extends LiteralTypeOrAll>(type: T, compare: CompareIm...
    method evaluate (line 65) | public evaluate(op: BinaryOp, left: Literal, right: Literal, ctx: Cont...
    method repr (line 90) | public static repr(op: BinaryOp, left: LiteralTypeOrAll, right: Litera...
  function createBinaryOps (line 96) | function createBinaryOps(linkNormalizer: (x: string) => string): BinaryO...

FILE: src/expression/context.ts
  type LinkHandler (line 11) | interface LinkHandler {
  class Context (line 27) | class Context {
    method constructor (line 32) | public constructor(
    method set (line 41) | public set(name: string, value: Literal): Context {
    method get (line 47) | public get(name: string): Literal {
    method tryEvaluate (line 52) | public tryEvaluate(field: Field, data: Record<string, Literal> = {}): ...
    method evaluate (line 57) | public evaluate(field: Field, data: Record<string, Literal> = {}): Res...

FILE: src/expression/field.ts
  type CompareOp (line 5) | type CompareOp = ">" | ">=" | "<=" | "<" | "=" | "!=";
  type ArithmeticOp (line 7) | type ArithmeticOp = "+" | "-" | "*" | "/" | "%" | "&" | "|";
  type BinaryOp (line 9) | type BinaryOp = CompareOp | ArithmeticOp;
  type Field (line 11) | type Field =
  type LiteralField (line 23) | interface LiteralField {
  type VariableField (line 29) | interface VariableField {
  type ListField (line 35) | interface ListField {
  type ObjectField (line 41) | interface ObjectField {
  type BinaryOpField (line 47) | interface BinaryOpField {
  type FunctionField (line 55) | interface FunctionField {
  type LambdaField (line 63) | interface LambdaField {
  type IndexField (line 72) | interface IndexField {
  type NegatedField (line 81) | interface NegatedField {
  function variable (line 89) | function variable(name: string): VariableField {
  function literal (line 93) | function literal(value: Literal): LiteralField {
  function binaryOp (line 97) | function binaryOp(left: Field, op: BinaryOp, right: Field): Field {
  function index (line 101) | function index(obj: Field, index: Field): IndexField {
  function indexVariable (line 106) | function indexVariable(name: string): Field {
  function lambda (line 116) | function lambda(args: string[], value: Field): LambdaField {
  function func (line 120) | function func(func: Field, args: Field[]): FunctionField {
  function list (line 124) | function list(values: Field[]): ListField {
  function object (line 128) | function object(values: Record<string, Field>): ObjectField {
  function negate (line 132) | function negate(child: Field): NegatedField {
  function isCompareOp (line 136) | function isCompareOp(op: BinaryOp): op is CompareOp {

FILE: src/expression/functions.ts
  type FunctionImpl (line 18) | type FunctionImpl = (context: Context, ...rest: Literal[]) => Literal;
  type BoundFunctionImpl (line 20) | type BoundFunctionImpl = (...args: Literal[]) => Literal;
  type FunctionVariant (line 23) | interface FunctionVariant {
  class FunctionBuilder (line 34) | class FunctionBuilder {
    method constructor (line 38) | public constructor(public name: string) {
    method vararg (line 44) | public vararg(impl: FunctionImpl): FunctionBuilder {
    method add1 (line 50) | public add1<T extends LiteralTypeOrAll>(
    method add2 (line 63) | public add2<T extends LiteralTypeOrAll, U extends LiteralTypeOrAll>(
    method add3 (line 77) | public add3<T extends LiteralTypeOrAll, U extends LiteralTypeOrAll, V ...
    method vectorize (line 93) | public vectorize(numArgs: number, positions: number[]): FunctionBuilder {
    method build (line 99) | public build(): FunctionImpl {
  function bind (line 159) | function bind(func: FunctionImpl, context: Context): BoundFunctionImpl {
  function bindAll (line 164) | function bindAll(funcs: Record<string, FunctionImpl>, context: Context):...
  constant DEFAULT_FUNCTIONS (line 895) | const DEFAULT_FUNCTIONS: Record<string, FunctionImpl> = {

FILE: src/expression/parse.ts
  constant EMOJI_REGEX (line 11) | const EMOJI_REGEX = new RegExp(emojiRegex(), "");
  constant DURATION_TYPES (line 14) | const DURATION_TYPES = {
  constant DATE_SHORTHANDS (line 55) | const DATE_SHORTHANDS = {
  constant KEYWORDS (line 84) | const KEYWORDS = ["FROM", "WHERE", "LIMIT", "GROUP", "FLATTEN"];
  function splitOnUnescapedPipe (line 91) | function splitOnUnescapedPipe(link: string): [string, string | undefined] {
  function parseInnerLink (line 102) | function parseInnerLink(rawlink: string): Link {
  function createBinaryParser (line 108) | function createBinaryParser<T, U>(
  function chainOpt (line 124) | function chainOpt<T>(base: P.Parser<T>, ...funcs: ((r: T) => P.Parser<T>...
  type PostfixFragment (line 146) | type PostfixFragment =
  type ExpressionLanguage (line 151) | interface ExpressionLanguage {
  constant EXPRESSION (line 222) | const EXPRESSION = P.createLanguage<ExpressionLanguage>({
  function parseField (line 589) | function parseField(text: string): Result<Field, string> {

FILE: src/main.ts
  class DataviewPlugin (line 33) | class DataviewPlugin extends Plugin {
    method onload (line 45) | async onload() {
    method registerDataviewjsCodeHighlighting (line 169) | public registerDataviewjsCodeHighlighting(): void {
    method unregisterDataviewjsCodeHighlighting (line 175) | public unregisterDataviewjsCodeHighlighting(): void {
    method updateRefreshSettings (line 183) | private updateRefreshSettings() {
    method onunload (line 191) | public onunload() {
    method registerPriorityMarkdownPostProcessor (line 196) | public registerPriorityMarkdownPostProcessor(
    method registerPriorityCodeblockPostProcessor (line 205) | public registerPriorityCodeblockPostProcessor(
    method updateEditorExtensions (line 214) | public updateEditorExtensions() {
    method dataview (line 230) | public async dataview(
    method dataviewjs (line 241) | public async dataviewjs(
    method dataviewInline (line 252) | public async dataviewInline(
    method updateSettings (line 306) | async updateSettings(settings: Partial<DataviewSettings>) {
    method withApi (line 313) | public withApi(callback: (api: DataviewApi) => void) {
    method localApi (line 321) | public localApi(path: string, component: Component, el: HTMLElement): ...
  class GeneralSettingsTab (line 327) | class GeneralSettingsTab extends PluginSettingTab {
    method constructor (line 328) | constructor(app: App, private plugin: DataviewPlugin) {
    method display (line 332) | public display(): void {

FILE: src/query/engine.ts
  function iden (line 15) | function iden<T>(x: T): T {
  type OperationDiagnostics (line 20) | interface OperationDiagnostics {
  type IdentifierMeaning (line 28) | type IdentifierMeaning = { type: "group"; name: string; on: IdentifierMe...
  type Pagerow (line 31) | type Pagerow = Datarow<DataObject>;
  type ExecutionError (line 33) | type ExecutionError = { index: number; message: string };
  type CoreExecution (line 36) | interface CoreExecution {
  function executeCore (line 45) | function executeCore(rows: Pagerow[], context: Context, ops: QueryOperat...
  function executeCoreExtract (line 224) | function executeCoreExtract(
  type ListExecution (line 280) | interface ListExecution {
  function executeList (line 287) | async function executeList(
  type TableExecution (line 321) | interface TableExecution {
  function executeTable (line 329) | async function executeTable(
  type TaskExecution (line 366) | interface TaskExecution {
  function extractTaskGroupings (line 372) | function extractTaskGroupings(id: IdentifierMeaning, rows: DataObject[])...
  function executeTask (line 388) | async function executeTask(
  function executeInline (line 436) | function executeInline(
  function defaultLinkHandler (line 448) | function defaultLinkHandler(index: FullIndex, origin: string): LinkHandl...
  function executeCalendar (line 471) | async function executeCalendar(
  type CalendarExecution (line 504) | interface CalendarExecution {

FILE: src/query/parse.ts
  type QueryLanguageTypes (line 27) | interface QueryLanguageTypes {
  function captureRaw (line 48) | function captureRaw<T>(base: P.Parser<T>): P.Parser<[T, string]> {
  function stripNewlines (line 60) | function stripNewlines(text: string): string {
  function precededByWhitespaceIfNotEof (line 69) | function precededByWhitespaceIfNotEof<T>(if_eof: (_: undefined) => T, pa...
  constant QUERY_LANGUAGE (line 74) | const QUERY_LANGUAGE = P.createLanguage<QueryLanguageTypes>({
  function parseQuery (line 225) | function parseQuery(text: string): Result<Query, string> {

FILE: src/query/query.ts
  type QueryType (line 6) | type QueryType = "list" | "table" | "task" | "calendar";
  type Comment (line 9) | type Comment = string;
  type NamedField (line 12) | interface NamedField {
  type QuerySortBy (line 20) | interface QuerySortBy {
  function named (line 29) | function named(name: string, field: Field): NamedField {
  function sortBy (line 33) | function sortBy(field: Field, dir: "ascending" | "descending"): QuerySor...
  type ListQuery (line 43) | interface ListQuery {
  type TableQuery (line 52) | interface TableQuery {
  type TaskQuery (line 61) | interface TaskQuery {
  type CalendarQuery (line 66) | interface CalendarQuery {
  type QueryHeader (line 72) | type QueryHeader = ListQuery | TableQuery | TaskQuery | CalendarQuery;
  type WhereStep (line 75) | interface WhereStep {
  type SortByStep (line 81) | interface SortByStep {
  type LimitStep (line 87) | interface LimitStep {
  type FlattenStep (line 93) | interface FlattenStep {
  type GroupStep (line 99) | interface GroupStep {
  type ExtractStep (line 105) | interface ExtractStep {
  type QueryOperation (line 110) | type QueryOperation = WhereStep | SortByStep | LimitStep | FlattenStep |...
  type Query (line 115) | interface Query {

FILE: src/settings.ts
  type QuerySettings (line 5) | interface QuerySettings {
  constant DEFAULT_QUERY_SETTINGS (line 38) | const DEFAULT_QUERY_SETTINGS: QuerySettings = {
  type ExportSettings (line 61) | interface ExportSettings {
  constant DEFAULT_EXPORT_SETTINGS (line 66) | const DEFAULT_EXPORT_SETTINGS: ExportSettings = {
  type DataviewSettings (line 74) | interface DataviewSettings extends QuerySettings, ExportSettings {
  constant DEFAULT_SETTINGS (line 96) | const DEFAULT_SETTINGS: DataviewSettings = {

FILE: src/test/api/data-array.test.ts
  function da (line 203) | function da<T>(val: T[]): DataArray<T> {

FILE: src/test/common.ts
  function expectEvals (line 7) | function expectEvals(text: string, result: Literal) {
  function parseEval (line 12) | function parseEval(text: string): Literal {
  function simpleLinkHandler (line 18) | function simpleLinkHandler(): LinkHandler {
  function simpleContext (line 27) | function simpleContext(): Context {

FILE: src/test/data/transferable.test.ts
  function roundTrip (line 22) | function roundTrip<T>(value: T): T {
  function checkRoundTrip (line 26) | function checkRoundTrip(value: any) {

FILE: src/test/function/eval.test.ts
  function parseEval (line 101) | function parseEval(text: string): Literal {
  function simpleLinkHandler (line 107) | function simpleLinkHandler(): LinkHandler {
  function simpleContext (line 116) | function simpleContext(): Context {

FILE: src/test/function/vectorization.test.ts
  function check (line 18) | function check(statement: string, result: Literal) {

FILE: src/test/parse/parse.query.test.ts
  function testQueryTypeAlone (line 7) | function testQueryTypeAlone(name: string) {

FILE: src/typings/obsidian-ex.d.ts
  type MetadataCache (line 6) | interface MetadataCache {
  type App (line 11) | interface App {
  type Workspace (line 23) | interface Workspace {
  type Editor (line 28) | interface Editor {
  type Window (line 37) | interface Window {

FILE: src/ui/export/markdown.ts
  function markdownTable (line 11) | function markdownTable(
  function tableLiteral (line 52) | function tableLiteral(value: Literal, allowHtml: boolean = true, setting...
  function rawTableLiteral (line 57) | function rawTableLiteral(value: Literal, allowHtml: boolean = true, sett...
  function padright (line 80) | function padright(text: string, padding: string, length: number): string {
  function escapeTable (line 86) | function escapeTable(text: string): string {
  function markdownList (line 95) | function markdownList(values: Literal[], settings?: QuerySettings & Expo...
  function markdownListRec (line 100) | function markdownListRec(input: Literal, settings?: QuerySettings & Expo...
  function markdownTaskList (line 132) | function markdownTaskList(

FILE: src/ui/lp-render.ts
  function selectionAndRangeOverlap (line 45) | function selectionAndRangeOverlap(selection: EditorSelection, rangeFrom:...
  class InlineWidget (line 55) | class InlineWidget extends WidgetType {
    method constructor (line 56) | constructor(
    method eq (line 67) | eq(other: InlineWidget): boolean {
    method toDOM (line 84) | toDOM(view: EditorView): HTMLElement {
    method ignoreEvent (line 94) | ignoreEvent(event: MouseEvent | Event): boolean {
  function getCssClasses (line 113) | function getCssClasses(props: Set<string>): string[] {
  function inlinePlugin (line 133) | function inlinePlugin(app: App, index: FullIndex, settings: DataviewSett...

FILE: src/ui/markdown.tsx
  type MarkdownProps (line 15) | type MarkdownProps = { contents: string; sourcePath: string };
  type MarkdownContext (line 16) | type MarkdownContext = { component: Component };
  type DataviewInit (line 19) | type DataviewInit = {
  type DataviewContexts (line 27) | type DataviewContexts = DataviewInit & {
  function RawMarkdown (line 34) | function RawMarkdown({
  function RawEmbedHtml (line 76) | function RawEmbedHtml({ element }: { element: HTMLElement }) {
  function RawLit (line 92) | function RawLit({
  function ErrorPre (line 222) | function ErrorPre(props: { children: ComponentChildren }, {}) {
  function ErrorMessage (line 227) | function ErrorMessage({ message }: { message: string }) {
  function useIndexBackedState (line 238) | function useIndexBackedState<T>(
  class ReactRenderer (line 282) | class ReactRenderer extends MarkdownRenderChild {
    method constructor (line 283) | public constructor(public init: DataviewInit, public element: h.JSX.El...
    method onload (line 287) | public onload(): void {
    method onunload (line 292) | public onunload(): void {

FILE: src/ui/refreshable-view.ts
  method constructor (line 9) | public constructor(
  method onload (line 21) | onload() {

FILE: src/ui/render.ts
  function renderCompactMarkdown (line 9) | async function renderCompactMarkdown(
  function renderCompactMarkdownForInlineFieldLivePreview (line 34) | async function renderCompactMarkdownForInlineFieldLivePreview(
  function renderErrorPre (line 56) | function renderErrorPre(container: HTMLElement, error: string): HTMLElem...
  function renderCodeBlock (line 63) | function renderCodeBlock(container: HTMLElement, source: string, languag...
  type ValueRenderContext (line 70) | type ValueRenderContext = "root" | "list";
  function renderValue (line 73) | async function renderValue(

FILE: src/ui/views/calendar-view.ts
  type CalendarFile (line 15) | interface CalendarFile extends IDot {
  class DataviewCalendarRenderer (line 19) | class DataviewCalendarRenderer extends DataviewRefreshableRenderer {
    method constructor (line 21) | constructor(
    method render (line 32) | async render() {
    method onClose (line 106) | onClose(): Promise<void> {

FILE: src/ui/views/inline-field-live-preview.ts
  class InlineFieldValue (line 19) | class InlineFieldValue extends RangeValue {
    method constructor (line 20) | constructor(public field: InlineField) {
    method eq (line 24) | eq(other: InlineFieldValue): boolean {
  function buildInlineFields (line 29) | function buildInlineFields(state: EditorState): RangeSet<InlineFieldValu...
  method update (line 60) | update(oldFields, tr) {
  method constructor (line 72) | constructor(view: EditorView) {
  method destroy (line 78) | destroy() {
  method buildDecorations (line 82) | buildDecorations(view: EditorView): DecorationSet {
  method update (line 117) | update(update: ViewUpdate) {
  method updateDecorations (line 136) | updateDecorations(view: EditorView) {
  method removeDeco (line 159) | removeDeco(start: number, end: number) {
  method addDeco (line 169) | addDeco(start: number, end: number, field: InlineField, file: TFile, vie...
  class InlineFieldWidget (line 202) | class InlineFieldWidget extends WidgetType {
    method constructor (line 203) | constructor(
    method eq (line 214) | eq(other: InlineFieldWidget): boolean {
    method toDOM (line 218) | toDOM() {
    method addKeyClickHandler (line 288) | addKeyClickHandler(key: HTMLElement, renderContainer: HTMLElement) {
    method addValueClickHandler (line 300) | addValueClickHandler(value: HTMLElement, renderContainer: HTMLElement) {

FILE: src/ui/views/inline-field.tsx
  function replaceInlineFields (line 8) | async function replaceInlineFields(ctx: MarkdownPostProcessorContext, in...

FILE: src/ui/views/inline-view.ts
  class DataviewInlineRenderer (line 11) | class DataviewInlineRenderer extends DataviewRefreshableRenderer {
    method constructor (line 15) | constructor(
    method render (line 28) | async render() {

FILE: src/ui/views/js-view.ts
  class DataviewJSRenderer (line 6) | class DataviewJSRenderer extends DataviewRefreshableRenderer {
    method constructor (line 9) | constructor(public api: DataviewApi, public script: string, public con...
    method render (line 13) | async render() {
  class DataviewInlineJSRenderer (line 38) | class DataviewInlineJSRenderer extends DataviewRefreshableRenderer {
    method constructor (line 44) | constructor(
    method render (line 54) | async render() {

FILE: src/ui/views/list-view.tsx
  function ListGrouping (line 18) | function ListGrouping({ items, sourcePath }: { items: Literal[]; sourceP...
  type ListViewState (line 30) | type ListViewState =
  function ListView (line 36) | function ListView({ query, sourcePath }: { query: Query; sourcePath: str...
  function createListView (line 75) | function createListView(init: DataviewInit, query: Query, sourcePath: st...
  function createFixedListView (line 79) | function createFixedListView(init: DataviewInit, elements: Literal[], so...

FILE: src/ui/views/table-view.tsx
  function ResultCount (line 20) | function ResultCount(props: { length: number }) {
  function TableGrouping (line 26) | function TableGrouping({
  type TableViewState (line 69) | type TableViewState =
  function TableView (line 75) | function TableView({ query, sourcePath }: { query: Query; sourcePath: st...
  function createTableView (line 110) | function createTableView(init: DataviewInit, query: Query, sourcePath: s...
  function createFixedTableView (line 114) | function createFixedTableView(

FILE: src/ui/views/task-view.tsx
  function wasLinkPressed (line 24) | function wasLinkPressed(evt: preact.JSX.TargetedMouseEvent<HTMLElement>)...
  function TaskItem (line 29) | function TaskItem({ item }: { item: STask }) {
  function ListItem (line 113) | function ListItem({ item }: { item: SListEntry }) {
  function TaskList (line 151) | function TaskList({ items }: { items: SListItem[] }) {
  function ResultCount (line 167) | function ResultCount(props: { item: SListEntry | STask | GroupElement<SL...
  function TaskGrouping (line 177) | function TaskGrouping({ items, sourcePath }: { items: Grouping<SListItem...
  type TaskViewState (line 199) | type TaskViewState =
  function TaskView (line 208) | function TaskView({ query, sourcePath }: { query: Query; sourcePath: str...
  function createTaskView (line 246) | function createTaskView(init: DataviewInit, query: Query, sourcePath: st...
  function createFixedTaskView (line 250) | function createFixedTaskView(
  function listId (line 262) | function listId(item: SListItem): string {
  function parentListId (line 266) | function parentListId(item: SListItem): string {
  function enumerateChildren (line 271) | function enumerateChildren(item: SListItem, output: Map<string, SListIte...
  function replaceChildren (line 279) | function replaceChildren(elements: SListItem[], lookup: Map<string, SLis...
  function nestItems (line 295) | function nestItems(raw: SListItem[]): [SListItem[], Set<string>] {
  function nestGroups (line 318) | function nestGroups(raw: Grouping<SListItem>): Grouping<SListItem> {
  function trimEndingLines (line 333) | function trimEndingLines(text: string): string {
  function setTaskCompletion (line 342) | function setTaskCompletion(
  function rewriteTask (line 374) | async function rewriteTask(vault: Vault, task: STask, desiredStatus: str...

FILE: src/util/hash.ts
  function cyrb53 (line 7) | function cyrb53(str: string, seed: number = 0): number {

FILE: src/util/locale.ts
  function currentLocale (line 2) | function currentLocale(): string {

FILE: src/util/media.ts
  constant IMAGE_EXTENSIONS (line 3) | const IMAGE_EXTENSIONS = Object.freeze(
  function isImageEmbed (line 25) | function isImageEmbed(link: Link): boolean {
  function extractImageDimensions (line 33) | function extractImageDimensions(link: Link): [number, number] | [number]...

FILE: src/util/normalize.ts
  function normalizeDuration (line 9) | function normalizeDuration(dur: Duration) {
  function stripTime (line 16) | function stripTime(dt: DateTime): DateTime {
  function extractDate (line 27) | function extractDate(str: string): DateTime | undefined {
  function getParentFolder (line 41) | function getParentFolder(path: string): string {
  function getFileName (line 46) | function getFileName(path: string): string {
  function getFileTitle (line 51) | function getFileTitle(path: string): string {
  function getExtension (line 58) | function getExtension(path: string): string {
  function extractSubtags (line 64) | function extractSubtags(tag: string): string[] {
  function tryOrPropagate (line 75) | function tryOrPropagate<T>(func: () => Result<T, string>): Result<T, str...
  function asyncTryOrPropagate (line 84) | async function asyncTryOrPropagate<T>(func: () => Promise<Result<T, stri...
  function escapeRegex (line 96) | function escapeRegex(str: string) {
  constant VAR_NAME_CANONICALIZER (line 101) | const VAR_NAME_CANONICALIZER: P.Parser<string> = P.alt(
  function canonicalizeVarName (line 111) | function canonicalizeVarName(name: string): string {
  constant HEADER_CANONICALIZER (line 115) | const HEADER_CANONICALIZER: P.Parser<string> = P.alt(
  function normalizeHeaderForLink (line 130) | function normalizeHeaderForLink(header: string): string {
  function renderMinimalDate (line 135) | function renderMinimalDate(time: DateTime, settings: QuerySettings, loca...
  function renderMinimalDuration (line 145) | function renderMinimalDuration(dur: Duration): string {
  function setsEqual (line 157) | function setsEqual<T>(first: Set<T>, second: Set<T>): boolean {
  function normalizeMarkdown (line 165) | function normalizeMarkdown(str: string): string {
Condensed preview — 148 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (808K chars).
[
  {
    "path": ".editorconfig",
    "chars": 291,
    "preview": "root = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\ninsert_final_newline = true\ntri"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 25,
    "preview": "github: [\"blacksmithgu\"]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1414,
    "preview": "name: Bug Report (desktop)\ndescription: \"File a bug report for Dataview on desktop Obsidian\"\ntitle: \"Bug report\"\nlabels:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report_mobile.yml",
    "chars": 1715,
    "preview": "name: Bug Report (mobile)\ndescription: \"File a bug report for Dataview on mobile Obsidian\"\ntitle: \"Bug report\"\nlabels: ["
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 641,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Dataview Discussions\n    url: https://github.com/blacksmithgu/obsid"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/documentation.md",
    "chars": 491,
    "preview": "---\nname: Documentation\nabout: Suggest improvements to documentation\ntitle: ''\nlabels: documentation\n\n---\n\n**Please prov"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 829,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature-request\n\n---\n\n[//]: # (Note:"
  },
  {
    "path": ".github/workflows/documentation.yml",
    "chars": 369,
    "preview": "name: docs\non:\n  release:\n    types:\n      - published\n  workflow_dispatch:\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n "
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 904,
    "preview": "name: Build and test project\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  form"
  },
  {
    "path": ".gitignore",
    "chars": 616,
    "preview": "# Intellij\n*.iml\n.idea\n\n# VSCode\n.vscode\n.history/\n\n# npm\nnode_modules\n\n# build\nbuild/\n\n# Ignore .obsidian\n# No one will"
  },
  {
    "path": ".prettierrc.json",
    "chars": 160,
    "preview": "{\n    \"tabWidth\": 4,\n    \"semi\": true,\n    \"embeddedLanguageFormatting\": \"off\",\n    \"parser\": \"typescript\",\n    \"printWi"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 31139,
    "preview": "# 0.5.70 (Beta)\n\nStill attempting to fix #2557, github is acting up.\n\n\n---\n\n# 0.5.69 (Beta)\n\nAttempting to fix #2557, bu"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2021 Michael Brenan\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 7828,
    "preview": "# Obsidian Dataview\n\nTreat your [Obsidian Vault](https://obsidian.md/) as a database which you can query from. Provides "
  },
  {
    "path": "__mocks__/data-import/web-worker/import-manager.ts",
    "chars": 622,
    "preview": "/** A mock for `FileImporter` which runs on the same thread. */\n\nimport { runImport } from \"data-import/web-worker/impor"
  },
  {
    "path": "__mocks__/obsidian.ts",
    "chars": 1097,
    "preview": "import EventEmitter from \"events\";\n\n/** Basic obsidian abstraction for any file or folder in a vault. */\nexport abstract"
  },
  {
    "path": "cspell.json",
    "chars": 3477,
    "preview": "{\n  \"version\": \"0.2\",\n  \"ignorePaths\": [],\n  \"dictionaryDefinitions\": [],\n  \"dictionaries\": [],\n  \"words\": [\n    \"aaab\","
  },
  {
    "path": "docs/.gitignore",
    "chars": 6,
    "preview": "site/\n"
  },
  {
    "path": "docs/docs/annotation/add-metadata.md",
    "chars": 7459,
    "preview": "# Adding Metadata to your Pages\n\nDataview cannot query all content of your vault. In order to be able to search, filter "
  },
  {
    "path": "docs/docs/annotation/metadata-pages.md",
    "chars": 3145,
    "preview": "# Metadata on Pages\n\nYou can add fields to a markdown page (a note) in three different ways - via Frontmatter, Inline fi"
  },
  {
    "path": "docs/docs/annotation/metadata-tasks.md",
    "chars": 5789,
    "preview": "# Metadata on Tasks and Lists\n\nJust like pages, you can also add **fields** on list item and task level to bind it to a "
  },
  {
    "path": "docs/docs/annotation/types-of-metadata.md",
    "chars": 7527,
    "preview": "# Field Types\n\nAll fields in dataview have a **type**, which determines how dataview will render, sort, and operate on t"
  },
  {
    "path": "docs/docs/api/code-examples.md",
    "chars": 1198,
    "preview": "# Codeblock Examples\n\n## Grouped Books\n\nGroup your books by genre, then create a table for each sorted by rating via a s"
  },
  {
    "path": "docs/docs/api/code-reference.md",
    "chars": 14996,
    "preview": "# Codeblock Reference\n\nDataview JavaScript Codeblocks are created using the `dataviewjs` language specification for a co"
  },
  {
    "path": "docs/docs/api/data-array.md",
    "chars": 6479,
    "preview": "# Data Arrays\n\nThe general representation of result lists in Dataview is the `DataArray`, which is a [proxied](https://d"
  },
  {
    "path": "docs/docs/api/intro.md",
    "chars": 1019,
    "preview": "# Overview\n\nThe Dataview JavaScript API allows for executing arbitrary JavaScript with access to the dataview indices an"
  },
  {
    "path": "docs/docs/changelog.md",
    "chars": 31139,
    "preview": "# 0.5.70 (Beta)\n\nStill attempting to fix #2557, github is acting up.\n\n\n---\n\n# 0.5.69 (Beta)\n\nAttempting to fix #2557, bu"
  },
  {
    "path": "docs/docs/friends.md",
    "chars": 865,
    "preview": "# Friends of Dataview\n\nA list of plugins which may be helpful for Dataview related workflows:\n\n - [MetaEdit](https://git"
  },
  {
    "path": "docs/docs/index.md",
    "chars": 7738,
    "preview": "# Overview\n\nDataview is a live index and query engine over your personal knowledge base. You can [**add metadata**](anno"
  },
  {
    "path": "docs/docs/queries/data-commands.md",
    "chars": 4733,
    "preview": "# Data Commands\n\nThe different commands that dataview queries can be made up of. Commands are\nexecuted in order, and you"
  },
  {
    "path": "docs/docs/queries/differences-to-sql.md",
    "chars": 2694,
    "preview": "<!--\n * @Author: chinesehamburger 2576226012@qq.com\n * @Date: 2024-12-12 14:24:45\n * @LastEditors: chinesehamburger 2576"
  },
  {
    "path": "docs/docs/queries/dql-js-inline.md",
    "chars": 5207,
    "preview": "# DQL, JS and Inlines\n\nOnce you've added [useful data to relevant pages](../annotation/add-metadata.md), you'll want to "
  },
  {
    "path": "docs/docs/queries/query-types.md",
    "chars": 14514,
    "preview": "# Query Types\n\nThe **Query Type** determines how the output of your dataview query looks like. It is the **first and onl"
  },
  {
    "path": "docs/docs/queries/structure.md",
    "chars": 7144,
    "preview": "# Structure of a Query\n\nDataview offers [multiple ways](dql-js-inline.md) to write queries and the syntax differs for ea"
  },
  {
    "path": "docs/docs/reference/expressions.md",
    "chars": 8180,
    "preview": "# Expressions\n\nDataview query language **expressions** are anything that yields a value:\n\n- all [fields](../annotation/a"
  },
  {
    "path": "docs/docs/reference/functions.md",
    "chars": 26888,
    "preview": "# Functions\n\nDataview functions provide more advanced ways to manipulate data. You can use functions **in [data commands"
  },
  {
    "path": "docs/docs/reference/literals.md",
    "chars": 4713,
    "preview": "# Literals\n\nDataview query language *literals* are **expressions** which represent constant values like a text (`\"Scienc"
  },
  {
    "path": "docs/docs/reference/sources.md",
    "chars": 2435,
    "preview": "# Sources\n\nA dataview **source** is something that identifies a set of files, tasks, or other data. Sources are indexed "
  },
  {
    "path": "docs/docs/resources/develop-against-dataview.md",
    "chars": 2172,
    "preview": "# Developing Against Dataview\n\nDataview includes a high-level plugin-facing API as well as TypeScript definitions and a "
  },
  {
    "path": "docs/docs/resources/examples.md",
    "chars": 1801,
    "preview": "# Examples\n\nA small collection of simple usages of the dataview query language.\n\n---\n\nShow all games in the games folder"
  },
  {
    "path": "docs/docs/resources/faq.md",
    "chars": 4833,
    "preview": "# Frequently Asked Questions\n\nA collection of frequently asked questions for Dataview queries and the expression languag"
  },
  {
    "path": "docs/docs/resources/resources-and-support.md",
    "chars": 3280,
    "preview": "# Other Resources\n\nThere is a bit of a learning curve to getting started with Dataview.\nThis page is a collection of res"
  },
  {
    "path": "docs/mkdocs.yml",
    "chars": 2689,
    "preview": "site_name: Dataview\nrepo_url: https://github.com/blacksmithgu/obsidian-dataview\nedit_uri: edit/master/docs/docs/\nmarkdow"
  },
  {
    "path": "docs/overrides/main.html",
    "chars": 26,
    "preview": "{% extends \"base.html\" %}\n"
  },
  {
    "path": "jest.config.js",
    "chars": 123,
    "preview": "module.exports = {\n    preset: \"ts-jest\",\n    testEnvironment: \"jsdom\",\n    moduleDirectories: [\"node_modules\", \"src\"],\n"
  },
  {
    "path": "manifest-beta.json",
    "chars": 357,
    "preview": "{\n  \"id\": \"dataview\",\n  \"name\": \"Dataview\",\n  \"version\": \"0.5.70\",\n  \"minAppVersion\": \"0.13.11\",\n  \"description\": \"Compl"
  },
  {
    "path": "manifest.json",
    "chars": 357,
    "preview": "{\n  \"id\": \"dataview\",\n  \"name\": \"Dataview\",\n  \"version\": \"0.5.68\",\n  \"minAppVersion\": \"0.13.11\",\n  \"description\": \"Compl"
  },
  {
    "path": "package.json",
    "chars": 1867,
    "preview": "{\n  \"name\": \"obsidian-dataview\",\n  \"version\": \"0.5.70\",\n  \"description\": \"Advanced data views for Obsidian.md.\",\n  \"main"
  },
  {
    "path": "rollup.config.js",
    "chars": 2553,
    "preview": "import nodeResolve from \"@rollup/plugin-node-resolve\";\nimport commonjs from \"@rollup/plugin-commonjs\";\nimport webWorker "
  },
  {
    "path": "scripts/beta-release",
    "chars": 2296,
    "preview": "#!/usr/bin/env bash\n# Automatically update versions in files and create an autorelease.\n# Requires the github CLI, and t"
  },
  {
    "path": "scripts/install-built",
    "chars": 409,
    "preview": "#!/usr/bin/env bash\n# Builds dataview and allows you to provide a path to the vault that it should be installed in.\n# Us"
  },
  {
    "path": "scripts/release",
    "chars": 2435,
    "preview": "#!/usr/bin/env bash\n# Automatically update versions in files and create an autorelease.\n# Requires the github CLI and jq"
  },
  {
    "path": "src/api/data-array.ts",
    "chars": 18615,
    "preview": "import { Groupings, Values } from \"data-model/value\";\nimport { QuerySettings } from \"settings\";\n\n/** A function which ma"
  },
  {
    "path": "src/api/extensions.ts",
    "chars": 840,
    "preview": "import { STask } from \"data-model/serialized/markdown\";\n\n/** A general function for deciding how to check a task given i"
  },
  {
    "path": "src/api/inline-api.ts",
    "chars": 17478,
    "preview": "/** Fancy wrappers for the JavaScript API, used both by external plugins AND by the dataview javascript view. */\n\nimport"
  },
  {
    "path": "src/api/plugin-api.ts",
    "chars": 25217,
    "preview": "/** The general, externally accessible plugin API (available at `app.plugins.plugins.dataview.api` or as global `Datavie"
  },
  {
    "path": "src/api/result.ts",
    "chars": 3123,
    "preview": "/** Functional return type for error handling. */\nexport class Success<T, E> {\n    public successful: true;\n\n    public "
  },
  {
    "path": "src/data-import/common.ts",
    "chars": 576,
    "preview": "/** Common utilities for extracting tags, links, and other business from metadata. */\n\nimport { EXPRESSION } from \"expre"
  },
  {
    "path": "src/data-import/csv.ts",
    "chars": 837,
    "preview": "import { canonicalizeVarName } from \"util/normalize\";\nimport { DataObject } from \"data-model/value\";\nimport * as Papa fr"
  },
  {
    "path": "src/data-import/inline-field.ts",
    "chars": 9565,
    "preview": "/** Parse inline fields and other embedded metadata in a line. */\n\nimport { EXPRESSION } from \"expression/parse\";\nimport"
  },
  {
    "path": "src/data-import/markdown-file.ts",
    "chars": 17620,
    "preview": "/** Importer for markdown documents. */\n\nimport { extractFullLineField, extractInlineFields, parseInlineValue, InlineFie"
  },
  {
    "path": "src/data-import/persister.ts",
    "chars": 3036,
    "preview": "import { PageMetadata } from \"data-model/markdown\";\nimport { Transferable } from \"data-model/transferable\";\nimport local"
  },
  {
    "path": "src/data-import/web-worker/import-entry.ts",
    "chars": 1144,
    "preview": "/** Entry-point script used by the index as a web worker. */\nimport { runImport } from \"data-import/web-worker/import-im"
  },
  {
    "path": "src/data-import/web-worker/import-impl.ts",
    "chars": 493,
    "preview": "/** Actual import implementation backend. This must remain separate from `import-entry` since it is used without web wor"
  },
  {
    "path": "src/data-import/web-worker/import-manager.ts",
    "chars": 4399,
    "preview": "/** Controls and creates Dataview file importers, allowing for asynchronous loading and parsing of files. */\n\nimport { T"
  },
  {
    "path": "src/data-index/index.ts",
    "chars": 22310,
    "preview": "/** Stores various indices on all files in the vault to make dataview generation fast. */\nimport { Result } from \"api/re"
  },
  {
    "path": "src/data-index/resolver.ts",
    "chars": 6171,
    "preview": "/** Collect data matching a source query. */\n\nimport { FullIndex, PathFilters } from \"data-index/index\";\nimport { Result"
  },
  {
    "path": "src/data-index/source.ts",
    "chars": 3293,
    "preview": "/** AST implementation for queries over data sources. */\n\n/** The source of files for a query. */\nexport type Source = T"
  },
  {
    "path": "src/data-model/markdown.ts",
    "chars": 13324,
    "preview": "import { extractSubtags, getExtension, getFileTitle, getParentFolder, stripTime } from \"util/normalize\";\nimport { DateTi"
  },
  {
    "path": "src/data-model/serialized/markdown.ts",
    "chars": 3805,
    "preview": "/** Serialized / API facing data types for Dataview objects. */\n\nimport { Link, Literal } from \"data-model/value\";\nimpor"
  },
  {
    "path": "src/data-model/transferable.ts",
    "chars": 3827,
    "preview": "import { Link, Values } from \"data-model/value\";\nimport { DateTime, Duration, SystemZone } from \"luxon\";\n\n/** Simplifies"
  },
  {
    "path": "src/data-model/value.ts",
    "chars": 22281,
    "preview": "import { DateTime, Duration } from \"luxon\";\nimport { DEFAULT_QUERY_SETTINGS, QuerySettings } from \"settings\";\nimport { g"
  },
  {
    "path": "src/expression/binaryop.ts",
    "chars": 7067,
    "preview": "/** Provides a global dispatch table for evaluating binary operators, including comparison. */\nimport { LiteralRepr, Lit"
  },
  {
    "path": "src/expression/context.ts",
    "chars": 12538,
    "preview": "/** Core implementation of the query language evaluation engine. */\n\nimport { DataObject, Literal, Values } from \"data-m"
  },
  {
    "path": "src/expression/field.ts",
    "chars": 4130,
    "preview": "/** Defines the AST for a field which can be evaluated. */\nimport { Literal } from \"data-model/value\";\n\n/** Comparison o"
  },
  {
    "path": "src/expression/functions.ts",
    "chars": 38761,
    "preview": "/** Default function implementations for the expression evaluator. */\n\nimport { DateTime } from \"luxon\";\nimport { Litera"
  },
  {
    "path": "src/expression/parse.ts",
    "chars": 21585,
    "preview": "import { DateTime, Duration } from \"luxon\";\nimport { Literal, Link } from \"data-model/value\";\nimport * as P from \"parsim"
  },
  {
    "path": "src/index.ts",
    "chars": 1755,
    "preview": "// Basic API type.\nexport type { DataviewApi } from \"api/plugin-api\";\nexport type { DataviewInlineApi, DataviewInlineIOA"
  },
  {
    "path": "src/main.ts",
    "chars": 32148,
    "preview": "import {\n    App,\n    Component,\n    debounce,\n    MarkdownPostProcessorContext,\n    MarkdownView,\n    Plugin,\n    Plugi"
  },
  {
    "path": "src/query/engine.ts",
    "chars": 19152,
    "preview": "/**\n * Takes a full query and a set of indices, and (hopefully quickly) returns all relevant files.\n */\nimport { FullInd"
  },
  {
    "path": "src/query/parse.ts",
    "chars": 9138,
    "preview": "import { EXPRESSION } from \"expression/parse\";\nimport * as P from \"parsimmon\";\nimport {\n    FlattenStep,\n    GroupStep,\n"
  },
  {
    "path": "src/query/query.ts",
    "chars": 3485,
    "preview": "/** Provides an AST for complex queries. */\nimport { Source } from \"data-index/source\";\nimport { Field } from \"expressio"
  },
  {
    "path": "src/settings.ts",
    "chars": 4437,
    "preview": "////////////////////\n// Query Settings //\n////////////////////\n\nexport interface QuerySettings {\n    /** What to render "
  },
  {
    "path": "src/test/api/data-array.test.ts",
    "chars": 6355,
    "preview": "import { DataArray } from \"api/data-array\";\nimport { DEFAULT_QUERY_SETTINGS } from \"settings\";\n\ndescribe(\"where\", () => "
  },
  {
    "path": "src/test/common.ts",
    "chars": 1039,
    "preview": "import { Literal } from \"data-model/value\";\nimport { Context, LinkHandler } from \"expression/context\";\nimport { EXPRESSI"
  },
  {
    "path": "src/test/data/index-map.test.ts",
    "chars": 1116,
    "preview": "import { IndexMap } from \"data-index/index\";\n\ntest(\"Simple Set/Get\", () => {\n    let index = new IndexMap();\n    index.s"
  },
  {
    "path": "src/test/data/transferable.test.ts",
    "chars": 1100,
    "preview": "import { Transferable } from \"data-model/transferable\";\nimport { Link } from \"data-model/value\";\nimport { DateTime, Dura"
  },
  {
    "path": "src/test/data/values.test.ts",
    "chars": 1181,
    "preview": "import { Values, Link } from \"data-model/value\";\n\ndescribe(\"Links\", () => {\n    describe(\"Comparisons\", () => {\n        "
  },
  {
    "path": "src/test/function/aggregation.test.ts",
    "chars": 3845,
    "preview": "import { expectEvals } from \"test/common\";\n\ndescribe(\"map()\", () => {\n    test(\"empty list\", () => expectEvals(\"map([], "
  },
  {
    "path": "src/test/function/coerce.test.ts",
    "chars": 703,
    "preview": "import { expectEvals, parseEval } from \"test/common\";\n\ntest(\"number()\", () => {\n    expect(parseEval('number(\"hmm\")')).t"
  },
  {
    "path": "src/test/function/constructors.test.ts",
    "chars": 830,
    "preview": "import { Duration } from \"luxon\";\nimport { parseEval } from \"test/common\";\n\ndescribe(\"dur()\", () => {\n    test(\"8 minute"
  },
  {
    "path": "src/test/function/eval.test.ts",
    "chars": 5104,
    "preview": "/** Various tests for evaluating fields in context. */\n\nimport { EXPRESSION } from \"expression/parse\";\nimport { Context,"
  },
  {
    "path": "src/test/function/functions.test.ts",
    "chars": 7827,
    "preview": "// <-- Functions -->\n// <-- Function vectorization -->\n\nimport { DateTime } from \"luxon\";\nimport { DefaultFunctions } fr"
  },
  {
    "path": "src/test/function/meta.test.ts",
    "chars": 1109,
    "preview": "import { parseEval } from \"test/common\";\n\ntest(\"Evaluate meta(link).display\", () => {\n    expect(parseEval(`meta([[2021-"
  },
  {
    "path": "src/test/function/string.test.ts",
    "chars": 6988,
    "preview": "// <-- regexreplace() -->\n\nimport { parseEval } from \"test/common\";\n\ndescribe(\"regexreplace()\", () => {\n    test(\"letter"
  },
  {
    "path": "src/test/function/vectorization.test.ts",
    "chars": 944,
    "preview": "import { Literal } from \"data-model/value\";\nimport { parseEval } from \"test/common\";\n\ndescribe(\"Single List Argument\", ("
  },
  {
    "path": "src/test/markdown/parse.file.test.ts",
    "chars": 1747,
    "preview": "import { extractTags } from \"data-import/markdown-file\";\nimport * as common from \"data-import/common\";\nimport { FrontMat"
  },
  {
    "path": "src/test/parse/parse.expression.test.ts",
    "chars": 24647,
    "preview": "import { BinaryOpField, Fields, LiteralField } from \"expression/field\";\nimport { EXPRESSION } from \"expression/parse\";\ni"
  },
  {
    "path": "src/test/parse/parse.inline.test.ts",
    "chars": 7119,
    "preview": "import { EXPRESSION } from \"expression/parse\";\nimport { Link } from \"data-model/value\";\nimport { extractInlineFields, se"
  },
  {
    "path": "src/test/parse/parse.query.test.ts",
    "chars": 8264,
    "preview": "import { TableQuery, ListQuery, CalendarQuery, SortByStep, QueryFields, Query } from \"query/query\";\nimport { QUERY_LANGU"
  },
  {
    "path": "src/test/util/normalize.test.ts",
    "chars": 1687,
    "preview": "import { canonicalizeVarName, normalizeHeaderForLink } from \"util/normalize\";\n\ndescribe(\"Header Normalization\", () => {\n"
  },
  {
    "path": "src/test/util/paths.test.ts",
    "chars": 1179,
    "preview": "import { getFileTitle, getParentFolder } from \"util/normalize\";\n\ndescribe(\"getFileTitle()\", () => {\n    test(\"empty\", ()"
  },
  {
    "path": "src/typings/obsidian-ex.d.ts",
    "chars": 954,
    "preview": "import type { DataviewApi } from \"api/plugin-api\";\nimport \"obsidian\";\nimport { EditorView } from \"@codemirror/view\";\n\nde"
  },
  {
    "path": "src/typings/workers.d.ts",
    "chars": 123,
    "preview": "declare module \"web-worker:*\" {\n    const WorkerFactory: new (options: any) => Worker;\n    export default WorkerFactory;"
  },
  {
    "path": "src/ui/export/markdown.ts",
    "chars": 5819,
    "preview": "import { SListItem } from \"data-model/serialized/markdown\";\nimport { Grouping, Groupings, Literal, Values, Widgets } fro"
  },
  {
    "path": "src/ui/lp-render.ts",
    "chars": 16753,
    "preview": "/*\n * inspired and adapted from https://github.com/artisticat1/obsidian-latex-suite/blob/main/src/conceal.ts\n *\n * The o"
  },
  {
    "path": "src/ui/markdown.tsx",
    "chars": 11364,
    "preview": "/** Provides core preact / rendering utilities for all view types. */\nimport { App, MarkdownRenderChild, MarkdownRendere"
  },
  {
    "path": "src/ui/refreshable-view.ts",
    "chars": 1365,
    "preview": "import { FullIndex } from \"data-index\";\nimport { App, MarkdownRenderChild } from \"obsidian\";\nimport { DataviewSettings }"
  },
  {
    "path": "src/ui/render.ts",
    "chars": 9092,
    "preview": "import { App, Component, MarkdownRenderer } from \"obsidian\";\nimport { DataArray } from \"api/data-array\";\nimport { QueryS"
  },
  {
    "path": "src/ui/views/calendar-view.ts",
    "chars": 4105,
    "preview": "import { FullIndex } from \"data-index\";\nimport { Link } from \"index\";\nimport { App } from \"obsidian\";\nimport { Calendar,"
  },
  {
    "path": "src/ui/views/inline-field-live-preview.ts",
    "chars": 12502,
    "preview": "import { App, Component, TFile, editorInfoField, editorLivePreviewField } from \"obsidian\";\nimport { EditorState, RangeSe"
  },
  {
    "path": "src/ui/views/inline-field.tsx",
    "chars": 4157,
    "preview": "import { InlineField, extractInlineFields, parseInlineValue } from \"data-import/inline-field\";\nimport { MarkdownPostProc"
  },
  {
    "path": "src/ui/views/inline-view.ts",
    "chars": 1638,
    "preview": "import { FullIndex } from \"data-index\";\nimport { Field } from \"expression/field\";\nimport { App } from \"obsidian\";\nimport"
  },
  {
    "path": "src/ui/views/js-view.ts",
    "chars": 3050,
    "preview": "import { asyncEvalInContext, DataviewInlineApi } from \"api/inline-api\";\nimport { renderErrorPre, renderValue } from \"ui/"
  },
  {
    "path": "src/ui/views/list-view.tsx",
    "chars": 2654,
    "preview": "import { MarkdownRenderChild } from \"obsidian\";\nimport { executeList } from \"query/engine\";\nimport { Query } from \"query"
  },
  {
    "path": "src/ui/views/table-view.tsx",
    "chars": 4117,
    "preview": "import { Literal } from \"data-model/value\";\nimport { executeTable } from \"query/engine\";\nimport { Query } from \"query/qu"
  },
  {
    "path": "src/ui/views/task-view.tsx",
    "chars": 14514,
    "preview": "import { setEmojiShorthandCompletionField, setInlineField } from \"data-import/inline-field\";\nimport { LIST_ITEM_REGEX } "
  },
  {
    "path": "src/util/hash.ts",
    "chars": 1086,
    "preview": "// cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated.\n// A fast and simple 64-bit "
  },
  {
    "path": "src/util/locale.ts",
    "chars": 220,
    "preview": "/** Test-environment-friendly function which fetches the current system locale. */\nexport function currentLocale(): stri"
  },
  {
    "path": "src/util/media.ts",
    "chars": 1159,
    "preview": "import { Link } from \"data-model/value\";\n\nexport const IMAGE_EXTENSIONS = Object.freeze(\n    new Set([\n        \".tif\",\n "
  },
  {
    "path": "src/util/normalize.ts",
    "chars": 6080,
    "preview": "import { DateTime, Duration } from \"luxon\";\nimport { Result } from \"api/result\";\nimport * as P from \"parsimmon\";\nimport "
  },
  {
    "path": "styles.css",
    "chars": 2965,
    "preview": ".block-language-dataview {\n    overflow-y: auto;\n}\n\n/*****************/\n/** Table Views **/\n/*****************/\n\n/* List"
  },
  {
    "path": "test-vault/.obsidian/community-plugins.json",
    "chars": 32,
    "preview": "[\n  \"hot-reload\",\n  \"dataview\"\n]"
  },
  {
    "path": "test-vault/Books.md",
    "chars": 104,
    "preview": "# Non-Fiction\n```dataview\nlist from [[Non-Fiction]]\n```\n# Fiction\n```dataview\nlist from [[Fiction]]\n```\n"
  },
  {
    "path": "test-vault/Home.md",
    "chars": 62,
    "preview": "Home\n\n[[example tables]]\n\n[[example lists]]\n\n[[example tasks]]"
  },
  {
    "path": "test-vault/blog/2020-08-08-an-earlier-post.md",
    "chars": 298,
    "preview": "---\ndraft: true\nstart_date: 2021-10-01T02:00:00+02:00\nend_date: 2021-10-01T13:00:00-10:00\nanother_date: 2021-10-01T01:00"
  },
  {
    "path": "test-vault/blog/2021-08-08-a-post.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test-vault/books/Catcher in the Rye.md",
    "chars": 46,
    "preview": "- Author: [[J.D. Salinger]]\n- Tag: [[Fiction]]"
  },
  {
    "path": "test-vault/books/Origin of Species.md",
    "chars": 51,
    "preview": "- Author: [[Charles Darwin]]\n- Tag: [[Non-Fiction]]"
  },
  {
    "path": "test-vault/books/The Great Gatsby.md",
    "chars": 49,
    "preview": "- Author: [[Scott Fitzgerald]]\n- Tag: [[Fiction]]"
  },
  {
    "path": "test-vault/example calendars.md",
    "chars": 108,
    "preview": "\n```dataview\nCALENDAR thoughtOfDate\nFROM\n\"recipes\"\n```\n\n\n```dataview\nCALENDAR file.mtime\nFROM\n\"recipes\"\n```\n"
  },
  {
    "path": "test-vault/example lists.md",
    "chars": 43,
    "preview": "# Lists\n```dataview\nlist from \"recipes\"\n```"
  },
  {
    "path": "test-vault/example tables.md",
    "chars": 408,
    "preview": "# Tables\n```dataview\ntable mtime as Modified, draft as Draft from \"blog\"\n```\n\n```dataview\ntable cuisine as Cuisine, need"
  },
  {
    "path": "test-vault/recipes/pbj.md",
    "chars": 186,
    "preview": "---\ncuisine: American\nneedsStove: false\nthoughtOfDate: 2021-12-11\n---\n# Peanut Butter and Jelly\n## Ingredients\n- [ ] Bre"
  },
  {
    "path": "test-vault/recipes/toast.md",
    "chars": 202,
    "preview": "---\ncuisine: British\nneedsStove: true\nthoughtOfDate: 2021-12-10\n---\n\n# Toast\n## Ingredients \n- [ ] Bread\n- [ ] Butter\n\n#"
  },
  {
    "path": "test-vault/tasks/Annotated Tasks.md",
    "chars": 86,
    "preview": "```dataview\ntask where annotated\n```\n\ngrouped\n```dataview\ntask\nwhere p\ngroup by p\n```\n"
  },
  {
    "path": "test-vault/tasks/Completed Tasks.md",
    "chars": 56,
    "preview": "## Completed Tasks\n\n```dataview\ntask WHERE completed\n```"
  },
  {
    "path": "test-vault/tasks/Grouped Sorted Tasks.md",
    "chars": 50,
    "preview": "```dataview\ntask\nwhere p\nsort p asc\ngroup by p\n```"
  },
  {
    "path": "test-vault/tasks/Sorted Tasks.md",
    "chars": 39,
    "preview": "```dataview\ntask\nwhere p\nsort p asc\n```"
  },
  {
    "path": "test-vault/tasks/Tasks Completed on specific Date.md",
    "chars": 102,
    "preview": "## Completed on a specific date\n```dataview\ntask from \"tasks\" where\ncompletion = date(2021-08-06)\n```\n"
  },
  {
    "path": "test-vault/tasks/Tasks in a specific section.md",
    "chars": 109,
    "preview": "# Tasks in a specific section\n\n```dataview\ntask\nwhere meta(section).subpath = \"Section\"\ngroup by section\n```\n"
  },
  {
    "path": "test-vault/tasks/Uncompleted Tasks.md",
    "chars": 69,
    "preview": "## Uncompleted\n```dataview\ntask from -\"recipes\"\nWHERE !completed\n```\n"
  },
  {
    "path": "test-vault/tasks/checklist.md",
    "chars": 717,
    "preview": "- [x] Normal task, tags inherited from page [completion:: 2021-10-23]\n* [ ] Task with a #tag, adds to inherited page tag"
  },
  {
    "path": "test-vault/tasks/example tasks.md",
    "chars": 194,
    "preview": "# Tasks\n\n![[Uncompleted Tasks]]\n\n![[Completed Tasks]]\n\n![[Tasks Completed on specific Date]]\n\n![[Annotated Tasks]]\n\n![[S"
  },
  {
    "path": "test-vault/untracked/README.md",
    "chars": 287,
    "preview": "Git will not track files in this folder. (except this one)\n\nFeel free to write whatever for anything you want to try. Gi"
  },
  {
    "path": "tsconfig-lib.json",
    "chars": 249,
    "preview": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"outDir\": \"lib\",\n    \"plugins\": [{"
  },
  {
    "path": "tsconfig.json",
    "chars": 659,
    "preview": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"sourceMap\": true,\n    \"inlineSourceMap\": false,\n    \"inlineSources\":"
  },
  {
    "path": "versions.json",
    "chars": 3286,
    "preview": "{\n  \"0.0.1\": \"0.10.7\",\n  \"0.1.0\": \"0.10.7\",\n  \"0.1.1\": \"0.10.7\",\n  \"0.1.2\": \"0.10.7\",\n  \"0.1.3\": \"0.10.7\",\n  \"0.1.4\": \"0"
  }
]

About this extraction

This page contains the full source code of the blacksmithgu/obsidian-dataview GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 148 files (749.9 KB), approximately 188.8k tokens, and a symbol index with 682 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!