obsidian-dev-skills 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -92,6 +92,7 @@ on:
|
|
|
92
92
|
push:
|
|
93
93
|
tags:
|
|
94
94
|
- "*"
|
|
95
|
+
workflow_dispatch:
|
|
95
96
|
|
|
96
97
|
permissions:
|
|
97
98
|
contents: write
|
|
@@ -110,6 +111,8 @@ jobs:
|
|
|
110
111
|
cache: "pnpm"
|
|
111
112
|
- run: pnpm install --frozen-lockfile
|
|
112
113
|
- run: pnpm build
|
|
114
|
+
- id: version
|
|
115
|
+
run: echo "version=$(jq -r .version manifest.json)" >> "$GITHUB_OUTPUT"
|
|
113
116
|
- uses: actions/attest-build-provenance@v2
|
|
114
117
|
with:
|
|
115
118
|
subject-path: |
|
|
@@ -118,10 +121,10 @@ jobs:
|
|
|
118
121
|
manifest.json
|
|
119
122
|
- env:
|
|
120
123
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
121
|
-
|
|
124
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
122
125
|
run: |
|
|
123
|
-
gh release create "$
|
|
124
|
-
--title="$
|
|
126
|
+
gh release create "$VERSION" \
|
|
127
|
+
--title="$VERSION" \
|
|
125
128
|
--generate-notes \
|
|
126
129
|
main.js styles.css manifest.json
|
|
127
130
|
```
|
|
@@ -134,6 +137,62 @@ Then cut releases by pushing a tag (e.g. `git tag 0.1.0 && git push origin 0.1.0
|
|
|
134
137
|
|
|
135
138
|
**Fix**: merge the two rule blocks. If they target the same selector and have non-overlapping properties, combine into one block. If they target the same selector and one is meant to override the other (e.g. inside a media query), wrap the override in a more specific selector or use a CSS variable.
|
|
136
139
|
|
|
140
|
+
### `!important` declarations
|
|
141
|
+
|
|
142
|
+
> Avoid `!important`. Override styles by increasing selector specificity or using CSS variables instead.
|
|
143
|
+
|
|
144
|
+
The fix is almost never to keep `!important` and hope the scorecard ignores it. Instead, scope the rule with a parent class so it wins the cascade naturally.
|
|
145
|
+
|
|
146
|
+
```css
|
|
147
|
+
/* Wrong: leans on !important to beat Obsidian's defaults */
|
|
148
|
+
.my-plugin-btn {
|
|
149
|
+
border: none !important;
|
|
150
|
+
background: none !important;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Right: parent class boosts specificity, no !important needed */
|
|
154
|
+
.my-plugin-panel .my-plugin-btn {
|
|
155
|
+
border: none;
|
|
156
|
+
background: none;
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The parent class is whatever wrapper the plugin's UI lives inside (e.g. the panel root, settings container). For toggle classes that need to beat an element's natural display, chain the toggle class with the base class for the same specificity boost: `.my-plugin-panel .my-toggle-hidden { display: none; }`.
|
|
161
|
+
|
|
162
|
+
### `:has()` selector
|
|
163
|
+
|
|
164
|
+
> Avoid `:has()`. It can cause significant performance issues due to broad selector invalidation.
|
|
165
|
+
|
|
166
|
+
Most uses of `:has()` are stylistic preferences that can be rewritten as descendant selectors targeting the child element directly.
|
|
167
|
+
|
|
168
|
+
```css
|
|
169
|
+
/* Wrong: re-styles the parent based on a descendant */
|
|
170
|
+
.result:has(a[href*="http"]) {
|
|
171
|
+
word-break: break-all;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Right: targets the child directly */
|
|
175
|
+
.result a[href*="http"] {
|
|
176
|
+
word-break: break-all;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
If the rule genuinely needs to style a parent based on a child's presence, fall back to adding a marker class via TypeScript when the child is appended (e.g. `parentEl.addClass('has-external-link')`).
|
|
181
|
+
|
|
182
|
+
### Don't override global Obsidian UI selectors
|
|
183
|
+
|
|
184
|
+
A plugin's `styles.css` is loaded globally. Rules targeting Obsidian's built-in classes affect every other plugin and Obsidian itself, not just yours.
|
|
185
|
+
|
|
186
|
+
```css
|
|
187
|
+
/* Wrong: forces flex layout on every menu in Obsidian, not just this plugin's */
|
|
188
|
+
.menu .menu-item {
|
|
189
|
+
display: flex !important;
|
|
190
|
+
justify-content: space-between !important;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Fix**: either remove the rule and accept Obsidian's default styling, or scope it. Menus appended outside your plugin's panel (via `new Menu()`) can't be scoped via parent class, so the rule has to be removed, or a marker class added when the menu is opened. The scorecard does not specifically flag this leak, but it's a hygiene rule that prevents conflicts with other plugins.
|
|
195
|
+
|
|
137
196
|
### `obsidianmd` ESLint rules (Warnings and Risks)
|
|
138
197
|
|
|
139
198
|
`eslint-plugin-obsidianmd` enforces Obsidian-idiomatic patterns. Common signals and fixes:
|
|
@@ -154,6 +213,18 @@ this.countEl.setText('0 Selected');
|
|
|
154
213
|
|
|
155
214
|
**Never disable this rule.** The scorecard explicitly flags `eslint-disable-next-line obsidianmd/ui/sentence-case` as a Risk and counts each occurrence. If a string genuinely cannot be sentence case (e.g. it embeds a proper noun or product name), fix the casing instead of disabling.
|
|
156
215
|
|
|
216
|
+
**Configure the rule for domain-specific acronyms.** The rule accepts `acronyms`, `brands`, `ignoreWords`, and `ignoreRegex` options. Use these when your plugin legitimately uses acronyms or quoted button names that the rule otherwise rejects.
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
// eslint.config.mjs
|
|
220
|
+
"obsidianmd/ui/sentence-case": ["error", {
|
|
221
|
+
acronyms: ["SEO", "MDX", "URL", "CSV", "H1", "H2", "H3", "H4", "H5", "H6"],
|
|
222
|
+
ignoreRegex: ['"[^"]+"'], // ignore content inside double quotes (referenced button/control names)
|
|
223
|
+
}]
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This is the right answer when the autofix expected output is something like `'Open seo audit panel'` (downcased acronym) but the string genuinely should read `'Open SEO audit panel'`. Configuring the rule is preferred over per-line disables, which are forbidden, or awkward rephrasing.
|
|
227
|
+
|
|
157
228
|
#### `obsidianmd/prefer-create-el-shorthand` (Warning)
|
|
158
229
|
|
|
159
230
|
Use `createDiv()` and `createSpan()` instead of `createEl('div')` and `createEl('span')`.
|
|
@@ -31,6 +31,7 @@ on:
|
|
|
31
31
|
push:
|
|
32
32
|
tags:
|
|
33
33
|
- "*"
|
|
34
|
+
workflow_dispatch:
|
|
34
35
|
|
|
35
36
|
permissions:
|
|
36
37
|
contents: write
|
|
@@ -49,6 +50,8 @@ jobs:
|
|
|
49
50
|
cache: "pnpm"
|
|
50
51
|
- run: pnpm install --frozen-lockfile
|
|
51
52
|
- run: pnpm build
|
|
53
|
+
- id: version
|
|
54
|
+
run: echo "version=$(jq -r .version manifest.json)" >> "$GITHUB_OUTPUT"
|
|
52
55
|
- uses: actions/attest-build-provenance@v2
|
|
53
56
|
with:
|
|
54
57
|
subject-path: |
|
|
@@ -57,18 +60,60 @@ jobs:
|
|
|
57
60
|
manifest.json
|
|
58
61
|
- env:
|
|
59
62
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
60
|
-
|
|
63
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
61
64
|
run: |
|
|
62
|
-
gh release
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
if gh release view "$VERSION" >/dev/null 2>&1; then
|
|
66
|
+
gh release upload "$VERSION" main.js styles.css manifest.json --clobber
|
|
67
|
+
else
|
|
68
|
+
gh release create "$VERSION" \
|
|
69
|
+
--title="$VERSION" \
|
|
70
|
+
--generate-notes \
|
|
71
|
+
main.js styles.css manifest.json
|
|
72
|
+
fi
|
|
66
73
|
```
|
|
67
74
|
|
|
75
|
+
**Why read the version from `manifest.json`**: the workflow runs from either a tag push (where `github.ref_name` is the tag) or a `workflow_dispatch` from a branch (where `github.ref_name` is the branch name, e.g. `master`). Using `github.ref_name` directly would title a manually-triggered release after the branch. Reading from `manifest.json` is consistent across both triggers and matches what Obsidian's plugin loader actually reads.
|
|
76
|
+
|
|
68
77
|
Cut releases by pushing a tag (`git tag 0.1.0 && git push origin 0.1.0`). The workflow attaches the three required assets and registers the attestation. The scorecard's "Build verified" signal also fires once the workflow has run, because the attested artifacts can be reproduced byte-for-byte from source.
|
|
69
78
|
|
|
70
79
|
For the full set of scorecard signals and their fixes, see [scorecard-compliance.md](scorecard-compliance.md).
|
|
71
80
|
|
|
81
|
+
### Pushing tags so the workflow actually fires
|
|
82
|
+
|
|
83
|
+
Push order matters. Push commits to the default branch **first**, in a separate command, then push the tag. If you push both in a single batch (`git push --tags --follow-tags` or some GUIs), GitHub occasionally processes the tag webhook before indexing the workflow file at that ref, and the trigger silently drops.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git push origin master # commits first
|
|
87
|
+
# pause a few seconds
|
|
88
|
+
git push origin 0.1.0 # tag in a separate command
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If the workflow does not fire on a tag push, diagnose with:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
gh api repos/:owner/:repo/actions/runs --jq '.workflow_runs[0:5] | .[] | {id, event, status, conclusion, head_branch, created_at}'
|
|
95
|
+
gh workflow list
|
|
96
|
+
gh api repos/:owner/:repo/actions/permissions/workflow
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If `gh api .../runs` is empty for the tag, the trigger was dropped. Recovery options:
|
|
100
|
+
|
|
101
|
+
- **Add `workflow_dispatch:` to the trigger** so you can re-run from the Actions tab without a re-push.
|
|
102
|
+
- **Re-push the tag**: `git push origin :refs/tags/0.1.0 && git push origin 0.1.0`.
|
|
103
|
+
- **Manually create the release** in the GitHub UI. The release will exist but it will not have the build provenance attestation, which costs scorecard points until the next release.
|
|
104
|
+
|
|
105
|
+
### Recovery trigger
|
|
106
|
+
|
|
107
|
+
It is worth adding a manual trigger alongside the tag-push trigger so future "the workflow didn't fire" situations have a one-click fix:
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
on:
|
|
111
|
+
push:
|
|
112
|
+
tags:
|
|
113
|
+
- "*"
|
|
114
|
+
workflow_dispatch:
|
|
115
|
+
```
|
|
116
|
+
|
|
72
117
|
> [!NOTE]
|
|
73
118
|
> Themes and plugins have different asset requirements and submission paths. Ensure you follow the correct flow for your project type.
|
|
74
119
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "obsidian-dev-skills",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Agent skills for Obsidian plugin and theme development, including community scorecard compliance, release workflow attestation, and dependency vulnerability hygiene.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"obsidian",
|