Skip to content

0.20.4 — Frontmatter property placeholders + settings UI no longer lags or scrolls

Latest

Choose a tag to compare

@diegoeis diegoeis released this 18 Jun 23:06

0.20.4 - 2026-06-18

Fixes

  • No more scroll-to-top or lag on any settings interaction. Every remaining this.display() call inside the settings UI has been replaced by a localized DOM mutation:

    • Changing the Scan scope no longer rebuilds the page — the "Notes to scan" row is now created once and toggled via an is-hidden class.
    • Add rule appends the new rule's wrap right after the Add button instead of re-rendering all rules.
    • Changing a condition's Property / First level heading type, or its operator, rebuilds only that single condition row in place.
    • Changing an action's Property / First heading type, or its action (add / overwrite / delete / rename / …), rebuilds only that single action row in place.

    The only display() left in the settings UI is on Import settings, where rebuilding the whole tab is the right thing to do (every field potentially changed).

Internal

  • Eliminated dead code (_updateValueInputState, never called).
  • Removed the unused ruleIdx parameter from _renderThenAction and call sites.
  • Translated lingering Portuguese comments to English (or removed them when they only restated the code).
  • Replaced fragile class-based DOM lookups (.extra-setting-button, .conditional-match, .setting-item-name) with explicit references on ruleCtx:
    • ruleCtx.matchWrapEl — the Match dropdown element, null when absent.
    • ruleCtx.removeBtnByConditionWeakMap<Setting, HTMLElement> mapping each condition's Setting instance to its ✕ button element.
    • ruleCtx.actionEntries — array of { el, setting } per action row, so reindexing and rebuilds use the Setting instance directly instead of querying the DOM by class.
  • Added _rebuildCondition(ruleCtx, cond) and _rebuildAction(ruleCtx, action) to encapsulate the "this row's shape changed, redraw just this row" path that used to be a full display().
  • Added an is-hidden utility class in styles.css so visibility toggles stay in CSS instead of being scattered as inline style.display = '…' assignments.

0.20.3 - 2026-06-18

Fixes

  • The rule-level Remove button no longer scrolls or lags either. The same display() call that 0.20.1 and 0.20.2 eliminated for rows was still firing when an entire rule was removed. The rule's wrap element is now detached in place; the other rules stay exactly where they were on screen.

Internal

  • The Remove handler unsubscribes the rule's onScanStateChange listener and prunes it from _scanStateUnsubscribers before detaching the DOM, so removed rules don't leave dangling subscribers behind.
  • Both Run this rule and Remove resolve the rule's current index via Array#indexOf(rule) at click time instead of trusting the idx captured at render time. With re-renders gone, the closure-captured index would go stale after any other rule was removed and we'd run / delete the wrong one.

0.20.2 - 2026-06-18

Fixes

  • Removing a condition or action no longer scrolls or lags. Same root cause as 0.20.1 — the per-row Remove (✕) button still called display(), which destroyed and rebuilt the entire settings tab. Now the removed row's DOM is detached in place; the remaining rows are reindexed (Condition 1, Condition 2, …) via the Setting instance, and when a rule drops back to a single condition the Match (any/all) dropdown and the last Remove ✕ are stripped without re-rendering.

Internal

  • Introduced a per-rule ruleCtx object ({ wrap, ifHeader, rule, conditionSettings, actionWraps }) shared between _renderRule, _renderCondition, _renderThenAction, _addConditionRemoveButton, and _ensureMatchDropdown. Remove handlers mutate this context instead of falling back to a full re-render.
  • Condition rows are tracked as Setting instances so setName() is enough to reindex; action wraps are tracked as their root elements and reindexed via a scoped querySelector for .setting-item-name.

0.20.1 - 2026-06-18

Fixes

  • "+ Add condition" and "+ Add action" no longer scroll the settings tab to the top. Previously each click re-rendered the entire settings UI via display(), which destroyed and recreated every rule and reset the scroll position — making it impossible to keep your eyes on the rule you were editing. The new condition/action is now appended in place, right above its "Add" button.
  • New conditions/actions appear instantly. The full re-render was also responsible for the lag — every existing rule, condition and action was being rebuilt on each click. Only the new row is created now.
  • The Match (any/all) dropdown is materialized on the fly the first time a rule gets a second condition, and the per-condition Remove button is wired into the previously-single condition at the same moment — no element is destroyed and recreated.

Internal

  • _renderCondition() and _renderThenAction() now return the elements they create (the Setting and the wrap div), so callers can insert them at a precise position without resorting to lastElementChild or DOM scraping.
  • New helpers _ensureMatchDropdown(ifHeader, rule) and _addConditionRemoveButton(settingLine, rule, cond) extract the dynamic-mutation logic. The Remove handler looks up the condition's current index via Array#indexOf instead of capturing it in a closure, so removals stay correct after subsequent additions.
  • Remove handler for actions does the same indexOf lookup, fixing a latent off-by-one when an action is deleted after another was appended.
  • All DOM lookups remain scoped to elements the plugin owns (settingEl.querySelector(...), ifHeader.querySelector(...)); no global document.querySelector was introduced. No innerHTML, var, or unregistered listeners were added — Obsidian's createEl / createDiv and the Setting / DropdownComponent / ButtonComponent APIs are used throughout, in line with the project's plugin guidelines.

0.20.0 - 2026-05-19

New Features

  • Frontmatter property placeholders in THEN values. Any {propertyName} reference inside a THEN action's value (property add/overwrite/remove, title prefix/suffix/overwrite) is now expanded to the live value of that frontmatter property on the note being processed. Example: an action Property excerpt = Add value {g_excerpt} copies the contents of g_excerpt into excerpt.
  • Missing properties expand to an empty string — no error, no literal {name} left behind.
  • Array values are joined with , so a multi-valued source like tags produces a readable string.
  • The reserved placeholders {date}, {date:FORMAT}, and {filename} keep their existing meaning; they're resolved first and never collide with property lookups.

Internal

  • _formatText(text, file) now takes an optional third argument fm (the in-progress frontmatter snapshot). All four call sites inside applyRulesToFrontmatter pass newFm, so a later action in the same rule sees the writes performed by earlier actions. When fm is omitted, the helper falls back to metadataCache.getFileCache(file).frontmatter.
  • Placeholder resolution is now a two-pass replace: pass 1 handles {date}/{filename}; pass 2 treats any other {name} token as a frontmatter lookup. The pass-2 regex excludes : and whitespace, so a malformed {date:FORMAT} survivor would not be mistaken for a property name.

Why

Users storing canonical content in one property (g_excerpt, g_title, summary, ...) and needing to project it onto another (excerpt, description, ...) previously had to copy by hand. This closes that gap without inventing a new action type — the existing add/overwrite/title actions just gained a richer expansion grammar.