mirror of
https://github.com/unabyss/obsidian-plugin.git
synced 2026-07-22 07:47:17 +00:00
fix: address Obsidian community plugin review findings (1.1.1)
- manifest: drop redundant "Obsidian" from description - settings: render logo as inline themed SVG (no shipped image assets, adapts via currentColor), move all inline styles to styles.css, use Setting().setHeading() for section headers, drop document/activeDocument access, and avoid returning a promise from a void event handler - syncInbound: use FileManager.trashFile to respect the user's deletion preference instead of Vault.trash - main: type catch parameters as unknown (no unsafe any) - apiClient: optional catch binding for the unused error - build: replace builtin-modules package with node:module builtinModules - release CI: attach only main.js/manifest.json/styles.css and add build provenance attestations - versions.json: backfill 1.0.1 and 1.1.1 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
ffd5b07ec5
commit
a05c1252d1
12 changed files with 128 additions and 77 deletions
19
.github/workflows/release.yml
vendored
19
.github/workflows/release.yml
vendored
|
|
@ -1,9 +1,9 @@
|
|||
name: Release Obsidian Plugin
|
||||
|
||||
# Triggered by pushing a SemVer tag (v*). Builds the production bundle
|
||||
# and attaches main.js, manifest.json, and logo SVGs to the GitHub
|
||||
# Release - the same artefacts the Obsidian Community Plugins store
|
||||
# expects to download from the GitHub release.
|
||||
# and attaches only the files Obsidian downloads - main.js, manifest.json,
|
||||
# and styles.css - to the GitHub Release. Obsidian ignores any other
|
||||
# release assets, so none are attached.
|
||||
#
|
||||
# The Release is published under the BARE version tag (e.g. 1.1.0), not
|
||||
# the pushed v-prefixed tag. Obsidian matches manifest.json "version"
|
||||
|
|
@ -17,6 +17,8 @@ on:
|
|||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
|
|
@ -65,9 +67,16 @@ jobs:
|
|||
- name: Collect release artefacts
|
||||
run: |
|
||||
mkdir -p release
|
||||
cp main.js manifest.json logo-dark.svg logo-light.svg release/
|
||||
cp main.js manifest.json release/
|
||||
if [ -f styles.css ]; then cp styles.css release/; fi
|
||||
|
||||
- name: Attest build provenance
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-path: |
|
||||
release/main.js
|
||||
release/manifest.json
|
||||
|
||||
- name: Publish GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
|
|
@ -78,8 +87,6 @@ jobs:
|
|||
files: |
|
||||
release/main.js
|
||||
release/manifest.json
|
||||
release/logo-dark.svg
|
||||
release/logo-light.svg
|
||||
release/styles.css
|
||||
fail_on_unmatched_files: false
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ Two-way OAuth sync between your Obsidian vault and your Unabyss memory.
|
|||
pnpm build
|
||||
```
|
||||
|
||||
3. Copy `main.js`, `manifest.json`, `logo-dark.svg`, and
|
||||
`logo-light.svg` into `<vault>/.obsidian/plugins/unabyss/`
|
||||
3. Copy `main.js`, `manifest.json`, and `styles.css` into
|
||||
`<vault>/.obsidian/plugins/unabyss/`
|
||||
(create the folder if it doesn't exist).
|
||||
4. Enable the plugin in Settings -> Community plugins.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
import { builtinModules } from "module";
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
|
|
@ -28,7 +28,8 @@ const context = await esbuild.context({
|
|||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins,
|
||||
...builtinModules,
|
||||
...builtinModules.map((name) => `node:${name}`),
|
||||
],
|
||||
format: "cjs",
|
||||
target: "es2018",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"id": "unabyss",
|
||||
"name": "Unabyss",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"minAppVersion": "1.5.0",
|
||||
"description": "Sync notes and exports between your Obsidian vault and Unabyss.",
|
||||
"description": "Sync notes and exports between your vault and Unabyss.",
|
||||
"author": "Unabyss",
|
||||
"authorUrl": "https://unabyss.com",
|
||||
"isDesktopOnly": false
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
"devDependencies": {
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.0",
|
||||
"builtin-modules": "^3.3.0",
|
||||
"esbuild": "^0.21.5",
|
||||
"jest": "^29.7.0",
|
||||
"obsidian": "^1.5.7",
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ importers:
|
|||
'@types/node':
|
||||
specifier: ^20.11.0
|
||||
version: 20.19.41
|
||||
builtin-modules:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
esbuild:
|
||||
specifier: ^0.21.5
|
||||
version: 0.21.5
|
||||
|
|
@ -575,10 +572,6 @@ packages:
|
|||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
builtin-modules@3.3.0:
|
||||
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -2020,8 +2013,6 @@ snapshots:
|
|||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
builtin-modules@3.3.0: {}
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase@5.3.1: {}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ export class UnabyssApiClient {
|
|||
}
|
||||
try {
|
||||
await this.refreshTokens();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
await this.clearAuth("refresh_failed");
|
||||
throw new AuthExpiredError();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,14 +232,14 @@ export default class UnabyssPlugin extends Plugin {
|
|||
this.settings.outboundEnabled
|
||||
? this.runOutboundSync(true)
|
||||
.then((report) => ({ ok: true as const, report }))
|
||||
.catch((err) => ({ ok: false as const, err }))
|
||||
.catch((err: unknown) => ({ ok: false as const, err }))
|
||||
: Promise.resolve(null);
|
||||
|
||||
const inboundP: Promise<DirectionOutcome<SyncInboundReport> | null> =
|
||||
this.settings.inboundEnabled
|
||||
? this.runInboundSync(true)
|
||||
.then((report) => ({ ok: true as const, report }))
|
||||
.catch((err) => ({ ok: false as const, err }))
|
||||
.catch((err: unknown) => ({ ok: false as const, err }))
|
||||
: Promise.resolve(null);
|
||||
|
||||
const [outboundSettled, inboundSettled] = await Promise.allSettled([outboundP, inboundP]);
|
||||
|
|
|
|||
|
|
@ -61,29 +61,42 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
|
||||
private renderHeader(containerEl: HTMLElement): void {
|
||||
const header = containerEl.createDiv({ cls: "unabyss-settings-header" });
|
||||
header.style.display = "flex";
|
||||
header.style.alignItems = "center";
|
||||
header.style.gap = "10px";
|
||||
header.style.marginBottom = "18px";
|
||||
|
||||
const logo = header.createEl("img", { cls: "unabyss-settings-logo" });
|
||||
logo.alt = "Unabyss";
|
||||
logo.src = this.pluginLogoResourcePath();
|
||||
logo.style.width = "32px";
|
||||
logo.style.height = "32px";
|
||||
logo.style.flexShrink = "0";
|
||||
|
||||
const title = header.createEl("h2", { text: "Unabyss" });
|
||||
title.style.margin = "0";
|
||||
this.renderLogo(header);
|
||||
header.createDiv({ cls: "unabyss-settings-title", text: "Unabyss" });
|
||||
}
|
||||
|
||||
private pluginLogoResourcePath(): string {
|
||||
const logoFile = document.body.classList.contains("theme-dark")
|
||||
? "logo-dark.svg"
|
||||
: "logo-light.svg";
|
||||
return this.app.vault.adapter.getResourcePath(
|
||||
`.obsidian/plugins/${this.plugin.manifest.id}/${logoFile}`,
|
||||
);
|
||||
/**
|
||||
* Renders the Unabyss mark as inline SVG that inherits the current
|
||||
* theme text colour, so the plugin ships no extra image assets and
|
||||
* adapts to light/dark automatically.
|
||||
*/
|
||||
private renderLogo(parent: HTMLElement): void {
|
||||
const dotOpacities = [
|
||||
0.28, 0.26, 0.89, 0.65,
|
||||
0.56, 0.7, 0.88, 0.69,
|
||||
0.57, 0.26, 0.62, 0.5,
|
||||
0.74, 0.08, 0.13, 0.98,
|
||||
];
|
||||
const coords = [4, 12, 20, 28];
|
||||
const svg = parent.createSvg("svg", {
|
||||
cls: "unabyss-settings-logo",
|
||||
attr: { viewBox: "0 0 32 32", width: 32, height: 32 },
|
||||
});
|
||||
let index = 0;
|
||||
for (const cy of coords) {
|
||||
for (const cx of coords) {
|
||||
svg.createSvg("circle", {
|
||||
attr: {
|
||||
cx,
|
||||
cy,
|
||||
r: 3,
|
||||
fill: "currentColor",
|
||||
"fill-opacity": dotOpacities[index],
|
||||
},
|
||||
});
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private renderApiBaseUrl(containerEl: HTMLElement): void {
|
||||
|
|
@ -111,11 +124,6 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
}
|
||||
const auth = this.plugin.settings.auth;
|
||||
const banner = containerEl.createDiv({ cls: "unabyss-connection-banner" });
|
||||
banner.style.marginBottom = "16px";
|
||||
banner.style.padding = "12px 14px";
|
||||
banner.style.borderRadius = "8px";
|
||||
banner.style.border = "1px solid var(--background-modifier-border)";
|
||||
banner.style.background = "var(--background-secondary)";
|
||||
|
||||
banner.createEl("p", {
|
||||
text:
|
||||
|
|
@ -128,11 +136,7 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
cls: "setting-item-description",
|
||||
});
|
||||
|
||||
const actions = banner.createDiv();
|
||||
actions.style.display = "flex";
|
||||
actions.style.flexWrap = "wrap";
|
||||
actions.style.gap = "8px";
|
||||
actions.style.marginTop = "10px";
|
||||
const actions = banner.createDiv({ cls: "unabyss-connection-banner-actions" });
|
||||
|
||||
const syncBtn = actions.createEl("button", { text: "Sync now" });
|
||||
syncBtn.classList.add("mod-cta");
|
||||
|
|
@ -221,7 +225,7 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
private renderOutboundSection(containerEl: HTMLElement): void {
|
||||
containerEl.createEl("h3", { text: "Obsidian \u2192 Unabyss (outbound)" });
|
||||
new Setting(containerEl).setName("Obsidian \u2192 Unabyss (outbound)").setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Sync outbound")
|
||||
|
|
@ -267,7 +271,7 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
private renderInboundSection(containerEl: HTMLElement): void {
|
||||
containerEl.createEl("h3", { text: "Unabyss \u2192 Obsidian (inbound)" });
|
||||
new Setting(containerEl).setName("Unabyss \u2192 Obsidian (inbound)").setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Sync inbound")
|
||||
|
|
@ -322,7 +326,7 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
private renderAdvancedSection(containerEl: HTMLElement): void {
|
||||
containerEl.createEl("h3", { text: "Advanced" });
|
||||
new Setting(containerEl).setName("Advanced").setHeading();
|
||||
this.renderApiBaseUrl(containerEl);
|
||||
new Setting(containerEl)
|
||||
.setName("Force full resync")
|
||||
|
|
@ -359,26 +363,16 @@ export class UnabyssSettingTab extends PluginSettingTab {
|
|||
return;
|
||||
}
|
||||
const chipsRow = containerEl.createDiv({ cls: "unabyss-folder-chip-row" });
|
||||
chipsRow.style.display = "flex";
|
||||
chipsRow.style.flexWrap = "wrap";
|
||||
chipsRow.style.gap = "8px";
|
||||
chipsRow.style.marginBottom = "12px";
|
||||
for (const folder of folders) {
|
||||
const chip = chipsRow.createDiv({ cls: "unabyss-folder-chip" });
|
||||
chip.style.padding = "4px 8px";
|
||||
chip.style.border = "1px solid var(--background-modifier-border)";
|
||||
chip.style.borderRadius = "4px";
|
||||
chip.style.display = "flex";
|
||||
chip.style.alignItems = "center";
|
||||
chip.style.gap = "6px";
|
||||
chip.createSpan({ text: folder });
|
||||
const remove = chip.createEl("button", { text: "x" });
|
||||
remove.style.background = "transparent";
|
||||
remove.style.border = "none";
|
||||
remove.style.cursor = "pointer";
|
||||
remove.addEventListener("click", async () => {
|
||||
const remove = chip.createEl("button", {
|
||||
text: "x",
|
||||
cls: "unabyss-folder-chip-remove",
|
||||
});
|
||||
remove.addEventListener("click", () => {
|
||||
const next = folders.filter((entry) => entry !== folder);
|
||||
await save(next);
|
||||
void save(next);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ async function applyDeletion(
|
|||
};
|
||||
}
|
||||
if (deps.deleteBehaviour === "delete") {
|
||||
await deps.app.vault.trash(existing, true);
|
||||
await deps.app.fileManager.trashFile(existing);
|
||||
return {
|
||||
exportId: row.id,
|
||||
title: row.title,
|
||||
|
|
|
|||
56
styles.css
Normal file
56
styles.css
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
.unabyss-settings-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.unabyss-settings-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.unabyss-settings-title {
|
||||
margin: 0;
|
||||
font-size: var(--font-ui-large);
|
||||
font-weight: var(--font-bold);
|
||||
}
|
||||
|
||||
.unabyss-connection-banner {
|
||||
margin-bottom: 16px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
background: var(--background-secondary);
|
||||
}
|
||||
|
||||
.unabyss-connection-banner-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.unabyss-folder-chip-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.unabyss-folder-chip {
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.unabyss-folder-chip-remove {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
{
|
||||
"0.1.0": "1.5.0",
|
||||
"1.0.0": "1.5.0"
|
||||
"1.0.0": "1.5.0",
|
||||
"1.0.1": "1.5.0",
|
||||
"1.1.0": "1.5.0",
|
||||
"1.1.1": "1.5.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue