Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ version: 2
updates:
- package-ecosystem: npm
directory: "/"
target-branch: develop
schedule:
interval: monthly
interval: weekly
open-pull-requests-limit: 10
labels:
- Dependencies
Expand Down
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@

An Obsidian plugin that integrates with GitHub to track issues and pull requests directly in your vault.

The configurations are heavily inspired by https://github.com/schaier-io, including some specific settings. However, I had already started working on my prototype before I discovered the plugin, and had initially even given it a similar name.

>The configurations are heavily inspired by https://github.com/schaier-io, including some specific settings. However, I had already started working on my prototype before I discovered the plugin, and had initially even given it a similar name.

## ✨ Features

- Track issues and pull requests from specific GitHub repositories
- Automatically sync GitHub data on Obsidian startup (configurable)
- Filter tracked items by assignee and reviewers
- Create Markdown notes for each issue or pull request
### 🔄 Issue & Pull Request Tracking
- Track issues and pull requests from multiple GitHub repositories
- Automatically sync GitHub data on startup (configurable)
- Background sync at configurable intervals
- Filter by labels, assignees, and reviewers
- Include or exclude closed issues/PRs
- Automatic cleanup of old closed items

### 📊 GitHub Projects v2 Integration
- Track GitHub Projects across repositories
- Kanban board view for project visualization
- Custom field support (status, priority, iteration)
- Project-specific filtering and organization

### 📝 Markdown Notes
- Create markdown notes for each issue or PR
- Customizable filename templates with variables
- Custom content templates
- YAML frontmatter with metadata
- Preserve user content with persist blocks
- Include comments in notes

## 🚀 Installation

Expand Down Expand Up @@ -43,6 +61,9 @@ The configurations are heavily inspired by https://github.com/schaier-io, includ
3. Click **Add Repository** or **Add Selected Repositories**
4. The plugin will automatically fetch issues from the configured repositories

### ⭐ This repository if you like this project!


## 📄 License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@
"author": "LonoxX",
"license": "MIT",
"devDependencies": {
"@types/node": "^24.9.1",
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/parser": "^8.46.2",
"@types/node": "^25.0.3",
"@typescript-eslint/eslint-plugin": "^8.51.0",
"@typescript-eslint/parser": "^8.51.0",
"builtin-modules": "^5.0.0",
"esbuild": "^0.27.0",
"eslint": "^9.38.0",
"esbuild": "^0.27.2",
"eslint": "^9.39.2",
"obsidian": "latest",
"tslib": "^2.8.1",
"typescript": "^5.9.3"
},
"dependencies": {
"date-fns": "^4.1.0",
"octokit": "^5.0.4",
"prettier": "^3.6.2"
"octokit": "^5.0.5",
"prettier": "^3.7.4"
}
}
58 changes: 45 additions & 13 deletions src/content-generator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { format } from "date-fns";
import { GitHubTrackerSettings, RepositoryTracking } from "./types";
import { GitHubTrackerSettings, RepositoryTracking, ProjectData } from "./types";
import { escapeBody, escapeYamlString } from "./util/escapeUtils";
import {
createIssueTemplateData,
Expand All @@ -21,6 +21,7 @@ export class ContentGenerator {
repo: RepositoryTracking,
comments: any[],
settings: GitHubTrackerSettings,
projectData?: ProjectData[],
): Promise<string> {
// Determine whether to escape hash tags (repo setting takes precedence if ignoreGlobalSettings is true)
const shouldEscapeHashTags = repo.ignoreGlobalSettings ? repo.escapeHashTags : settings.escapeHashTags;
Expand All @@ -35,17 +36,19 @@ export class ContentGenerator {
comments,
settings.dateFormat,
settings.escapeMode,
shouldEscapeHashTags
shouldEscapeHashTags,
projectData
);
return processContentTemplate(templateContent, templateData, settings.dateFormat);
}
}

// Fallback to default template
return `---
let frontmatter = `---
title: "${escapeYamlString(issue.title)}"
number: ${issue.number}
status: "${issue.state}"
state: "${issue.state}"
type: "issue"
created: "${
settings.dateFormat !== ""
? format(new Date(issue.created_at), settings.dateFormat)
Expand All @@ -69,7 +72,19 @@ labels: [${(
) || []
).join(", ")}]
updateMode: "${repo.issueUpdateMode}"
allowDelete: ${repo.allowDeleteIssue ? true : false}
allowDelete: ${repo.allowDeleteIssue ? true : false}`;

// Add projectData if available
if (projectData && projectData.length > 0) {
frontmatter += `
projectData:`;
for (const project of projectData) {
frontmatter += `
- projectId: "${project.projectId}"`;
}
}

frontmatter += `
---

# ${escapeBody(issue.title, settings.escapeMode, false)}
Expand All @@ -79,8 +94,9 @@ ${
: "No description found"
}

${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFormat, shouldEscapeHashTags)}
`;
${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFormat, shouldEscapeHashTags)}`;

return frontmatter;
}

/**
Expand All @@ -91,6 +107,7 @@ ${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFo
repo: RepositoryTracking,
comments: any[],
settings: GitHubTrackerSettings,
projectData?: ProjectData[],
): Promise<string> {
// Determine whether to escape hash tags (repo setting takes precedence if ignoreGlobalSettings is true)
const shouldEscapeHashTags = repo.ignoreGlobalSettings ? repo.escapeHashTags : settings.escapeHashTags;
Expand All @@ -105,17 +122,19 @@ ${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFo
comments,
settings.dateFormat,
settings.escapeMode,
shouldEscapeHashTags
shouldEscapeHashTags,
projectData
);
return processContentTemplate(templateContent, templateData, settings.dateFormat);
}
}

// Fallback to default template
return `---
let frontmatter = `---
title: "${escapeYamlString(pr.title)}"
number: ${pr.number}
status: "${pr.state}"
state: "${pr.state}"
type: "pr"
created: "${
settings.dateFormat !== ""
? format(new Date(pr.created_at), settings.dateFormat)
Expand Down Expand Up @@ -144,7 +163,19 @@ labels: [${(
) || []
).join(", ")}]
updateMode: "${repo.pullRequestUpdateMode}"
allowDelete: ${repo.allowDeletePullRequest ? true : false}
allowDelete: ${repo.allowDeletePullRequest ? true : false}`;

// Add projectData if available
if (projectData && projectData.length > 0) {
frontmatter += `
projectData:`;
for (const project of projectData) {
frontmatter += `
- projectId: "${project.projectId}"`;
}
}

frontmatter += `
---

# ${escapeBody(pr.title, settings.escapeMode, false)}
Expand All @@ -154,7 +185,8 @@ ${
: "No description found"
}

${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFormat, shouldEscapeHashTags)}
`;
${this.fileHelpers.formatComments(comments, settings.escapeMode, settings.dateFormat, shouldEscapeHashTags)}`;

return frontmatter;
}
}
Loading