Datacore

repository·master·Indexed 24 days ago

https://github.com/blacksmithgu/datacore

A reactive data engine for Obsidian.md that allows users to create interactive views using JavaScript, JSX, TypeScript, or TSX. It provides a specialized API (`dc`) for querying the Datacore index via React hooks, a `DataArray` wrapper for advanced data manipulation (filtering, sorting, grouping), and components like `dc.List` for rendering pageable, hierarchical data lists.

Tokens
32.8K
Snippets
76
Records
173
Agent score
81%

What's inside @blacksmithgu/datacore

  1. What is Datacore and how does it differ from Dataview?

    master

    Datacore is a successor to the Dataview plugin designed to index vault information for searching and compiling into views. It provides several key improvements over the original Dataview:

    • Performance: Up to 100x faster due to an optimized index design.
    • Granularity: Supports querying at the section, block, line, and canvas item levels.
    • Advanced API: Features a powerful JavaScript/TypeScript API, including React and JSX support for creating complex, live-updating views.
    • Code Reuse: Supports importing code files and using JSX/TypeScript directly.
    • Enhanced View Features: All views include built-in support for paging and embedding complex components within other components.
  2. Find children with `childof()` and `subtree()`

    master

    The childof() function produces all children of the objects matched by an input query.

    • childof(query): Exclusive. Returns only the children of the matching objects.
    • subtree(query): Inclusive. Returns both the children and the original matching objects.

    Example:

    // Return all sections, blocks, etc that are children of markdown pages.
    childof(@page)
    
    // Return page objects and all of the sections, blocks, etc in them.
    subtree(@page)
    // Return all sections, blocks, etc that are children of markdown pages.
    childof(@page)
    // Return page objects and all of the sections, blocks, etc in them.
    subtree(@page)
  3. How to use Datacore functions in expressions

    master

    Datacore functions can be used in expressions using two different styles:

    1. Standard Function Calling: Pass arguments directly to the function name. func(arg1, arg2)

    2. Postfix Calling Style: Chain functions onto an object. The object becomes the implicit first argument. object.func(arg1) is equivalent to func(object, arg1).

    Vectorization: Functions support vectorization. If you pass a list as an argument instead of a single value, the function will return a list of results instead of a single value.

    Example of vectorization with postfix style:

    ["YES", "NO"].lower() // -> ["yes", "no"]
    lower("YES")  // -> "yes"
    "YES".lower() // Same as lower("YES")
    ["YES", "NO"].lower() // vectorization + postfix calling style.
  4. How grouping works in dc.Table

    master

    If the rows prop contains grouped data (e.g., created via dc.useArray and array.groupBy), dc.Table will automatically render grouping headers.

    You can customize how these headers are rendered using the groupings prop. This prop accepts:

    1. A function: (key, rows) => ReactNode. This function receives the grouping key and the associated rows.
    2. A GroupingConfig object: { render: (key, rows) => ReactNode }.
    3. An array of configurations: To specify different rendering logic for multiple levels of grouping.
    // Using a function for custom grouping rendering
    <dc.Table 
        rows={booksByGenre} 
        columns={COLUMNS} 
        groupings={(key) => dc.fileLink(key)} 
    />
    
    // Using a GroupingConfig object
    const LINK_GROUPING = {
        render: (key, rows) => dc.fileLink(key)
    };
    <dc.Table 
        rows={booksByGenre} 
        columns={COLUMNS} 
        groupings={LINK_GROUPING} 
    />
  5. Find parents with `parentof()` and `supertree()`

    master

    The parentof() function matches the parents of the objects returned by an input query.

    • parentof(query): Exclusive. Returns only the parents of the matching objects.
    • supertree(query): Inclusive. Returns both the parents and the original matching objects.

    Example:

    // Find all pages that contain datacore codeblocks.
    @page and parentof(@codeblock and $languages.contains("datacorejs"))
    
    // Return the parent sections and pages of codeblocks, and the codeblocks themselves.
    supertree(@codeblock)
    // Find all pages that contain datacore codeblocks.
    @page and parentof(@codeblock and $languages.contains("datacorejs"))
    
    // Find pages which have `Daily` sections.
    @page and parentof(@section and $name = "Daily")
    
    // Return all of the parent sections/pages of codeblocks.
    parentof(@codeblock)
    // Return the parent sections and pages of codeblocks, and the codeblocks themselves.
    supertree(@codeblock)
  6. Supported Data Input methods

    master

    Datacore supports several ways to define and query metadata, moving towards native Obsidian metadata patterns while maintaining backward compatibility:

    • Inline YAML: Place YAML objects anywhere in a document and mark them inline to add metadata to a page or section.
    • Inline Objects: Define YAML codeblocks as "objects" (e.g., an "exercise" object) which are searchable independently of the page they reside on.
    • Sections: Individual sections within markdown files can be treated as objects and are directly queryable.
    • Tasks: Tasks are directly queryable and support metadata via the Tasks plugin emoji or inline fields.
  7. Navigate the Datacore hierarchy using `$parent` and `$sections`

    master

    The Datacore index is hierarchical. You can traverse this hierarchy using relationship fields:

    • Top-down: A page object contains a list of its sections in the $sections field.
    • Bottom-up: Any child object (like a section or block) can find its parent using the $parent field.
  8. Query and access section metadata

    master

    Datacore tracks sections in markdown files and canvases, which can be queried using the @section type. Each section contains built-in metadata fields such as $ordinal, $title, $level, $position, and $tags.

    Accessing Inline Fields

    Inline fields defined within a section can be accessed in two ways:

    1. In queries and expressions: Reference the field name directly.
    2. In JavaScript: Use the .value() method on the section object.

    Note that inline field access is case-insensitive.

  9. Use swizzling to access fields in a DataArray

    master

    In addition to standard numeric indexing (e.g., array[0]), DataArray supports "swizzling". If you index into a DataArray using a field name (e.g., array.fieldName), it automatically maps every element in the array to that field. If the field itself is an array, the result is automatically flattened.

    This is equivalent to calling .to("fieldName").

    const data = dc.array(dc.query("#books and @page"));
    
    data.$name // => List of all book names.
    data.$ctime // => List of all book created times.
  10. Work with List Blocks and List Items

    master

    Datacore distinguishes between a list-block (the container) and individual list-items (the elements within).

    List Blocks (list-block)

    Used to query the entire list structure. They contain a $elements field which is a list of the items within.

    List Items (list-item)

    Individual items or tasks. They can be queried via @list-item.

    Key List Item fields:

    • $type: Either task or list.
    • $line / $lineCount: The starting line number and total line count.
    • $text: The full text of the item including markup.
    • $cleantext: The text with indentation, inline fields, and IDs removed.
    • $parentLine: The line number of the parent item (negative for top-level items).
    • $symbol: The marker used (e.g., -, *, 1.).
    • $elements: A list of sub-items under this item.
  11. What are Datacore expressions and where to use them

    master
    Datacore features an internal expression language that functions as a simple scripting language. It is primarily used for filtering pages within queries, but it is also accessible via the Javascript View API and will be supported in the upcoming YAML-based view format. The syntax is similar to JavaScript but includes specialized handling for dates, durations, and links.