Frontmatter Modified Date for Obsidian

repository·main·Indexed 41 days ago

https://github.com/alangrainger/obsidian-frontmatter-modified-date

An Obsidian plugin (v1.5.4) that automatically updates a specified YAML frontmatter property with the modified date based on editor activity rather than filesystem timestamps. It supports custom MomentJS date formatting, folder exclusions, and a history logging feature to maintain an array of modification dates instead of a single value.

Tokens
2.6K
Snippets
4
Records
12
Agent score
52%

What's inside Frontmatter Modified Date

  1. How the modified date update works

    main

    The plugin automatically updates a specified YAML field in your note's frontmatter whenever you edit a note within Obsidian.

    Key distinction: Unlike many other plugins, this does not rely on the filesystem's modified time. Instead, it triggers based on activity within the Obsidian editor. Updates are queued; if you stop typing, the plugin will update the frontmatter even if you close the file shortly after.

  2. Configure plugin options

    main

    You can customize how the plugin behaves via the Settings page:

    • YAML field name: Specify the name of the property you want to update (e.g., modified, updated).
    • Date format: Define the output format using MomentJS format.
    • Excluding folders: Prevent automatic updates for specific directories (useful for scripts or templates).
    • Use typing events instead of Obsidian events:
      • Disabled (Default): Updates when Obsidian fires an editor-change event. This includes updates from other plugins (like Linter) or external applications.
      • Enabled: Updates only based on active typing, avoiding updates triggered by external processes.
  3. Append modified dates to a history array

    main

    To keep a log of every time a note is edited rather than just overwriting a single field, you can use the history feature.

    Setup: Add a checkbox property named append_modified_update to your note's frontmatter.

    ⚠️ Warning: Removing the append_modified_update property from the frontmatter will permanently remove all previously saved modification dates in that file.

    Frequency Control: By default, the plugin records a maximum of one entry per day. To change this frequency, edit your plugin's data.json file and modify the appendMaximumFrequency value using any MomentJS time unit (e.g., second, minute, hour, month).

  4. How the plugin handles history logging

    main

    When storeHistoryLog is enabled (or if the target field is already an array), the plugin manages a history of modification dates:

    • Merging Updates: If a new update occurs within the same timeframe defined by appendMaximumFrequency as the last entry, the plugin replaces the existing entry instead of adding a new one.
    • Array Management: Depending on historyNewestFirst, entries are either unshifted (newest at index 0) or pushed (newest at the end).
    • Trimming: The history array is trimmed to the size specified by historyMaxItems to prevent unbounded growth.
    • Type Safety: If the previous entry was a single string/number and the plugin switches to array mode, it automatically converts the existing value into an array.
  5. Understand the FrontmatterModified plugin architecture

    main

    The FrontmatterModified plugin automates the updating of a specific YAML frontmatter property to track when a file was last modified. It operates in two primary modes:

    1. Editor Change Mode (Default): Watches for editor-change events in the Obsidian workspace. This is preferred over vault modification events because it avoids false positives triggered by sync clients that update file timestamps without changing content.
    2. Keyup Events Mode: Uses a custom editor extension (userChangeListenerExtension) to listen for typing events. This mode is recommended for users who experience issues with external programs modifying their files.

    To prevent race conditions and Obsidian's "merging changes" error, the plugin uses a debounced timeout mechanism. It waits for the user to stop typing (based on the timeout setting) before attempting to update the frontmatter.

  6. Configure history logging for modified dates

    main

    When storeHistoryLog is enabled, the plugin tracks a history of all updates to a note. You can configure the following settings to manage this log:

    • Frequency of updates (appendMaximumFrequency): Limits the number of entries by specifying a time unit. The plugin will store a maximum of 1 entry per specified unit (e.g., minute, hour, day, week, month, quarter, or year). If multiple edits occur within that period, the last edit entry will update the existing one for that unit.
    • Order (historyNewestFirst): Determines if the history list starts with the newest item (true) or the oldest item (false).
    • Maximum items (historyMaxItems): Limits the total number of history entries. Set to 0 for unlimited history.
    // Possible values for appendMaximumFrequency:
    // 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
  7. Troubleshoot the 'Merging changes' popup

    main

    If you see an Obsidian message regarding "Merging changes," it means you were typing in a note at the exact moment the plugin attempted to update the frontmatter.

    Context:

    • This is caused by Obsidian's internal frontmatter handling, not an external process.
    • The plugin attempts to minimize this by waiting 10 seconds after you stop typing before performing the update.
    • This occurrence is rare and does not affect the integrity of your data.
  8. Configure FrontmatterModified settings

    main

    The plugin's behavior is controlled via FrontmatterModifiedSettings. Key configuration capabilities include:

    • frontmatterProperty: The name of the YAML field used to store the modified date.
    • onlyUpdateExisting: If true, the plugin will only update the property if it already exists in the file's frontmatter.
    • excludeField: A specific YAML field that, if present, prevents the plugin from updating that file.
    • excludedFolders: A list of folder paths that are ignored by the plugin.
    • storeHistoryLog: If enabled, the plugin can maintain an array of previous modification dates instead of a single value.
    • appendField: Used in conjunction with history logging to identify the field containing the history array.
    • momentFormat: A MomentJS string used to format the date. If the format results in only digits, the plugin stores it as an integer; otherwise, it is stored as a string.
    • historyMaxItems: Limits the number of entries kept in the history log.
    • historyNewestFirst: Determines if new history entries are unshifted to the front or pushed to the end of the array.
    • appendMaximumFrequency: Defines the timeframe (using MomentJS comparison) within which multiple updates are merged into a single entry rather than creating new history items.
  9. Configure Frontmatter Modified Date settings

    main

    The FrontmatterModifiedSettings interface defines the configuration available for the plugin. You can control which YAML properties are updated, how dates are formatted using momentjs, how history is logged, and which folders are excluded from tracking.

    Key Configuration Options

    • frontmatterProperty: The name of the YAML/frontmatter property to update (defaults to modified).
    • createdDateProperty: (Optional) If provided, the plugin will also update the note's creation date.
    • momentFormat: The date format using momentjs syntax. If left blank, it uses the default atom format.
    • momentLocale: The momentjs locale to use (e.g., en).
    • storeHistoryLog: When enabled, the frontmatterProperty becomes a list of all modification dates instead of a single value.
    • excludedFolders: A list of folder paths to ignore. All subfolders of these paths are also excluded.
    • onlyUpdateExisting: If enabled, the plugin will only update a frontmatter field if it already exists in the file.
    • useKeyupEvents: If enabled, the plugin watches for typing events instead of Obsidian file events. This prevents updates when files are modified by external editors or via mouse interactions (like updating properties via the UI).
    • timeout: The number of seconds to wait after the last edit before updating the frontmatter. Increasing this can reduce "merging changes" popups.
    • excludeField: The field name used to exclude a note from updates (defaults to exclude_modified_update).
    • appendField: The field name used for appending history (defaults to append_modified_update).
    export interface FrontmatterModifiedSettings {
      frontmatterProperty: string;
      createdDateProperty: string;
      momentFormat: string;
      momentLocale: string;
      storeHistoryLog: boolean;
      historyNewestFirst: boolean;
      historyMaxItems: number;
      excludedFolders: string[];
      useKeyupEvents: boolean;
      onlyUpdateExisting: boolean;
      timeout: number;
      excludeField: string;
      appendField: string;
      appendMaximumFrequency: StartOfUnit;
    }
  10. Update frontmatter with updateFrontmatter()

    main

    The updateFrontmatter(file: TFile) method is the core logic for applying changes. It performs the following steps:

    1. Debouncing: Clears any existing timeout for the specific file path and starts a new one based on the timeout setting.
    2. Validation: Checks if the file should be ignored based on onlyUpdateExisting, excludeField, or excludedFolders.
    3. Frequency Check: Compares the current time to the last recorded modification. To prevent sync race conditions, updates are only applied if at least 30 seconds have passed since the last recorded timestamp.
    4. Formatting: Formats the current time using momentFormat via formatFrontmatterDate().
    5. Writing: Uses app.fileManager.processFrontMatter to safely update the YAML. If createdDateProperty is configured and the file lacks a creation date, it will also initialize that field using the file's creation time (ctime).
    async updateFrontmatter (file: TFile)