👏

Obsidian Templaterスニペット集:効率的なナレッジベース構築のために

2025/04/08に公開

ObsidianのTemplaterプラグインを活用した便利なスニペットまとめておく。

目次

  1. コールアウト選択
  2. Dataviewクエリ生成
  3. テーブル作成
  4. タグ選択
  5. 文字カウント
  6. コードブロック挿入
  7. フローチャート作成
  8. ガントチャート作成
  9. マインドマップ作成
  10. スニペットの導入方法

コールアウト選択

Obsidianのコールアウトを簡単に挿入できるスニペット。カラーグループ別に整理されたコールアウトタイプから選択できる。

<%*
// Choose a callout from a suggester
// Grouped by color
const types = ["🟦", "Note", "Abstract", "Summary", "TLDR", "Info", "Todo", "Tip", "Hint", "Important", "🟩", "Success", "Check", "Done", "Question", "Help", "FAQ", "🟨", "Warning", "Caution", "Attention", "🟧", "Failure", "Fail", "Missing", "🟥", "Danger", "Error", "Bug", "🟪", "Example", "⬛️", "Quote", "Cite"];
const callouts = ["Blue", "> [!note]", "> [!abstract]", "> [!summary]", "> [!tldr]", "> [!info]", "> [!todo]", "> [!tip]", "> [!hint]", "> [!important]", "Green", "> [!success]", "> [!check]", "> [!done]", "> [!question]", "> [!help]", "> [!faq]", "Yellow", "> [!warning]", "> [!caution]", "> [!attention]", "Orange", "> [!failure]", "> [!fail]", "> [!missing]", "Red", "> [!danger]", "> [!error]", "> [!bug]", "Pink", "> [!example]", "Black", "> [!quote]", "> [!cite]"];
let suggest = await tp.system.suggester(types, callouts);
if (suggest == "null" || /Blue|Green|Yellow|Orange|Red|Pink|Black/.test(suggest)) {return ""};
return suggest;
%>

Dataviewクエリ生成

Dataviewクエリを対話的に作成するスニペット。クエリのタイプ、検索範囲、条件、ソート順などを順に設定できる。

<%*
// Generate a customized Dataview query
const queryType = await tp.system.suggester(["TABLE", "LIST", "TASK"], ["TABLE", "LIST", "TASK"]);
const folder = await tp.system.prompt("検索対象フォルダ(例:20_Memo)", "");
let conditions = [];

// Ask for conditions
let addCondition = true;
while (addCondition) {
  const field = await tp.system.prompt("フィールド名(例:status)", "");
  if (field) {
    const operator = await tp.system.suggester(["=", "!=", ">", "<", "contains"], ["=", "!=", ">", "<", "contains"]);
    const value = await tp.system.prompt("値", "");
    conditions.push(`${field} ${operator} "${value}"`);
    addCondition = await tp.system.suggester(["条件を追加", "完了"], [true, false]);
  } else {
    addCondition = false;
  }
}

// Generate query
let query = "```dataview\n" + queryType + "\n";

if (queryType === "TABLE") {
  const fields = await tp.system.prompt("表示するフィールド(カンマ区切り、空白で全て表示)", "");
  if (fields) {
    query += fields.split(",").map(f => f.trim()).join(", ") + "\n";
  }
}

query += `FROM "${folder}"\n`;

if (conditions.length > 0) {
  query += "WHERE " + conditions.join(" AND ") + "\n";
}

const sortField = await tp.system.prompt("ソートするフィールド(空白でソートなし)", "");
if (sortField) {
  const sortOrder = await tp.system.suggester(["昇順", "降順"], ["ASC", "DESC"]);
  query += `SORT ${sortField} ${sortOrder}\n`;
}

query += "```";
return query;
%>

テーブル作成

カスタムサイズのマークダウンテーブルを簡単に作成できるスニペット。行数、列数、各列の見出しを指定できる。

<%*
// Create a table with custom dimensions and headers
const rows = parseInt(await tp.system.prompt("行数を入力", "3"));
const cols = parseInt(await tp.system.prompt("列数を入力", "3"));

// Generate header prompts
let headers = [];
for (let i = 0; i < cols; i++) {
  const header = await tp.system.prompt(`${i+1}列目の見出し`, `見出し${i+1}`);
  headers.push(header);
}

// Create header row
let table = "| " + headers.join(" | ") + " |\n";

// Create separator row
table += "|" + headers.map(() => "---").join("|") + "|\n";

// Create content rows
for (let i = 0; i < rows; i++) {
  let row = "|";
  for (let j = 0; j < cols; j++) {
    row += " |";
  }
  table += row + "\n";
}

return table;
%>

タグ選択

既存のタグをインテリジェントに提案するスニペット。同じフォルダ内のファイルに付けられたタグや使用頻度の高いタグが優先的に表示される。

<%*
// 頻出タグと同フォルダタグを優先表示するスニペット
try {
  // 現在のファイルのパスとフォルダを取得
  const currentFilePath = tp.file.path(true);
  const currentFolder = currentFilePath.substring(0, currentFilePath.lastIndexOf('/'));
  
  // タグのリストとその出現回数を保持するオブジェクト
  const tagObj = app.metadataCache.getTags();
  const tagCounts = {};
  const folderTags = new Set();
  
  // すべてのマークダウンファイルをループ
  const files = app.vault.getMarkdownFiles();
  for (const file of files) {
    // ファイルのキャッシュを取得
    const fileCache = app.metadataCache.getFileCache(file);
    if (!fileCache || !fileCache.tags) continue;
    
    // このファイルのすべてのタグを処理
    for (const tagObj of fileCache.tags) {
      const tag = tagObj.tag;
      // タグの出現回数をカウント
      if (!tagCounts[tag]) {
        tagCounts[tag] = 1;
      } else {
        tagCounts[tag]++;
      }
      
      // 同じフォルダにあるファイルのタグをマーク
      if (file.path.startsWith(currentFolder + '/')) {
        folderTags.add(tag);
      }
    }
  }
  
  // タグをリストに変換し、#を削除
  let tags = Object.keys(tagCounts).map(tag => {
    return {
      name: tag.replace('#', ''),
      count: tagCounts[tag],
      inFolder: folderTags.has(tag)
    };
  });
  
  // タグをソート:同フォルダのタグを優先し、次に出現回数で降順ソート
  tags.sort((a, b) => {
    // 同フォルダのタグを優先
    if (a.inFolder && !b.inFolder) return -1;
    if (!a.inFolder && b.inFolder) return 1;
    
    // 同じフォルダ状態なら出現回数で降順ソート
    return b.count - a.count;
  });
  
  // 表示用のタグ名リストと、実際のタグ名リストを作成
  const tagDisplayNames = tags.map(tag => {
    let displayName = tag.name;
    // 同フォルダのタグには🔷マーク、頻出タグには回数を表示
    if (tag.inFolder) {
      displayName = `🔷 ${displayName}`;
    }
    return `${displayName} (${tag.count})`;
  });
  
  const tagNames = tags.map(tag => tag.name);
  
  // タグがない場合の処理
  if (tagNames.length === 0) {
    new Notice("タグが見つかりませんでした");
    return "タグが見つかりません。先にいくつかのノートにタグを追加してください。";
  }
  
  // 選択したタグを保存する配列
  const selectedTags = [];
  let continue_adding = true;
  
  // タグを選択するループ
  while (continue_adding) {
    // タグを選択(表示名をsuggeseterに表示、実際の値としてtagNamesを取得)
    const selectedTag = await tp.system.suggester(tagDisplayNames, tagNames);
    
    // 有効なタグが選択された場合
    if (selectedTag !== null) {
      selectedTags.push(selectedTag);
      // さらにタグを追加するか確認
      continue_adding = await tp.system.suggester(
        ["タグを追加", "完了"], 
        [true, false]
      );
    } else {
      // キャンセルされた場合
      continue_adding = false;
    }
  }
  
  // 選択されたタグを返す
  if (selectedTags.length > 0) {
    return selectedTags.map(t => '#' + t).join(' ');
  } else {
    return "";  // タグが選択されなかった場合
  }
} catch (error) {
  // エラーが発生した場合
  console.error("タグ選択エラー:", error);
  new Notice("タグの取得中にエラーが発生しました: " + error.message);
  return "エラーが発生しました。コンソールを確認してください。";
}
%>

文字カウント

選択したテキストやクリップボード内のテキストの文字数、単語数、行数を計測するスニペット。

<%*
// Count characters, words, and lines in selected text
const text = await tp.system.clipboard();
if (!text) {
  return "テキストをクリップボードにコピーしてから実行してください";
}

const charCount = text.length;
const wordCount = text.split(/\s+/).filter(word => word.length > 0).length;
const lineCount = text.split(/\r\n|\r|\n/).length;

return `
> [!info]+ テキスト統計
> - 文字数: ${charCount}
> - 単語数: ${wordCount}
> - 行数: ${lineCount}
`;
%>

コードブロック挿入

言語を選択してコードブロックを挿入するスニペット。

<%*
// Insert a code block with language selection
const languages = ["javascript", "python", "java", "c", "cpp", "csharp", "php", "ruby", "go", "rust", "typescript", "bash", "sql", "html", "css", "json", "yaml", "markdown", "plaintext"];
const language = await tp.system.suggester(languages, languages);
if (!language) return "";

return "```" + language + "\n\n```";
%>

フローチャート作成

Mermaidフローチャートのテンプレートを挿入するスニペット。基本的なフローチャート構造を素早く作成できる。

<%*
// Insert a Mermaid flowchart template
const direction = await tp.system.suggester(
  ["上から下 (TD)", "左から右 (LR)"], 
  ["TD", "LR"]
);
if (!direction) return "";

const nodeCount = parseInt(await tp.system.prompt("ノード数", "3"));
let flowchart = "```mermaid\nflowchart " + direction + "\n";

// Add nodes
for (let i = 1; i <= nodeCount; i++) {
  flowchart += `    Node${i}[ノード${i}]\n`;
}

// Add connections
for (let i = 1; i < nodeCount; i++) {
  flowchart += `    Node${i} --> Node${i+1}\n`;
}

flowchart += "```";
return flowchart;
%>

ガントチャート作成

Mermaidガントチャートのテンプレートを挿入するスニペット。タイトルとタスク数を指定し、各タスクの名前と期間を入力することで、ガントチャートを生成する。デフォルトでは、タスクは順番に開始するように設定されている。

<%*
// Insert a Mermaid Gantt chart template
const title = await tp.system.prompt("チャートのタイトル", "プロジェクトスケジュール");
const taskCount = parseInt(await tp.system.prompt("タスク数", "3"));

let gantt = "```mermaid\ngantt\n";
gantt += `    title ${title}\n`;
gantt += "    dateFormat YYYY-MM-DD\n";
gantt += "    section セクション1\n";

// Get today's date
const today = moment().format("YYYY-MM-DD");

// Add tasks
for (let i = 1; i <= taskCount; i++) {
  const taskName = await tp.system.prompt(`タスク${i}の名前`, `タスク${i}`);
  const duration = await tp.system.prompt(`タスク${i}の期間(日数)`, "7");
  
  if (i === 1) {
    gantt += `    ${taskName} :a${i}, ${today}, ${duration}d\n`;
  } else {
    gantt += `    ${taskName} :a${i}, after a${i-1}, ${duration}d\n`;
  }
}

gantt += "```";
return gantt;
%>

マインドマップ作成

Mermaidマインドマップのテンプレートを挿入するスニペット。中心トピック、ブランチ数、サブブランチの有無を指定することで、構造化されたマインドマップを生成する。

<%*
// Insert a Mermaid mindmap template
const rootTopic = await tp.system.prompt("中心トピック", "メインテーマ");
const mainBranchCount = parseInt(await tp.system.prompt("主要ブランチ数", "3"));

let mindmap = "```mermaid\nmindmap\n";
mindmap += `  root((${rootTopic}))\n`;

// Add main branches
for (let i = 1; i <= mainBranchCount; i++) {
  const branchName = await tp.system.prompt(`ブランチ${i}の名前`, `トピック${i}`);
  mindmap += `    ${branchName}\n`;
  
  // Ask if sub-branches are needed
  const addSubBranches = await tp.system.suggester(["サブブランチを追加", "次のブランチへ"], [true, false]);
  if (addSubBranches) {
    const subBranchCount = parseInt(await tp.system.prompt(`${branchName}のサブブランチ数`, "2"));
    for (let j = 1; j <= subBranchCount; j++) {
      const subBranchName = await tp.system.prompt(`サブブランチ${j}の名前`, `サブトピック${j}`);
      mindmap += `      ${subBranchName}\n`;
    }
  }
}

mindmap += "```";
return mindmap;
%>

スニペットの導入方法

Templaterスニペットを利用するには、以下の手順に従う:

  1. Obsidianで「Templater」プラグインをインストールし有効化する
  2. スニペットを保存するテンプレートファイルを作成する
    • 設定 > Templater > Template folder location で指定したフォルダにファイルを作成
    • 例:snippets.mdという名前でファイルを作成し、上記のスニペットを保存
  3. スニペットを呼び出す
    • コマンドパレット(Ctrl+P または Cmd+P)を開く
    • 「Templater: Open Insert Template modal」を選択
    • 作成したスニペットテンプレートを選択

より効率的に使うためには、Templaterコマンドにホットキーを設定したり、テンプレートフォルダを整理したりするとよい。


本記事はClaude 3.7 Sonnetを使用して作成された。

Discussion