Skip to content

Conversation

@chhoumann
Copy link
Owner

@chhoumann chhoumann commented Dec 26, 2025

Summary

  • add insertion mode for Template choices with placement and template source selection
  • insert template content into active note with frontmatter merging and post-processing
  • adjust preflight to skip creation-only inputs when inserting

Testing

  • not run (not requested)

Closes #526

Summary by CodeRabbit

  • New Features

    • Insert templates directly into the active note with configurable placement (top, bottom, cursor, after selection, new-line above/below).
    • Select template source: fixed path, prompt at runtime, or reuse another template choice; UI allows switching and runtime prompting.
    • Template YAML frontmatter is detected and merged into the active note (deep-merge objects, concatenate arrays, overwrite scalars); some file-creation settings are ignored when inserting.
  • Documentation

    • Expanded TemplateChoice docs covering insertion behavior, placement options, source selection, frontmatter merging, and file name formatting.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
quickadd Ready Ready Preview Dec 27, 2025 0:08am

@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

📝 Walkthrough

Walkthrough

Adds an "insert into active note" feature for Template choices: selectable template sources (fixed path, prompt, or another Template choice), multiple insertion placements (cursor/selection/lines/top/bottom), optional YAML frontmatter merging into the active file, and supporting UI, engine, and type changes.

Changes

Cohort / File(s) Summary
Documentation
docs/docs/Choices/TemplateChoice.md
Expanded docs: clarify when Template Path is required; add "Insert into active note", insertion placements, template source options, and YAML frontmatter merging note.
Types
src/types/choices/ITemplateChoice.ts, src/types/choices/TemplateChoice.ts
Add TemplateInsertionPlacement, TemplateInsertionSourceType, TemplateInsertionSource, TemplateInsertionConfig, DEFAULT_TEMPLATE_INSERTION, normalizeTemplateInsertionConfig; add insertion property to ITemplateChoice and TemplateChoice.
Engine — TemplateChoice
src/engine/TemplateChoiceEngine.ts
New insertion flow and helpers: resolve template path (path/prompt/choice), run insertion path (validate active markdown, templater-format template, split YAML frontmatter using FRONTMATTER_REGEX, merge frontmatter into active file, and insert body at top/bottom or into editor for various placements); added prompt/choice helpers, frontmatter merge utilities, and insertion helpers.
Engine — Template
src/engine/TemplateEngine.ts
Added protected async formatTemplateForFile(templatePath, targetFile) returning formatted content and captured template variables.
UI Builder
src/gui/ChoiceBuilder/templateChoiceBuilder.ts
New insertion UI controls: normalize insertion config, enable/disable insertion, placement selector, template source selector (path/prompt/choice), conditional visibility for file-creation settings, and handling for cross-choice template selection.
Preflight / Validation
src/preflight/runOnePagePreflight.ts
Integrate insertion config into preflight: compute insertionEnabled, resolve templatePath when insertion is enabled (path/choice/prompt), and gate filename format and folder scanning accordingly.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as UI Builder
    participant Engine as TemplateChoiceEngine
    participant TplEngine as TemplateEngine
    participant Editor as Active Editor/File

    User->>UI: Enable "Insert into active note" & choose source/placement
    UI->>Engine: run(choice with insertion config)

    rect rgb(245,250,255)
      Engine->>Engine: Validate active Markdown file
      Engine->>Engine: Resolve template path (fixed / prompt / choice)
      alt Source = prompt
        Engine->>User: Prompt for template path
        User-->>Engine: Template path
      else Source = choice
        Engine->>User: Suggest template choices
        User-->>Engine: Selected template path
      end
      Engine->>TplEngine: formatTemplateForFile(templatePath, targetFile)
      TplEngine-->>Engine: formatted content + templateVars
      Engine->>Engine: splitFrontmatter(content) / applyFrontmatterProperties()
    end

    rect rgb(235,255,235)
      alt Placement = top/bottom
        Engine->>Engine: insertBodyAtTop/insertBodyAtBottom()
        Engine->>Editor: Replace file content (merge frontmatter/body)
      else Other placements
        Engine->>Engine: insertBodyIntoEditor(placement)
        Engine->>Editor: Insert at cursor/selection/line
      end
    end

    Editor-->>User: Active note updated with inserted template
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped in quick and found my place,
Pasted templates with a joyful pace.
Frontmatter hugged the note so tight,
Cursor danced and stitched it right.
🥕 Hooray — a tidy template chase!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: insert template into active note' directly and clearly describes the main feature added in the PR: enabling template insertion into an already-open note.
Linked Issues check ✅ Passed All core objectives from issue #526 are met: the PR adds template insertion into the active note with template/choice selection, supports frontmatter merging, and adjusts preflight behavior for inserts.
Out of Scope Changes check ✅ Passed All changes are in-scope: documentation updates, insertion workflow implementation, template path resolution, frontmatter handling, UI builder changes, preflight adjustments, and supporting types/interfaces—all directly related to the insertion feature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 526

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83a7718 and ca1b0f5.

📒 Files selected for processing (2)
  • docs/docs/Choices/TemplateChoice.md
  • src/preflight/runOnePagePreflight.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/docs/Choices/TemplateChoice.md
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,mjs,js,json}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,mts,mjs,js,json}: Use tab indentation with width 2 in TypeScript and configuration files (enforced by Biome).
Follow an 80-character line guide (enforced by Biome).

Files:

  • src/preflight/runOnePagePreflight.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use camelCase for variables and functions in TypeScript.
Prefer type-only imports in TypeScript.

Files:

  • src/preflight/runOnePagePreflight.ts
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components.

Files:

  • src/preflight/runOnePagePreflight.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Route logging through the logger utilities for consistent output.

Files:

  • src/preflight/runOnePagePreflight.ts
🧬 Code graph analysis (1)
src/preflight/runOnePagePreflight.ts (2)
src/types/choices/ITemplateChoice.ts (2)
  • normalizeTemplateInsertionConfig (35-47)
  • ITemplateChoice (49-76)
src/utils/choiceUtils.ts (1)
  • flattenChoices (11-23)
🔇 Additional comments (5)
src/preflight/runOnePagePreflight.ts (5)

14-14: LGTM: Imports are correctly structured.

The new imports support the insertion mode feature and are appropriately scoped.

Also applies to: 24-24


54-56: LGTM: Creation-only inputs correctly gated.

The logic appropriately skips file name format and folder collection when insertion mode is enabled, since these are only relevant for file creation.

Also applies to: 59-63


94-94: LGTM: Explicit conditional improves clarity.

The explicit if (templatePath) check is more readable than an implicit truthy test and correctly handles the undefined case from the resolution logic above.


50-51: No issues found. The normalizeTemplateInsertionConfig function has correct syntax with no compilation errors. The code at lines 50-51 is valid and works as intended.

Likely an incorrect or invalid review comment.


66-92: Silent failure on template lookup is by design; clarify preflight vs. execution phases.

The three edge cases mentioned are either intentional patterns or UI-level concerns:

  1. Choice not found (lines 76-81): When a referenced template choice isn't found, templatePath becomes undefined. This is intentional—the entire preflight function silently fails on errors (lines 319-325), and undefined template paths are handled gracefully by the conditional guard at line 93. The preflight phase only collects requirements without executing or prompting users.

  2. Name collision (lines 76-79): The find() returns the first match, but this is a UI-level concern. Users actively select which template to reference via the template builder UI (templateChoiceBuilder.ts), so the code matches the user's selection rather than discovering templates automatically. If users want to avoid collisions, they can select by ID instead of name.

  3. Prompt with pre-filled value (line 89): For type: "prompt", using insertion.templateSource.value ?? undefined is correct. In the preflight phase, this preserves any pre-filled value; the actual user prompt occurs during execution (TemplateChoiceEngine.ts), where promptForTemplatePath() is called. This separation is intentional: preflight collects requirements, execution handles user interaction.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/preflight/runOnePagePreflight.ts (1)

94-107: Bug: Uses choice.templatePath instead of computed templatePath variable.

After computing the correct templatePath based on the insertion source type (lines 66-92), the walk function on line 106 incorrectly uses choice.templatePath instead of the computed templatePath. This causes the preflight to scan the wrong template when insertion is enabled with a different template source.

🔎 Proposed fix
 	if (templatePath) {
 		const visited = new Set<string>();
 		const walk = async (path: string) => {
 			if (visited.has(path)) return;
 			visited.add(path);
 			const content = await readTemplate(app, path);
 			await collector.scanString(content);
 			for (const nested of collector.templatesToScan) {
 				if (!visited.has(nested)) await walk(nested);
 			}
 			collector.templatesToScan.clear();
 		};
-		await walk(choice.templatePath);
+		await walk(templatePath);
 	}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 786b53c and b4cd53d.

📒 Files selected for processing (7)
  • docs/docs/Choices/TemplateChoice.md
  • src/engine/TemplateChoiceEngine.ts
  • src/engine/TemplateEngine.ts
  • src/gui/ChoiceBuilder/templateChoiceBuilder.ts
  • src/preflight/runOnePagePreflight.ts
  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,mts,mjs,js,json}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,mts,mjs,js,json}: Use tab indentation with width 2 in TypeScript and configuration files (enforced by Biome).
Follow an 80-character line guide (enforced by Biome).

Files:

  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts
  • src/engine/TemplateEngine.ts
  • src/gui/ChoiceBuilder/templateChoiceBuilder.ts
  • src/preflight/runOnePagePreflight.ts
  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use camelCase for variables and functions in TypeScript.
Prefer type-only imports in TypeScript.

Files:

  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts
  • src/engine/TemplateEngine.ts
  • src/gui/ChoiceBuilder/templateChoiceBuilder.ts
  • src/preflight/runOnePagePreflight.ts
  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components.

Files:

  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts
  • src/engine/TemplateEngine.ts
  • src/gui/ChoiceBuilder/templateChoiceBuilder.ts
  • src/preflight/runOnePagePreflight.ts
  • src/engine/TemplateChoiceEngine.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Route logging through the logger utilities for consistent output.

Files:

  • src/types/choices/ITemplateChoice.ts
  • src/types/choices/TemplateChoice.ts
  • src/engine/TemplateEngine.ts
  • src/gui/ChoiceBuilder/templateChoiceBuilder.ts
  • src/preflight/runOnePagePreflight.ts
  • src/engine/TemplateChoiceEngine.ts
src/{engine,services,utils}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Structure production code so Obsidian dependencies are injected behind interfaces to enable unit testing without loading real Obsidian modules.

Files:

  • src/engine/TemplateEngine.ts
  • src/engine/TemplateChoiceEngine.ts
🧬 Code graph analysis (4)
src/types/choices/TemplateChoice.ts (1)
src/types/choices/ITemplateChoice.ts (2)
  • ITemplateChoice (49-76)
  • DEFAULT_TEMPLATE_INSERTION (29-33)
src/engine/TemplateEngine.ts (1)
tests/obsidian-stub.ts (1)
  • TFile (332-338)
src/preflight/runOnePagePreflight.ts (2)
src/types/choices/ITemplateChoice.ts (2)
  • normalizeTemplateInsertionConfig (35-47)
  • ITemplateChoice (49-76)
src/utils/choiceUtils.ts (1)
  • flattenChoices (11-23)
src/engine/TemplateChoiceEngine.ts (7)
src/types/choices/ITemplateChoice.ts (4)
  • ITemplateChoice (49-76)
  • normalizeTemplateInsertionConfig (35-47)
  • TemplateInsertionConfig (23-27)
  • TemplateInsertionPlacement (6-14)
src/errors/MacroAbortError.ts (1)
  • MacroAbortError (1-6)
src/utils/invariant.ts (1)
  • invariant (1-10)
src/utilityObsidian.ts (1)
  • templaterParseTemplate (390-410)
src/gui/InputSuggester/inputSuggester.ts (1)
  • InputSuggester (22-195)
src/utils/choiceUtils.ts (1)
  • flattenChoices (11-23)
src/types/linkPlacement.ts (1)
  • LinkPlacement (4-8)
🔇 Additional comments (18)
src/engine/TemplateEngine.ts (1)

546-564: LGTM!

The new formatTemplateForFile method cleanly encapsulates template loading and formatting logic for the insertion workflow. It follows the same pattern as createFileWithTemplate but appropriately omits file creation, making it reusable for inserting into existing files.

src/types/choices/ITemplateChoice.ts (2)

6-47: LGTM!

The new types are well-structured and the normalization function correctly handles partial or undefined configurations with sensible defaults. The use of nullish coalescing ensures proper fallback behavior.


74-75: LGTM!

The optional insertion field cleanly extends the interface without breaking existing configurations.

src/types/choices/TemplateChoice.ts (1)

52-56: LGTM!

Good use of the spread operator for templateSource to create a shallow copy, avoiding shared references between instances.

docs/docs/Choices/TemplateChoice.md (1)

13-38: LGTM!

The documentation clearly explains the new insertion feature, including placement options, template sources, and which settings are ignored when insertion is enabled. The YAML frontmatter merging behavior is well-documented.

src/preflight/runOnePagePreflight.ts (1)

50-63: LGTM!

Correctly gates the file name format and folder scanning behind insertionEnabled, since these settings are not applicable when inserting into an active note.

src/gui/ChoiceBuilder/templateChoiceBuilder.ts (4)

97-100: LGTM!

The ensureInsertionConfig method properly normalizes the insertion config and assigns it back to the choice, ensuring consistent state.


102-137: LGTM!

The insertion toggle and placement dropdown are well-implemented. The reload() call ensures the UI updates correctly when the enabled state changes.


139-163: LGTM!

The template source setting correctly clears templateSource.value when switching away from the "choice" type, preventing stale references. The reload() call ensures the UI reflects the new state.


165-204: LGTM!

Good handling of edge cases: displaying a message when no template choices are available, and preserving unknown current values in the dropdown to prevent data loss if a referenced choice was deleted.

src/engine/TemplateChoiceEngine.ts (8)

46-47: LGTM!

The regex correctly handles YAML frontmatter with both --- and ... closing delimiters, and supports both LF and CRLF line endings.


226-289: LGTM!

The runInsertion method is well-structured:

  • Validates active file is a Markdown note before proceeding
  • Correctly handles frontmatter merging separately from body insertion
  • Uses appropriate file modification vs. editor insertion based on placement type
  • Properly triggers post-processing for template variables

291-319: LGTM!

The template path resolution correctly handles all three source types with proper cancellation error handling that converts to MacroAbortError.


321-368: LGTM!

The choice resolution logic correctly falls back to prompting the user when the specified choice ID/name is not found, providing a graceful degradation path.


370-406: LGTM!

The frontmatter splitting and merging logic is correct:

  • splitFrontmatter properly extracts the YAML content without the delimiters
  • applyFrontmatterInsertion preserves existing frontmatter structure while appending new content

408-427: LGTM!

insertBodyAtTop correctly uses findYamlFrontMatterRange to insert content after any existing frontmatter, and insertBodyAtBottom appends with proper newline handling.


462-480: LGTM!

The joinWithNewlines helper correctly ensures single newlines between content segments without creating double newlines.


429-460: No functional issue here. The insertLinkWithPlacement function handles arbitrary content correctly—it contains no link-specific logic. All three code paths it receives (replaceSelection, afterSelection, endOfLine) use generic editor operations (replaceSelection() and replaceRange()) with no constraints on content type. The naming is misleading, but the implementation is intentionally generic for text insertion.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/engine/TemplateChoiceEngine.ts (3)

18-23: Consider using type-only imports for type definitions.

Per coding guidelines, prefer type-only imports in TypeScript. TemplateInsertionConfig, TemplateInsertionPlacement, and LinkPlacement appear to be used only as types.

🔎 Suggested change
 import {
 	normalizeTemplateInsertionConfig,
-	type TemplateInsertionConfig,
-	type TemplateInsertionPlacement,
 } from "../types/choices/ITemplateChoice";
-import { normalizeAppendLinkOptions, type LinkPlacement } from "../types/linkPlacement";
+import type {
+	TemplateInsertionConfig,
+	TemplateInsertionPlacement,
+} from "../types/choices/ITemplateChoice";
+import { normalizeAppendLinkOptions } from "../types/linkPlacement";
+import type { LinkPlacement } from "../types/linkPlacement";

236-240: Invariant error message has unreachable condition.

The ternary check templatePath?.length === 0 will never be true because if templatePath is falsy, the invariant fails and this message is constructed. If templatePath is an empty string (length 0), the invariant still fails but the optional chaining makes the condition evaluate correctly. However, if templatePath is undefined, templatePath?.length is undefined, not 0, so the condition is false and no helpful message is shown.

Consider simplifying:

🔎 Suggested change
 invariant(templatePath, () => {
-	return `Invalid template path for ${this.choice.name}. ${
-		templatePath?.length === 0 ? "Template path is empty." : ""
-	}`;
+	return `Invalid template path for ${this.choice.name}. Template path is empty or undefined.`;
 });

460-462: Consider using MacroAbortError for consistency.

The default case throws a generic Error, but other validation failures in this file throw MacroAbortError. For consistency in error handling upstream, consider using the same error type.

🔎 Suggested change
 		default:
-			throw new Error(`Unknown insertion placement: ${placement}`);
+			throw new MacroAbortError(`Unknown insertion placement: ${placement}`);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4cd53d and 930ae2d.

📒 Files selected for processing (1)
  • src/engine/TemplateChoiceEngine.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,mts,mjs,js,json}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,mts,mjs,js,json}: Use tab indentation with width 2 in TypeScript and configuration files (enforced by Biome).
Follow an 80-character line guide (enforced by Biome).

Files:

  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use camelCase for variables and functions in TypeScript.
Prefer type-only imports in TypeScript.

Files:

  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components.

Files:

  • src/engine/TemplateChoiceEngine.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Route logging through the logger utilities for consistent output.

Files:

  • src/engine/TemplateChoiceEngine.ts
src/{engine,services,utils}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Structure production code so Obsidian dependencies are injected behind interfaces to enable unit testing without loading real Obsidian modules.

Files:

  • src/engine/TemplateChoiceEngine.ts
🧬 Code graph analysis (1)
src/engine/TemplateChoiceEngine.ts (3)
src/types/choices/ITemplateChoice.ts (3)
  • ITemplateChoice (49-76)
  • TemplateInsertionConfig (23-27)
  • TemplateInsertionPlacement (6-14)
src/utilityObsidian.ts (1)
  • templaterParseTemplate (390-410)
src/types/linkPlacement.ts (1)
  • LinkPlacement (4-8)
🔇 Additional comments (10)
src/engine/TemplateChoiceEngine.ts (10)

46-47: Verify frontmatter regex allows leading whitespace intentionally.

The regex permits leading whitespace (\s*) before the opening ---. Standard YAML frontmatter typically requires --- at position 0 (start of file). This could match non-frontmatter content if there's accidental leading whitespace.

If this is intentional for flexibility, consider adding a comment explaining the design choice.


60-66: LGTM!

Clean early return pattern for insertion mode that properly short-circuits the normal template creation flow.


276-290: LGTM!

Clean switch statement for resolving template path with appropriate fallback to the choice's configured template path.


306-353: LGTM!

Well-structured method with proper validation, user-friendly display items that show template paths for disambiguation, and consistent error handling for cancellation.


355-368: LGTM!

Clean implementation that correctly handles both cases: content with and without frontmatter.


370-409: LGTM!

Robust implementation with proper YAML parsing validation and graceful error handling. Using processFrontMatter ensures proper atomic updates to the file's frontmatter.


411-422: LGTM!

Correctly inserts body content after any existing frontmatter, preserving the file structure.


424-430: LGTM!

Simple and correct implementation for appending content at the bottom.


465-483: LGTM!

Well-designed utility that handles edge cases properly, avoiding double newlines while ensuring proper separation between content sections.


292-304: LGTM!

Proper error handling pattern with cancellation detection, consistent with the rest of the codebase.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/engine/TemplateChoiceEngine.ts (1)

413-430: Array merge concatenates without deduplication.

Line 418 concatenates arrays: [...existing, ...incoming]. If a user runs insertion multiple times with the same tags/aliases, duplicates will accumulate. If this is intentional for additive behavior, it's fine; otherwise, consider deduplicating:

🔎 Optional: Deduplicate primitive arrays
 if (Array.isArray(existing) && Array.isArray(incoming)) {
-  return [...existing, ...incoming];
+  const merged = [...existing, ...incoming];
+  // Deduplicate primitives only
+  if (merged.every((v) => typeof v !== "object")) {
+    return [...new Set(merged)];
+  }
+  return merged;
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 930ae2d and 83a7718.

📒 Files selected for processing (1)
  • src/engine/TemplateChoiceEngine.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,mts,mjs,js,json}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,mts,mjs,js,json}: Use tab indentation with width 2 in TypeScript and configuration files (enforced by Biome).
Follow an 80-character line guide (enforced by Biome).

Files:

  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use camelCase for variables and functions in TypeScript.
Prefer type-only imports in TypeScript.

Files:

  • src/engine/TemplateChoiceEngine.ts
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components.

Files:

  • src/engine/TemplateChoiceEngine.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Route logging through the logger utilities for consistent output.

Files:

  • src/engine/TemplateChoiceEngine.ts
src/{engine,services,utils}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Structure production code so Obsidian dependencies are injected behind interfaces to enable unit testing without loading real Obsidian modules.

Files:

  • src/engine/TemplateChoiceEngine.ts
🔇 Additional comments (6)
src/engine/TemplateChoiceEngine.ts (6)

1-41: LGTM!

Imports are well-organized and appropriate for the new insertion functionality. Type imports are properly used where applicable.


46-47: Verify: Leading whitespace allowance in frontmatter regex.

The \s* at the start of the regex allows whitespace before ---. Standard YAML frontmatter requires --- at position 0. If templates with accidental leading whitespace are common, this is fine; otherwise, consider anchoring strictly with ^---\r?\n.


60-67: LGTM!

Clean separation of the insertion flow from the existing template creation flow using an early return pattern.


226-274: LGTM!

The insertion flow is well-structured with proper validation, error handling using MacroAbortError, and a good optimization to skip file modification when content is unchanged (lines 264-266).


276-353: LGTM!

Template path resolution is well-implemented with:

  • Clear fallback chain for path resolution
  • Consistent cancellation error handling across prompts
  • Proper validation that template choices exist and have paths

495-513: LGTM!

The joinWithNewlines utility correctly ensures proper newline separation between content sections without creating double newlines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE SUGGESTION] Insert Template Into Note

2 participants