Compare commits

...

41 commits
0.7.1 ... main

Author SHA1 Message Date
Erin Schnabel
5f0adac25b
Merge pull request #40 from ebullient/dependabot/npm_and_yarn/biomejs/biome-2.4.14
Bump @biomejs/biome from 2.4.11 to 2.4.14
2026-06-03 10:20:19 -04:00
Erin Schnabel
c782933af5
Merge pull request #38 from ebullient/dependabot/github_actions/actions/setup-node-6.4.0
Bump actions/setup-node from 6.3.0 to 6.4.0
2026-06-03 10:19:59 -04:00
dependabot[bot]
8c3379b349
Bump actions/setup-node from 6.3.0 to 6.4.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to 6.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](53b83947a5...48b55a011b)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-03 14:18:30 +00:00
dependabot[bot]
83f0a61f28
Bump @biomejs/biome from 2.4.11 to 2.4.14
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.4.11 to 2.4.14.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.14/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.4.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-03 14:18:16 +00:00
Erin Schnabel
5ab47a954b
Merge pull request #37 from ebullient/dependabot/npm_and_yarn/typescript-6.0.3
Bump typescript from 6.0.2 to 6.0.3
2026-06-03 10:17:48 -04:00
dependabot[bot]
10aaaf2ed9
Bump typescript from 6.0.2 to 6.0.3
Bumps [typescript](https://github.com/microsoft/TypeScript) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v6.0.2...v6.0.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-03 14:17:06 +00:00
GitHub Action
9c1c2c36a7 🔖 0.8.0 2026-06-03 14:16:19 +00:00
Erin Schnabel
f279ae3297
🎨 Use 1.13.0 Settings API 2026-06-03 10:14:16 -04:00
Erin Schnabel
990113e1e6
🔧 globalIgnores first 2026-05-19 17:38:07 -04:00
Erin Schnabel
ce408c1a80
⬆️ obsidian 1.12.3 / obsidian eslint 0.3.0 2026-05-12 13:58:57 -04:00
Erin Schnabel
5db632cfb0
👷 node 24 2026-05-12 13:25:30 -04:00
GitHub Action
96f9f35f70 🔖 0.7.6 2026-05-11 21:26:21 +00:00
Erin Schnabel
cee3c8a993
Merge pull request #33 from ebullient/dependabot/npm_and_yarn/esbuild-0.28.0
Bump esbuild from 0.27.7 to 0.28.0
2026-05-11 17:24:15 -04:00
dependabot[bot]
eeafa09f38
Bump esbuild from 0.27.7 to 0.28.0
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.27.7 to 0.28.0.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.7...v0.28.0)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-11 21:23:06 +00:00
Erin Schnabel
7b5826c211
Merge pull request #34 from ebullient/dependabot/npm_and_yarn/biomejs/biome-2.4.11
Bump @biomejs/biome from 2.4.9 to 2.4.11
2026-05-11 17:23:05 -04:00
Erin Schnabel
7e419d4028
⬆️ update dependencies 2026-05-11 17:21:42 -04:00
dependabot[bot]
5f526e098f
Bump @biomejs/biome from 2.4.9 to 2.4.11
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.4.9 to 2.4.11.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.11/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.4.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-11 02:28:45 +00:00
GitHub Action
77e3a30086 🔖 0.7.5 2026-04-30 18:42:57 +00:00
Erin Schnabel
8247f3a92c
⬆️ resolve dependencies 2026-04-30 14:39:12 -04:00
dependabot[bot]
39dfce8020
Bump @biomejs/biome from 2.4.7 to 2.4.9
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.4.7 to 2.4.9.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.9/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.4.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 14:38:22 -04:00
dependabot[bot]
8ea3cd02cf
Bump typescript from 5.9.3 to 6.0.2
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 14:38:20 -04:00
dependabot[bot]
c3d22818d4
Bump eslint from 9.39.4 to 10.1.0
Bumps [eslint](https://github.com/eslint/eslint) from 9.39.4 to 10.1.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.4...v10.1.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 10.1.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 14:38:18 -04:00
Erin Schnabel
622aa168fe
🔧 🎨 eslint updates + fixes 2026-04-30 08:15:26 -04:00
GitHub Action
b3af69c936 🔖 0.7.4 2026-04-15 15:04:57 +00:00
Erin Schnabel
bd20a736ca
Merge pull request #25 from ebullient/dependabot/npm_and_yarn/types/node-25.0.3
Bump @types/node from 24.10.4 to 25.0.3
2026-04-15 10:35:26 -04:00
dependabot[bot]
484ff7758a
Bump @types/node from 24.10.4 to 25.0.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.4 to 25.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-15 13:49:27 +00:00
Erin Schnabel
e09ae9c922
Merge pull request #24 from ebullient/dependabot/npm_and_yarn/esbuild-0.27.2
Bump esbuild from 0.25.12 to 0.27.2
2026-04-15 09:48:51 -04:00
Erin Schnabel
0b3cd95bce
Merge pull request #26 from ebullient/dependabot/npm_and_yarn/biomejs/biome-2.3.10
Bump @biomejs/biome from 2.2.6 to 2.3.10
2026-04-15 09:48:10 -04:00
dependabot[bot]
f68d9b9f9d
Bump esbuild from 0.25.12 to 0.27.2
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.25.12 to 0.27.2.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.12...v0.27.2)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.27.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-15 13:46:14 +00:00
dependabot[bot]
51c201da95
Bump @biomejs/biome from 2.2.6 to 2.3.10
Bumps [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) from 2.2.6 to 2.3.10.
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.3.10/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.3.10
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-15 13:45:52 +00:00
Erin Schnabel
7d2f43e752
⬆️ update minimatch, audit fix 2026-04-15 09:43:50 -04:00
GitHub
dc49a6ccf3 🔖 0.7.3 2026-01-03 14:57:26 +00:00
Erin Schnabel
e57ad0a696
🎨 Add settings icon 2026-01-03 09:18:53 -05:00
Erin Schnabel
99da810b1a
⬆️ dependency bump 2026-01-03 09:18:40 -05:00
Erin Schnabel
1a249c742b
♻️ Review comments 2026-01-03 08:45:46 -05:00
Erin Schnabel
57b2c43195
🔨💸 add funding url 2026-01-02 19:11:46 -05:00
GitHub
9e073e9610 🔖 0.7.2 2025-11-22 02:41:52 +00:00
Erin Schnabel
1e10f70f57
️ coffee 2025-11-21 21:40:10 -05:00
Erin Schnabel
68de05b5d2
🐛 debounce over Timer 2025-11-21 20:59:31 -05:00
Erin Schnabel
c7df00f53d
🎨 Simpilify tracking last seen 2025-11-21 20:41:55 -05:00
Erin Schnabel
3921ebf361
👷 consistent changelog behavior 2025-11-18 21:35:34 -05:00
19 changed files with 936 additions and 1164 deletions

View file

@ -1,6 +1,7 @@
name: CI Test
on:
workflow_dispatch:
push:
branches: [ main ]
paths:
@ -23,12 +24,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Use Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '20'
node-version: '24'
cache: 'npm'
- name: Build and Test

View file

@ -18,11 +18,6 @@ on:
default: true
required: true
type: boolean
retry:
description: "Retry release (clear created tag)"
default: false
required: true
type: boolean
env:
GH_BOT_EMAIL: "41898282+github-actions[bot]@users.noreply.github.com"
@ -32,19 +27,22 @@ jobs:
build:
permissions:
contents: write
actions: write
id-token: write
attestations: write
runs-on: ubuntu-latest
outputs:
version: ${{ steps.build.outputs.version }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# persist-credentials required: this step pushes commits and tags
# zizmor: ignore[artipacked]
with:
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
- name: Use Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '20'
node-version: '24'
cache: 'npm'
# Build the plugin
@ -52,37 +50,33 @@ jobs:
id: build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_VERSION: ${{ github.event.inputs.version }}
INPUT_UPDATE_MANIFEST: ${{ github.event.inputs.update_manifest }}
INPUT_UPDATE_BRAT: ${{ github.event.inputs.update_brat }}
run: |
echo "version: ${{ github.event.inputs.version }}"
echo "retry: ${{ github.event.inputs.retry }}"
echo "update_manifest: ${{ github.event.inputs.update_manifest }}"
echo "update_brat: ${{ github.event.inputs.update_brat }}"
echo "version: $INPUT_VERSION"
echo "update_manifest: $INPUT_UPDATE_MANIFEST"
echo "update_brat: $INPUT_UPDATE_BRAT"
git config user.name ${{ env.GH_BOT_NAME }}
git config user.email ${{ env.GH_BOT_EMAIL }}
git config user.name "$GH_BOT_NAME"
git config user.email "$GH_BOT_EMAIL"
npm ci
if [[ "${{ github.event.inputs.retry }}" = "true" ]]; then
npm run preversion
else
npm version ${{ github.event.inputs.version }} --no-git-tag-version
fi
npm version "$INPUT_VERSION" --no-git-tag-version
VERSION=$(grep '^ "version"' package.json | cut -d'"' -f4)
echo $VERSION
echo "$VERSION"
if git rev-parse "refs/tags/$VERSION" > /dev/null 2>&1; then
if [[ "${{ github.event.inputs.retry }}" = "true" ]]; then
gh release delete $VERSION --cleanup-tag --yes
else
echo "🛑 Tag $VERSION already exists"
exit 1
fi
echo "🛑 Tag $VERSION already exists. Delete the release and tag manually, then re-run."
exit 1
fi
if [ "${{ github.event.inputs.update_manifest }}" = "true" ]; then
if [ "$INPUT_UPDATE_MANIFEST" = "true" ]; then
# shellcheck disable=SC2086
sed -i 's|\(version":\) "[0-9\.]*"|\1 "'$VERSION'"|' manifest.json
fi
if [ "${{ github.event.inputs.update_brat }}" = "true" ]; then
if [ "$INPUT_UPDATE_BRAT" = "true" ]; then
# shellcheck disable=SC2086
sed -i 's|\(version":\) "[0-9\.]*"|\1 "'$VERSION'"|' manifest-beta.json
fi
@ -91,38 +85,54 @@ jobs:
git commit -m "🔖 $VERSION"
git push
git tag $VERSION
git tag "$VERSION"
git push --tags
npm run brat-notes -- ${VERSION}
echo "version=${VERSION}" >> $GITHUB_OUTPUT
npm run brat-notes -- "${VERSION}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
# Package the required files into a zip
- name: Package
env:
REPO_NAME: ${{ github.event.repository.name }}
RELEASE_VERSION: ${{ steps.build.outputs.version }}
run: |
mkdir ${{ github.event.repository.name }}
cp ./build/* ${{ github.event.repository.name }}
zip -r ${{ github.event.repository.name }}-${{ steps.build.outputs.version }}.zip ${{ github.event.repository.name }}
mv build "$REPO_NAME"
zip -r "${REPO_NAME}-${RELEASE_VERSION}.zip" "$REPO_NAME"
unzip -j "${REPO_NAME}-${RELEASE_VERSION}.zip" \
"$REPO_NAME/main.js" \
"$REPO_NAME/styles.css"
# Attest build provenance for release artifacts
- name: Attest build artifacts
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4
with:
subject-path: |
${{ github.event.repository.name }}-${{ steps.build.outputs.version }}.zip
./main.js
./styles.css
# Create the release on github
- name: Create Release
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_UPDATE_MANIFEST: ${{ github.event.inputs.update_manifest }}
REPO_NAME: ${{ github.event.repository.name }}
RELEASE_VERSION: ${{ steps.build.outputs.version }}
run: |
prerelease=true
if [ ${{ github.event.inputs.update_manifest }} ]; then
if [ "$INPUT_UPDATE_MANIFEST" = "true" ]; then
prerelease=false
fi
gh release create "${{ steps.build.outputs.version }}" \
gh release create "$RELEASE_VERSION" \
-F ./release-notes.md \
--title "Release ${{ steps.build.outputs.version }}" \
--title "$RELEASE_VERSION" \
--verify-tag \
--prerelease=${prerelease}
gh release upload "${{ steps.build.outputs.version }}" --clobber \
${{ github.event.repository.name }}-${{ steps.build.outputs.version }}.zip \
'./build/main.js#main.js' \
--prerelease=${prerelease} \
"${REPO_NAME}-${RELEASE_VERSION}.zip" \
'./main.js' \
'./styles.css' \
'./manifest.json' \
'./manifest-beta.json'

View file

@ -4,8 +4,60 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [0.8.0](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.6...0.8.0)
- 🎨 Use 1.13.0 Settings API [`f279ae3`](https://github.com/ebullient/obsidian-deck-notes/commit/f279ae32970cad72040ba6ce1b59b073443c46f9)
- ⬆️ obsidian 1.12.3 / obsidian eslint 0.3.0 [`ce408c1`](https://github.com/ebullient/obsidian-deck-notes/commit/ce408c1a80743030a487a95a8a685dbf70719d22)
- 👷 node 24 [`5db632c`](https://github.com/ebullient/obsidian-deck-notes/commit/5db632cfb09c2683ae88f131c7a594f5dde4487b)
- 🔧 globalIgnores first [`990113e`](https://github.com/ebullient/obsidian-deck-notes/commit/990113e1e650adf88daeac3a917fc5c81fe69edc)
#### [0.7.6](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.5...0.7.6)
> 11 May 2026
- Bump esbuild from 0.27.7 to 0.28.0 [`#33`](https://github.com/ebullient/obsidian-deck-notes/pull/33)
- Bump @biomejs/biome from 2.4.9 to 2.4.11 [`#34`](https://github.com/ebullient/obsidian-deck-notes/pull/34)
- ⬆️ update dependencies [`7e419d4`](https://github.com/ebullient/obsidian-deck-notes/commit/7e419d40287d9d1244987cada01e6389af05900c)
#### [0.7.5](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.4...0.7.5)
> 30 April 2026
- Bump eslint from 9.39.4 to 10.1.0 [`c3d2281`](https://github.com/ebullient/obsidian-deck-notes/commit/c3d22818d4489bed4b00b56e56cc2107676aaf27)
- 🔧 🎨 eslint updates + fixes [`622aa16`](https://github.com/ebullient/obsidian-deck-notes/commit/622aa168fe4ed55c01d81cbc5680e49033b87d48)
- Bump @biomejs/biome from 2.4.7 to 2.4.9 [`39dfce8`](https://github.com/ebullient/obsidian-deck-notes/commit/39dfce8020a4a2b74197a7a0a3aa20e3c7afaca3)
- ⬆️ resolve dependencies [`8247f3a`](https://github.com/ebullient/obsidian-deck-notes/commit/8247f3a92c7238f0abb08889bc7c5867dcd28d87)
- Bump typescript from 5.9.3 to 6.0.2 [`8ea3cd0`](https://github.com/ebullient/obsidian-deck-notes/commit/8ea3cd02cfa789c91de4e8313ca52abea11d8608)
#### [0.7.4](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.3...0.7.4)
> 15 April 2026
- Bump @types/node from 24.10.4 to 25.0.3 [`#25`](https://github.com/ebullient/obsidian-deck-notes/pull/25)
- Bump esbuild from 0.25.12 to 0.27.2 [`#24`](https://github.com/ebullient/obsidian-deck-notes/pull/24)
- Bump @biomejs/biome from 2.2.6 to 2.3.10 [`#26`](https://github.com/ebullient/obsidian-deck-notes/pull/26)
- ⬆️ update minimatch, audit fix [`7d2f43e`](https://github.com/ebullient/obsidian-deck-notes/commit/7d2f43e75236c0f89dde3e315c0c880bcc553323)
#### [0.7.3](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.2...0.7.3)
> 3 January 2026
- ⬆️ dependency bump [`99da810`](https://github.com/ebullient/obsidian-deck-notes/commit/99da810b1a1ffe96e83f0d665bc3ffb9039a43cd)
- ♻️ Review comments [`1a249c7`](https://github.com/ebullient/obsidian-deck-notes/commit/1a249c742b8181be46331e2337f78dcc928301dd)
- 🎨 Add settings icon [`e57ad0a`](https://github.com/ebullient/obsidian-deck-notes/commit/e57ad0a696a475d33162a8fd855217a772ec9223)
#### [0.7.2](https://github.com/ebullient/obsidian-deck-notes/compare/0.7.1...0.7.2)
> 22 November 2025
- 🎨 Simpilify tracking last seen [`c7df00f`](https://github.com/ebullient/obsidian-deck-notes/commit/c7df00f53d5ab0a88b9293b6dd0e4cfa62cc9db1)
- 🐛 debounce over Timer [`68de05b`](https://github.com/ebullient/obsidian-deck-notes/commit/68de05b5d28f55789dfc85e76cd78182e09f7884)
- ☕️ coffee [`1e10f70`](https://github.com/ebullient/obsidian-deck-notes/commit/1e10f70f57d3944f4e34be26ed06f665f0048516)
#### 0.7.1
> 18 November 2025
- 🎨 Plugin lint [`cedca21`](https://github.com/ebullient/obsidian-deck-notes/commit/cedca2173da68711e43ca1ec2298721271ff9a89)
- ✨ Initial pass at simple flashcards [`2d5695e`](https://github.com/ebullient/obsidian-deck-notes/commit/2d5695e5b123e21c6a8df022b873569403cc7da8)
- 📝 human docs to README/CONTRIBUTING [`63c230a`](https://github.com/ebullient/obsidian-deck-notes/commit/63c230a198991e24f6589aacab60c7ba0bd9d69b)

View file

@ -63,6 +63,11 @@ npm run format # Format code
- **Error handling**: `try/catch` with user-friendly `Notice` messages
- **Async**: Use `async/await` consistently
- **UI text (enforced by `obsidianmd/ui/sentence-case`)**:
- Use sentence case (capitalize first word only, except proper nouns)
- Setting descriptions must be complete sentences ending with periods
- Use semicolons to separate related clauses in a single sentence
- Avoid parenthetical notes; use semicolons instead
## Development Patterns

View file

@ -220,7 +220,7 @@ npm run format # Format code
```txt
src/
├── @types/
│ └── settings.d.ts # TypeScript interfaces
│ └── settings.d.ts # TypeScript interfaces
├── dn-Plugin.ts # Main plugin class
├── dn-CardParser.ts # Parse files into cards
├── dn-Modal.ts # Card display modal

View file

@ -1,35 +0,0 @@
# Security Policy
I only support the latest version of this plugin. Given the rapid
evolution of the MCP protocol and dependencies, running/maintaining older
versions isn't feasible.
## Security Considerations
This plugin runs a local HTTP server on your machine to expose vault
access via the MCP protocol:
- **Network exposure**: The server listens on localhost by default but
supports CORS for remote access (e.g., via Tailscale)
- **Authentication**: Currently there is no authentication mechanism - any
client that can reach the configured port can access your vault
- **Data privacy**: All data stays on your machine; the plugin does not
connect to external services or collect telemetry
- **Bridge script**: The `mcp-bridge.js` script runs as a Node.js process
and bridges stdio to HTTP
## Reporting a Vulnerability
Please report suspected security issues privately using GitHub's "Report a
vulnerability" link in the repository sidebar.
Do **not** open a public issue for suspected vulnerabilities.
When reporting, please include:
- A description of the issue and affected versions
- Steps to reproduce (ideally a minimal proof-of-concept)
- Assessment of potential impact (network exposure, data access, etc.)
- Your contact information
- Any specific requests, such as anonymity for you and/or the
organization you represent

View file

@ -1,6 +1,6 @@
import esbuild from "esbuild";
import process from "node:process";
import builtins from 'builtin-modules';
import { builtinModules } from "node:module";
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
@ -15,7 +15,7 @@ const parameters = {
banner: {
js: banner,
},
entryPoints: ['src/main.ts'],
entryPoints: ['src/main.ts', 'src/styles.css'],
bundle: true,
external: [
'obsidian',
@ -31,7 +31,7 @@ const parameters = {
'@lezer/common',
'@lezer/highlight',
'@lezer/lr',
...builtins
...builtinModules
],
format: 'cjs',
logLevel: 'info',
@ -54,4 +54,4 @@ if (prod) {
} else {
const ctx = await esbuild.context(parameters);
await ctx.watch()
}
}

View file

@ -5,12 +5,12 @@ import { defineConfig, globalIgnores } from "eslint/config";
import obsidianmd from "eslint-plugin-obsidianmd";
export default defineConfig([
...obsidianmd.configs.recommended,
globalIgnores([
"tests/",
"*.mjs",
"package.json"
]),
...obsidianmd.configs.recommended,
{
files: ["src/**/*.ts"],
languageOptions: {

View file

@ -1,10 +1,11 @@
{
"id": "deck-notes",
"name": "Deck Notes",
"version": "0.7.1",
"minAppVersion": "1.9.0",
"version": "0.8.0",
"minAppVersion": "1.13.0",
"description": "Define card decks for activities, strategies, or any content you want to rotate through. Embed cards in your notes or browse them in a modal. Filter by tag hierarchies to narrow your selection.",
"author": "ebullient",
"authorUrl": "https://github.com/ebullient",
"fundingUrl": "https://buymeacoffee.com/ebullient",
"isDesktopOnly": false
}

View file

@ -1,10 +1,11 @@
{
"id": "deck-notes",
"name": "Deck Notes",
"version": "0.7.1",
"minAppVersion": "1.9.0",
"version": "0.8.0",
"minAppVersion": "1.13.0",
"description": "Define card decks for activities, strategies, or any content you want to rotate through. Embed cards in your notes or browse them in a modal. Filter by tag hierarchies to narrow your selection.",
"author": "ebullient",
"authorUrl": "https://github.com/ebullient",
"fundingUrl": "https://buymeacoffee.com/ebullient",
"isDesktopOnly": false
}

1467
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "deck-notes",
"version": "0.7.1",
"version": "0.8.0",
"private": true,
"description": "Define card decks for activities, strategies, or any content you want to rotate through. Embed cards in your notes or browse them in a modal. Filter by tag hierarchies to narrow your selection.",
"main": "main.js",
@ -25,25 +25,30 @@
"flashcards"
],
"author": "ebullient",
"repository": "github.com:ebullient/obsidian-flashcards",
"repository": "github.com:ebullient/obsidian-deck-notes",
"license": "MIT",
"devDependencies": {
"@biomejs/biome": "2.2.6",
"@types/node": "^24.8.1",
"@biomejs/biome": "2.4.14",
"@types/node": "^25.5.0",
"@typescript-eslint/parser": "^8.46.4",
"auto-changelog": "^2.5.0",
"builtin-modules": "^5.0.0",
"esbuild": "^0.25.9",
"eslint": "^9.39.1",
"eslint-plugin-obsidianmd": "^0.1.9",
"moment": "^2.30.1",
"obsidian": "^1.10.2",
"esbuild": "^0.28.0",
"eslint-plugin-obsidianmd": "^0.3.0",
"obsidian": "^1.13.0",
"tslib": "^2.8.1",
"typescript": "5.9.3"
"typescript": "6.0.3"
},
"overrides": {
"glob": "13.0.6",
"minimatch": "10.2.3"
},
"auto-changelog": {
"backfillLimit": false,
"commitLimit": false,
"ignoreCommitPattern": "(🔖|🔨|🧹|changelog|release|Update README).*"
"ignoreCommitPattern": "(🔖|🔨|🧹|changelog|release|Update README).*",
"replaceText": {
"([;.,] [rR]esolves) #\\d+\\.?\\s*$": "$1",
"([;.,] [Ff]ixes) #\\d+\\.?\\s*$": "$1"
}
}
}

View file

@ -9,10 +9,9 @@ export interface Card {
export interface DeckNotesSettings {
cardPaths: string[]; // ["Journal/Coping", "Activities"]
defaultDeckTag: string; // Default tag for deck selection (e.g., "activities")
trackViews: boolean; // Enable view tracking
defaultDeckTag: string; // Default tag for deck selection
selectionMode: "random" | "least-recent";
calloutType: string; // Callout type for embedded cards (e.g., "readaloud")
calloutType: string; // Callout type for embedded cards
}
export interface DeckNotesData {

View file

@ -19,7 +19,8 @@ export class DeckNotesApi {
/**
* Get all unique deck tags discovered in cards
* @returns Array of normalized tag strings (e.g., ["activities", "activities/morning"])
* @returns Array of normalized tag strings; for example,
* ["activities", "activities/morning"]
*/
getTags(): string[] {
const tagsSet = new Set<string>();

View file

@ -3,7 +3,6 @@ import type { DeckNotesSettings } from "./@types/settings";
export const DEFAULT_SETTINGS: DeckNotesSettings = {
cardPaths: [],
defaultDeckTag: "",
trackViews: true,
selectionMode: "least-recent",
calloutType: "tip",
};

View file

@ -1,4 +1,10 @@
import { type App, ButtonComponent, MarkdownRenderer, Modal } from "obsidian";
import {
type App,
ButtonComponent,
MarkdownRenderChild,
MarkdownRenderer,
Modal,
} from "obsidian";
import type { Card } from "./@types/settings";
import type DeckNotesPlugin from "./dn-Plugin";
@ -6,6 +12,7 @@ export class CardModal extends Modal {
plugin: DeckNotesPlugin;
card: Card | null;
deckTag: string | undefined;
renderer: MarkdownRenderChild;
constructor(
app: App,
@ -17,6 +24,7 @@ export class CardModal extends Modal {
this.plugin = plugin;
this.card = card;
this.deckTag = deckTag;
this.renderer = new MarkdownRenderChild(this.containerEl);
}
onOpen() {
@ -39,7 +47,7 @@ export class CardModal extends Modal {
contentEl.createEl("h2", { text: this.card.heading });
// Render card content as markdown
const contentDiv = contentEl.createEl("div", {
const contentDiv = contentEl.createDiv({
cls: "card-content",
});
@ -49,8 +57,7 @@ export class CardModal extends Modal {
this.card.content,
contentDiv,
this.card.filePath,
// eslint-disable-next-line obsidianmd/no-plugin-as-component
this.plugin,
this.renderer,
);
// Add button controls
@ -59,7 +66,7 @@ export class CardModal extends Modal {
private addControls() {
const { contentEl } = this;
const buttonContainer = contentEl.createEl("div", {
const buttonContainer = contentEl.createDiv({
cls: "modal-button-container",
});
@ -91,7 +98,7 @@ export class CardModal extends Modal {
private addCloseButton() {
const { contentEl } = this;
const buttonContainer = contentEl.createEl("div", {
const buttonContainer = contentEl.createDiv({
cls: "modal-button-container",
});
@ -120,7 +127,7 @@ export class CardModal extends Modal {
private showNextCard() {
// Record view for current card
if (this.card && this.plugin.settings.trackViews) {
if (this.card) {
this.plugin.recordView(this.card.key);
}

View file

@ -1,4 +1,11 @@
import { type Editor, Notice, Plugin, TFile, TFolder } from "obsidian";
import {
debounce,
type Editor,
Notice,
Plugin,
TFile,
TFolder,
} from "obsidian";
import type { Card, DeckNotesData, DeckNotesSettings } from "./@types/settings";
import { DeckNotesApi } from "./dn-Api";
import { CardParser } from "./dn-CardParser";
@ -21,7 +28,8 @@ export default class DeckNotesPlugin extends Plugin {
this.addSettingTab(new DeckNotesSettingsTab(this.app, this));
// Defer initial card scan, API, and command registration to avoid blocking startup
// Defer initial card scan, API, and command registration
// to avoid blocking startup
this.app.workspace.onLayoutReady(async () => {
await this.scanCards();
@ -65,6 +73,10 @@ export default class DeckNotesPlugin extends Plugin {
onunload() {
console.debug("Unloading Deck Notes plugin");
// Flush any pending view saves
this.debouncedSaveViews.cancel();
void this.saveViews();
// Clear API reference
if (window.deckNotes) {
window.deckNotes.api = undefined;
@ -85,6 +97,21 @@ export default class DeckNotesPlugin extends Plugin {
await this.scanCards();
}
debouncedSaveViews = debounce(
async () => {
await this.saveViews();
},
2000,
true, // resetTimer: save only after 2s of no new views
);
async saveViews() {
await this.saveData({
...this.settings,
cardViews: this.data.cardViews,
});
}
async scanCards() {
this.cachedCards = [];
@ -151,10 +178,7 @@ export default class DeckNotesPlugin extends Plugin {
recordView(cardKey: string) {
this.data.cardViews[cardKey] = Date.now();
void this.saveData({
...this.settings,
cardViews: this.data.cardViews,
});
this.debouncedSaveViews();
}
showCard() {
@ -188,9 +212,7 @@ export default class DeckNotesPlugin extends Plugin {
].join("\n");
// Record as viewed
if (this.settings.trackViews) {
this.recordView(card.key);
}
this.recordView(card.key);
return embedText;
}

View file

@ -1,160 +1,187 @@
import { type App, PluginSettingTab, Setting } from "obsidian";
import type { DeckNotesSettings } from "./@types/settings";
import {
type App,
Modal,
PluginSettingTab,
Setting,
type SettingDefinitionItem,
type Setting as SettingType,
} from "obsidian";
import type DeckNotesPlugin from "./dn-Plugin";
export class DeckNotesSettingsTab extends PluginSettingTab {
plugin: DeckNotesPlugin;
newSettings!: DeckNotesSettings;
constructor(app: App, plugin: DeckNotesPlugin) {
super(app, plugin);
this.plugin = plugin;
this.icon = "gallery-thumbnails";
}
async save() {
this.plugin.settings = this.newSettings;
async setControlValue(key: string, value: unknown): Promise<void> {
(this.plugin.settings as unknown as Record<string, unknown>)[key] =
value;
await this.plugin.saveSettings();
}
private cloneSettings(): DeckNotesSettings {
return JSON.parse(
JSON.stringify(this.plugin.settings),
) as DeckNotesSettings;
}
getSettingDefinitions(): SettingDefinitionItem[] {
return [
{
name: "Usage",
render: (setting: SettingType) => {
setting.descEl.appendChild(
createFragment((f) => {
const p = f.createEl("p");
p.appendText(
"Cards are created from markdown files with ",
);
p.createEl("code", { text: "##" });
p.appendText(" headings.");
async reset() {
this.newSettings = this.cloneSettings();
this.display();
}
const ul = f.createEl("ul");
display(): void {
if (!this.newSettings) {
this.newSettings = this.cloneSettings();
}
const li1 = ul.createEl("li");
li1.appendText("Use ");
li1.createEl("code", { text: "---" });
li1.appendText(
" (horizontal rule) to mark the end of card content.",
);
const { containerEl } = this;
containerEl.empty();
new Setting(containerEl).setHeading().setName("Deck Notes");
new Setting(containerEl)
.setName("Save settings")
.setClass("decknotes-save-reset")
.addButton((button) =>
button
.setButtonText("Reset")
.setTooltip("Reset to current saved settings")
.onClick(async () => {
await this.reset();
}),
)
.addButton((button) =>
button
.setButtonText("Save")
.setCta()
.setTooltip("Save all changes")
.onClick(async () => {
await this.save();
}),
);
containerEl.createEl("p", {
text: "Configure activity card decks for random selection.",
});
new Setting(containerEl)
.setName("Card paths")
.setDesc(
"Paths to folders containing card files (one per line, relative to vault root)",
)
.addTextArea((text) =>
text
.setPlaceholder("journal/coping\nactivities/morning")
.setValue(this.newSettings.cardPaths.join("\n"))
.onChange((value) => {
this.newSettings.cardPaths = value
.split("\n")
.map((p) => p.trim())
.filter((p) => p.length > 0);
}),
)
.then((setting) => {
setting.controlEl
.querySelector("textarea")
?.setAttribute("rows", "4");
});
new Setting(containerEl)
.setName("Default deck tag")
.setDesc(
"Default tag for 'Show Random Activity Card' command (e.g., 'activities' or 'activities/morning'). Leave empty for all cards.",
)
.addText((text) =>
text
.setPlaceholder("Activities")
.setValue(this.newSettings.defaultDeckTag)
.onChange((value) => {
this.newSettings.defaultDeckTag = value.trim();
}),
);
new Setting(containerEl)
.setName("Track views")
.setDesc(
"Track when cards were last viewed (enables least-recent selection)",
)
.addToggle((toggle) =>
toggle
.setValue(this.newSettings.trackViews)
.onChange((value) => {
this.newSettings.trackViews = value;
}),
);
new Setting(containerEl)
.setName("Selection mode")
.setDesc("How to select cards to display")
.addDropdown((dropdown) =>
dropdown
.addOption("random", "Random")
.addOption("least-recent", "Least recently viewed")
.setValue(this.newSettings.selectionMode)
.onChange((value) => {
this.newSettings.selectionMode = value as
| "random"
| "least-recent";
}),
);
new Setting(containerEl)
.setName("Callout type")
.setDesc(
"Callout type for embedded cards (e.g., note, tip, warning)",
)
.addText((text) =>
text
.setPlaceholder("example")
.setValue(this.newSettings.calloutType)
.onChange((value) => {
this.newSettings.calloutType = value.trim();
}),
);
new Setting(containerEl).setHeading().setName("Usage");
containerEl.createEl("p", {
text: "Cards are created from markdown files with H2 headings (##). Each heading becomes one card.",
});
containerEl.createEl("p", {
text: "Use --- (horizontal rule) to mark the end of card content. Anything after --- will be ignored.",
});
containerEl.createEl("p", {
text: "Tag cards with #flashcards/deck-name (e.g., #flashcards/activities/morning). Tags can be in frontmatter or inline before each H2. Lines starting with #flashcards are stripped from display.",
});
}
/** Save on exit */
hide(): void {
void this.save();
const li2 = ul.createEl("li");
li2.appendText("Use ");
li2.createEl("code", {
text: "#flashcards",
});
li2.appendText(
" tags to identify decks. For example, ",
);
li2.createEl("code", {
text: "#flashcards/activities",
});
li2.appendText(" or ");
li2.createEl("code", {
text: "#flashcards/meditation",
});
li2.appendText(
". Tags can be added to the whole file (in frontmatter properties), or defined inline before each ",
);
li2.createEl("code", { text: "##" });
li2.appendText(". See the ");
li2.createEl("a", {
text: "README",
href: "https://github.com/ebullient/obsidian-deck-notes#card-format",
attr: { target: "_blank" },
});
li2.appendText(" for examples.");
}),
);
},
},
{
name: "Default deck tag",
desc:
"Optional tag to narrow the selection of cards available " +
"for 'Show Card' command; for example, 'activities' or " +
"'activities/morning'.",
control: {
type: "text",
key: "defaultDeckTag",
placeholder: "activities",
},
},
{
name: "Selection mode",
desc: "Cards can be selected at random or based on when they were last viewed.",
control: {
type: "dropdown",
key: "selectionMode",
options: {
random: "Random",
"least-recent": "Least recently viewed",
},
},
},
{
name: "Callout type",
desc: "Callout type for embedded cards; for example, note, tip, or warning.",
control: {
type: "text",
key: "calloutType",
placeholder: "example",
},
},
{
type: "list",
heading: "Card paths",
desc: "Paths to folders containing card decks, relative to vault root.",
emptyState: "No card paths configured.",
addItem: {
name: "Add path",
action: () =>
new AddCardPathModal(this.app, (path) => {
this.plugin.settings.cardPaths.push(path);
void this.plugin.saveSettings();
this.update();
}).open(),
},
onDelete: async (idx: number) => {
this.plugin.settings.cardPaths.splice(idx, 1);
await this.plugin.saveSettings();
this.update();
},
items: this.plugin.settings.cardPaths.map((path) => ({
name: path,
})),
},
{
name: "",
render: (setting: SettingType) => {
setting.descEl.addClass("deck-cards-coffee");
setting.descEl
.createEl("a", {
href: "https://www.buymeacoffee.com/ebullient",
})
.createEl("img", {
attr: {
src: "https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=☕&slug=ebullient&button_colour=8e6787&font_colour=ebebeb&font_family=Inter&outline_colour=392a37&coffee_colour=ecc986",
},
});
},
},
];
}
}
class AddCardPathModal extends Modal {
private onSubmit: (path: string) => void;
constructor(app: App, onSubmit: (path: string) => void) {
super(app);
this.onSubmit = onSubmit;
}
onOpen(): void {
const { contentEl } = this;
contentEl.createEl("h2", { text: "Add card path" });
let input = "";
new Setting(contentEl).setName("Path").addText((t) =>
t.setPlaceholder("journal/coping").onChange((v) => {
input = v.trim();
}),
);
new Setting(contentEl).addButton((b) =>
b
.setButtonText("Add")
.setCta()
.onClick(() => {
if (input) {
this.onSubmit(input);
this.close();
}
}),
);
}
onClose(): void {
this.contentEl.empty();
}
}

6
src/styles.css Normal file
View file

@ -0,0 +1,6 @@
.deck-cards-coffee {
text-align: center;
img {
height: 30px;
}
}