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-hiddenclass. - Add rule appends the new rule's
wrapright 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). - Changing the Scan scope no longer rebuilds the page — the "Notes to scan" row is now created once and toggled via an
Internal
- Eliminated dead code (
_updateValueInputState, never called). - Removed the unused
ruleIdxparameter from_renderThenActionand 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 onruleCtx:ruleCtx.matchWrapEl— the Match dropdown element,nullwhen absent.ruleCtx.removeBtnByCondition—WeakMap<Setting, HTMLElement>mapping each condition'sSettinginstance to its ✕ button element.ruleCtx.actionEntries— array of{ el, setting }per action row, so reindexing and rebuilds use theSettinginstance 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 fulldisplay(). - Added an
is-hiddenutility class instyles.cssso visibility toggles stay in CSS instead of being scattered as inlinestyle.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'swrapelement is now detached in place; the other rules stay exactly where they were on screen.
Internal
- The Remove handler unsubscribes the rule's
onScanStateChangelistener and prunes it from_scanStateUnsubscribersbefore detaching the DOM, so removed rules don't leave dangling subscribers behind. - Both
Run this ruleandRemoveresolve the rule's current index viaArray#indexOf(rule)at click time instead of trusting theidxcaptured 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 theSettinginstance, and when a rule drops back to a single condition theMatch (any/all)dropdown and the last Remove ✕ are stripped without re-rendering.
Internal
- Introduced a per-rule
ruleCtxobject ({ 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
Settinginstances sosetName()is enough to reindex; action wraps are tracked as their root elements and reindexed via a scopedquerySelectorfor.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 (theSettingand the wrapdiv), so callers can insert them at a precise position without resorting tolastElementChildor 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 viaArray#indexOfinstead of capturing it in a closure, so removals stay correct after subsequent additions. - Remove handler for actions does the same
indexOflookup, 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 globaldocument.querySelectorwas introduced. NoinnerHTML,var, or unregistered listeners were added — Obsidian'screateEl/createDivand theSetting/DropdownComponent/ButtonComponentAPIs 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 actionProperty excerpt = Add value {g_excerpt}copies the contents ofg_excerptintoexcerpt. - Missing properties expand to an empty string — no error, no literal
{name}left behind. - Array values are joined with
,so a multi-valued source liketagsproduces 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 argumentfm(the in-progress frontmatter snapshot). All four call sites insideapplyRulesToFrontmatterpassnewFm, so a later action in the same rule sees the writes performed by earlier actions. Whenfmis omitted, the helper falls back tometadataCache.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.