From e6e694977239837d2faaf686f47b8dbf7604c6b7 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Fri, 13 Jun 2025 08:58:23 +0100 Subject: [PATCH 01/14] [AMEND] Rename and Refactor --- LICENSE | 2 +- README.md | 6 +- ...racidianLogo.png => umbPublisher-Logo.png} | Bin ...nSettings.png => umbPublisherSettings.png} | Bin getLatest.ps1 | 2 +- icons/icons.ts | 6 +- ...acidian-logo.svg => umbPublisher-Logo.svg} | 0 main.ts | 55 +++++++++++------- manifest.json | 6 +- package-lock.json | 4 +- package.json | 10 ++-- settings/index.ts | 16 ++--- types/index.ts | 4 +- 13 files changed, 61 insertions(+), 50 deletions(-) rename assets/{UmbracidianLogo.png => umbPublisher-Logo.png} (100%) rename assets/{umbracidianSettings.png => umbPublisherSettings.png} (100%) rename icons/img/{umbracidian-logo.svg => umbPublisher-Logo.svg} (100%) diff --git a/LICENSE b/LICENSE index 8aa2645..e172ea7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) [year] [fullname] +Copyright (c) 2025 Owain Williams Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index d845a33..63a7e59 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -Document Type -# Umbracidian - a plugin for Obsidian +Document Type +# umbPublisher - a plugin for Obsidian This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a blog post. -To see how to use this plugin with Obsidian, check out the [Wiki pages](https://github.com/OwainWilliams/Umbracidian/wiki) +To see how to use this plugin with Obsidian, check out the [Wiki pages](https://github.com/OwainWilliams/umbPublisher/wiki) diff --git a/assets/UmbracidianLogo.png b/assets/umbPublisher-Logo.png similarity index 100% rename from assets/UmbracidianLogo.png rename to assets/umbPublisher-Logo.png diff --git a/assets/umbracidianSettings.png b/assets/umbPublisherSettings.png similarity index 100% rename from assets/umbracidianSettings.png rename to assets/umbPublisherSettings.png diff --git a/getLatest.ps1 b/getLatest.ps1 index 66443c4..8bef5fe 100644 --- a/getLatest.ps1 +++ b/getLatest.ps1 @@ -1,4 +1,4 @@ -$Repo = "OwainWilliams/Umbracidian" # Replace with your actual repository name +$Repo = "OwainWilliams/umbPublisher" # Replace with your actual repository name $ManifestFile = "manifest.json" $JSFile = "main.js" diff --git a/icons/icons.ts b/icons/icons.ts index fdd14a1..4220e69 100644 --- a/icons/icons.ts +++ b/icons/icons.ts @@ -1,9 +1,9 @@ import { addIcon } from "obsidian"; -import umbracoLogo from "./img/umbracidian-logo.svg"; +import umbracoLogo from "./img/umbPublisher-Logo.svg"; -export class UmbracidianIcons { - private icons = [{ iconId: "umbracidian-logo", svg: umbracoLogo }]; +export class umbPublisherIcons { + private icons = [{ iconId: "umbPublisher-logo", svg: umbracoLogo }]; registerIcons = () => { this.icons.forEach(({ iconId, svg }) => { diff --git a/icons/img/umbracidian-logo.svg b/icons/img/umbPublisher-Logo.svg similarity index 100% rename from icons/img/umbracidian-logo.svg rename to icons/img/umbPublisher-Logo.svg diff --git a/main.ts b/main.ts index f5d31c0..ca526b4 100644 --- a/main.ts +++ b/main.ts @@ -1,13 +1,13 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { Editor, MarkdownView, Notice, Plugin, requestUrl } from 'obsidian'; -import { DEFAULT_SETTINGS, UmbracidianSettings } from "./types/index"; +import { DEFAULT_SETTINGS, umbPublisherSettings } from "./types/index"; import { SettingTab } from "./settings"; -import { UmbracidianIcons } from "./icons/icons"; +import { umbPublisherIcons } from "./icons/icons"; import { GetUmbracoDocType } from "./methods/getUmbracoDocType"; import { CallUmbracoApi } from "./methods/callUmbracoApi"; import { GenerateGuid } from 'methods/generateGuid'; -const matter = require("gray-matter"); + interface Frontmatter { @@ -20,10 +20,10 @@ interface Frontmatter { content: string; } -export default class Umbracidian extends Plugin { - settings: UmbracidianSettings; +export default class umbPublisher extends Plugin { + settings: umbPublisherSettings; - private icons = new UmbracidianIcons(); + private icons = new umbPublisherIcons(); private bearerToken: null | string = null; // Initialize bearerToken to null async onload() { @@ -31,7 +31,7 @@ export default class Umbracidian extends Plugin { this.icons.registerIcons(); // This creates an icon in the left ribbon. - this.addRibbonIcon('umbracidian-logo', 'Umbracidian', async (evt: MouseEvent) => { + this.addRibbonIcon('umbPublisher-logo', 'umbPublisher', async (evt: MouseEvent) => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (!view) { new Notice('No active Markdown view found.'); @@ -48,18 +48,24 @@ export default class Umbracidian extends Plugin { // This adds an editor command that can perform some operation on the current editor instance this.addCommand({ id: 'push-to-umbraco', - name: 'Push to Umbraco command', - editorCallback: async (editor: Editor) => { - const view = this.app.workspace.getActiveViewOfType(MarkdownView); - if (!view) { + name: 'Push to Umbraco', + editorCheckCallback: (checking: boolean, editor: Editor, view: MarkdownView) => + { + if(checking) return true; + + const value = this.app.workspace.getActiveViewOfType(MarkdownView); + + if(!value){ new Notice('No active Markdown view found.'); return; } + (async () => { this.bearerToken = await this.getBearerToken(); - const umbracoDocType = await GetUmbracoDocType(this.settings.blogDocTypeAlias, this.settings.websiteUrl, this.bearerToken); await this.createObsidianNode(view, umbracoDocType, this.settings.websiteUrl); + })(); } + }); // This adds a settings tab so the user can configure various aspects of the plugin @@ -105,18 +111,16 @@ export default class Umbracidian extends Plugin { body: body.toString(), }); - // Check if the response contains valid JSON + if (response.json) { const data = response.json as { access_token: string }; - // console.log('Bearer token response:', data); - return data.access_token; // Assuming the token is in the "access_token" field + + return data.access_token; } else { - // console.error('Empty or invalid JSON response:', response); new Notice('Failed to fetch bearer token.'); return null; } } catch (error) { - // console.error('Error fetching bearer token:', error); new Notice(`Error fetching bearer token: ${error}`); return null; } @@ -130,9 +134,17 @@ export default class Umbracidian extends Plugin { return null; } - const metaMatter = this.app.metadataCache.getFileCache(noteFile)?.frontmatter; - const pageContent = matter(view.getViewData()); - + const fileCache = this.app.metadataCache.getFileCache(noteFile); + const metaMatter = fileCache?.frontmatter; + const fileContent = await this.app.vault.read(noteFile); + + let content = fileContent; + if (fileCache?.frontmatterPosition) { + const { start, end } = fileCache.frontmatterPosition; + const lines = fileContent.split('\n'); + content = lines.slice(end.line + 1).join('\n'); + } + const frontmatter = { title: metaMatter?.title || view.file?.basename, tags: metaMatter?.tags || [], @@ -140,14 +152,13 @@ export default class Umbracidian extends Plugin { status: metaMatter?.published ? "published" : "draft", excerpt: metaMatter?.excerpt || undefined, feature_image: metaMatter?.feature_image || undefined, - content: pageContent.content, + content: content, }; if (!frontmatter) { new Notice('No frontmatter found.'); return null; } else { - // console.log('Meta matter:', frontmatter); return frontmatter; } diff --git a/manifest.json b/manifest.json index b5ca102..e0177d8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { - "id": "umbracidian", - "name": "Umbracidian", + "id": "umbPublisher", + "name": "Umbraco Publisher", "version": "1.0.0", "minAppVersion": "1.8.10", - "description": "Push notes to Umbraco CMS as blog posts.", + "description": "Push notes to Umbraco CMS as content.", "author": "Owain Williams", "authorUrl": "https://owain.codes", "fundingUrl": "https://buymeacoffee.com/owaincodes", diff --git a/package-lock.json b/package-lock.json index f89b55b..bd84dc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "Umbracidian", + "name": "umbPublisher", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "Umbracidian", + "name": "umbPublisher", "version": "0.1.0", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4c98f99..a0837c0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "Umbracidian", + "name": "umbPublisher", "version": "0.1.0", "description": "Send Blog Posts to Umbraco CMS via Management API", "main": "main.js", @@ -9,7 +9,7 @@ "version": "node version-bump.mjs && git add manifest.json versions.json" }, "keywords": [], - "author": "", + "author": "Owain Williams", "license": "MIT", "devDependencies": { "@types/node": "^16.18.126", @@ -32,10 +32,10 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/obsidianmd/obsidian-sample-plugin.git" + "url": "git+https://github.com/OwainWilliams/Umbracidian.git" }, "bugs": { - "url": "https://github.com/obsidianmd/obsidian-sample-plugin/issues" + "url": "https://github.com/OwainWilliams/Umbracidian/issues" }, - "homepage": "https://github.com/obsidianmd/obsidian-sample-plugin#readme" + "homepage": "https://github.com/OwainWilliams/Umbracidian/" } diff --git a/settings/index.ts b/settings/index.ts index c17e0f5..13e1224 100644 --- a/settings/index.ts +++ b/settings/index.ts @@ -1,10 +1,10 @@ -import Umbracidian from "main"; +import umbPublisher from "main"; import { App, PluginSettingTab, Setting } from "obsidian"; export class SettingTab extends PluginSettingTab { - plugin: Umbracidian; + plugin: umbPublisher; - constructor(app: App, plugin: Umbracidian) { + constructor(app: App, plugin: umbPublisher) { super(app, plugin); this.plugin = plugin; } @@ -13,7 +13,7 @@ export class SettingTab extends PluginSettingTab { const { containerEl } = this; containerEl.empty(); - containerEl.createEl('h2', { text: 'Umbracidian' }); + new Setting(containerEl) .setName('Website URL') .setDesc('The URL of the Umbraco website e.g. https://example.com') @@ -35,17 +35,17 @@ export class SettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })), new Setting(containerEl) - .setName('Client Secret') + .setName('Client secret') .setDesc('The client secret for the Umbraco API') .addText(text => text - .setPlaceholder('Client Secret from Umbraco') + .setPlaceholder('Client secret from Umbraco') .setValue(this.plugin.settings.clientSecret) .onChange(async (value) => { this.plugin.settings.clientSecret = value; await this.plugin.saveSettings(); }).inputEl.setAttribute('type', 'password')), new Setting(containerEl) - .setName('Blog Parent Node UUID') + .setName('Blog parent node UUID') .setDesc('The UUID of the parent node for blog posts e.g. 00000000-0000-0000-0000-00000000000, leave empty for root') .addText(text => text .setPlaceholder('Enter the parent node UUID') @@ -75,7 +75,7 @@ export class SettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })), new Setting(containerEl) - .setName('Blog Content Editor alias') + .setName('Blog content editor alias') .setDesc('This should be an Umbraco.MarkdownEditor property on your page') .addText(text => text .setPlaceholder('Enter the Property alias') diff --git a/types/index.ts b/types/index.ts index 4d7baf9..7e3e2dd 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,4 +1,4 @@ -export interface UmbracidianSettings { +export interface umbPublisherSettings { mySetting: string; websiteUrl: string; blogParentNodeId: string; @@ -9,7 +9,7 @@ export interface UmbracidianSettings { blogContentAlias: string; } -export const DEFAULT_SETTINGS: UmbracidianSettings = { +export const DEFAULT_SETTINGS: umbPublisherSettings = { mySetting: 'default', blogParentNodeId: 'null', blogDocTypeAlias: 'BlogPost', From 586c4df029abc18a5ade503f4be179862d15f9ae Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 17 Jun 2025 14:27:59 +0100 Subject: [PATCH 02/14] [AMEND] Fix id so make it accepted by Obsidian PR --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index e0177d8..d8cf530 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "id": "umbPublisher", + "id": "umbpublisher", "name": "Umbraco Publisher", "version": "1.0.0", "minAppVersion": "1.8.10", From da1d22873e0de715e577535d94405d7b14c040b0 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 17 Jun 2025 14:29:29 +0100 Subject: [PATCH 03/14] [AMEND] casing of umbpublisher name --- README.md | 6 +++--- getLatest.ps1 | 2 +- icons/icons.ts | 6 +++--- main.ts | 12 ++++++------ package-lock.json | 4 ++-- package.json | 2 +- settings/index.ts | 6 +++--- types/index.ts | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 63a7e59..765710f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -Document Type -# umbPublisher - a plugin for Obsidian +Document Type +# umbpublisher - a plugin for Obsidian This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a blog post. -To see how to use this plugin with Obsidian, check out the [Wiki pages](https://github.com/OwainWilliams/umbPublisher/wiki) +To see how to use this plugin with Obsidian, check out the [Wiki pages](https://github.com/OwainWilliams/umbpublisher/wiki) diff --git a/getLatest.ps1 b/getLatest.ps1 index 8bef5fe..3424b76 100644 --- a/getLatest.ps1 +++ b/getLatest.ps1 @@ -1,4 +1,4 @@ -$Repo = "OwainWilliams/umbPublisher" # Replace with your actual repository name +$Repo = "OwainWilliams/umbpublisher" # Replace with your actual repository name $ManifestFile = "manifest.json" $JSFile = "main.js" diff --git a/icons/icons.ts b/icons/icons.ts index 4220e69..bc99ef6 100644 --- a/icons/icons.ts +++ b/icons/icons.ts @@ -1,9 +1,9 @@ import { addIcon } from "obsidian"; -import umbracoLogo from "./img/umbPublisher-Logo.svg"; +import umbracoLogo from "./img/umbpublisher-Logo.svg"; -export class umbPublisherIcons { - private icons = [{ iconId: "umbPublisher-logo", svg: umbracoLogo }]; +export class umbpublisherIcons { + private icons = [{ iconId: "umbpublisher-logo", svg: umbracoLogo }]; registerIcons = () => { this.icons.forEach(({ iconId, svg }) => { diff --git a/main.ts b/main.ts index ca526b4..ac45a2b 100644 --- a/main.ts +++ b/main.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { Editor, MarkdownView, Notice, Plugin, requestUrl } from 'obsidian'; -import { DEFAULT_SETTINGS, umbPublisherSettings } from "./types/index"; +import { DEFAULT_SETTINGS, umbpublisherSettings } from "./types/index"; import { SettingTab } from "./settings"; -import { umbPublisherIcons } from "./icons/icons"; +import { umbpublisherIcons } from "./icons/icons"; import { GetUmbracoDocType } from "./methods/getUmbracoDocType"; import { CallUmbracoApi } from "./methods/callUmbracoApi"; import { GenerateGuid } from 'methods/generateGuid'; @@ -20,10 +20,10 @@ interface Frontmatter { content: string; } -export default class umbPublisher extends Plugin { - settings: umbPublisherSettings; +export default class umbpublisher extends Plugin { + settings: umbpublisherSettings; - private icons = new umbPublisherIcons(); + private icons = new umbpublisherIcons(); private bearerToken: null | string = null; // Initialize bearerToken to null async onload() { @@ -31,7 +31,7 @@ export default class umbPublisher extends Plugin { this.icons.registerIcons(); // This creates an icon in the left ribbon. - this.addRibbonIcon('umbPublisher-logo', 'umbPublisher', async (evt: MouseEvent) => { + this.addRibbonIcon('umbpublisher-logo', 'umbpublisher', async (evt: MouseEvent) => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (!view) { new Notice('No active Markdown view found.'); diff --git a/package-lock.json b/package-lock.json index bd84dc7..91963a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "umbPublisher", + "name": "umbpublisher", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "umbPublisher", + "name": "umbpublisher", "version": "0.1.0", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index a0837c0..8db6678 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "umbPublisher", + "name": "umbpublisher", "version": "0.1.0", "description": "Send Blog Posts to Umbraco CMS via Management API", "main": "main.js", diff --git a/settings/index.ts b/settings/index.ts index 13e1224..fe28957 100644 --- a/settings/index.ts +++ b/settings/index.ts @@ -1,10 +1,10 @@ -import umbPublisher from "main"; +import umbpublisher from "main"; import { App, PluginSettingTab, Setting } from "obsidian"; export class SettingTab extends PluginSettingTab { - plugin: umbPublisher; + plugin: umbpublisher; - constructor(app: App, plugin: umbPublisher) { + constructor(app: App, plugin: umbpublisher) { super(app, plugin); this.plugin = plugin; } diff --git a/types/index.ts b/types/index.ts index 7e3e2dd..fd3d746 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,4 +1,4 @@ -export interface umbPublisherSettings { +export interface umbpublisherSettings { mySetting: string; websiteUrl: string; blogParentNodeId: string; @@ -9,7 +9,7 @@ export interface umbPublisherSettings { blogContentAlias: string; } -export const DEFAULT_SETTINGS: umbPublisherSettings = { +export const DEFAULT_SETTINGS: umbpublisherSettings = { mySetting: 'default', blogParentNodeId: 'null', blogDocTypeAlias: 'BlogPost', From 1d519563b6e566b3f9239b3e6a47ffe9b43651fd Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 17 Jun 2025 14:41:05 +0100 Subject: [PATCH 04/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 765710f..a394fe4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Document Type +Document Type # umbpublisher - a plugin for Obsidian This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a blog post. From 746499f737d638e251fea5176d9ee9d5a02b5f39 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 17 Jun 2025 14:42:04 +0100 Subject: [PATCH 05/14] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a394fe4..2ed4f31 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Document Type -# umbpublisher - a plugin for Obsidian +# umbPublisher - an Obsidian plugin. -This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a blog post. +This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a content item. To see how to use this plugin with Obsidian, check out the [Wiki pages](https://github.com/OwainWilliams/umbpublisher/wiki) From 552e927af2e42189a0b061d3c05d01982d8d1427 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 09:51:25 +0100 Subject: [PATCH 06/14] Add release workflow --- .github/workflows/release.yml | 0 README.md | 2 +- icons/icons.ts | 2 +- manifest.json | 2 +- package.json | 8 ++++---- versions.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 2ed4f31..4624948 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Document Type +Document Type # umbPublisher - an Obsidian plugin. This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a content item. diff --git a/icons/icons.ts b/icons/icons.ts index bc99ef6..b5ec248 100644 --- a/icons/icons.ts +++ b/icons/icons.ts @@ -1,6 +1,6 @@ import { addIcon } from "obsidian"; -import umbracoLogo from "./img/umbpublisher-Logo.svg"; +import umbracoLogo from "./img/umbpublisher-logo.svg"; export class umbpublisherIcons { private icons = [{ iconId: "umbpublisher-logo", svg: umbracoLogo }]; diff --git a/manifest.json b/manifest.json index d8cf530..d401006 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "umbpublisher", "name": "Umbraco Publisher", - "version": "1.0.0", + "version": "1.0.2", "minAppVersion": "1.8.10", "description": "Push notes to Umbraco CMS as content.", "author": "Owain Williams", diff --git a/package.json b/package.json index 8db6678..7706beb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umbpublisher", - "version": "0.1.0", + "version": "1.0.2", "description": "Send Blog Posts to Umbraco CMS via Management API", "main": "main.js", "scripts": { @@ -32,10 +32,10 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/OwainWilliams/Umbracidian.git" + "url": "git+https://github.com/OwainWilliams/umbPublisher.git" }, "bugs": { - "url": "https://github.com/OwainWilliams/Umbracidian/issues" + "url": "https://github.com/OwainWilliams/umbPublisher/issues" }, - "homepage": "https://github.com/OwainWilliams/Umbracidian/" + "homepage": "https://github.com/OwainWilliams/umbPublisher/" } diff --git a/versions.json b/versions.json index 26382a1..7b2a176 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ { - "1.0.0": "0.15.0" + "1.0.2": "0.15.0" } From 6da1b7945a50440a904d9f763e1da1101f4da0d9 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 09:54:20 +0100 Subject: [PATCH 07/14] Add release workflow --- .github/workflows/release.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e69de29..350e329 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -0,0 +1,35 @@ +name: Release Obsidian plugin + +on: + push: + tags: + - "*" + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v3 + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: "18.x" + + - name: Build plugin + run: | + npm install + npm run build + + - name: Create release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + tag="${GITHUB_REF#refs/tags/}" + + gh release create "$tag" \ + --title="$tag" \ + --draft \ + main.js manifest.json styles.css \ No newline at end of file From 798ccffe6704886f34bd86b1f34f63e03281dfd8 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 10:05:18 +0100 Subject: [PATCH 08/14] Rename logo --- icons/img/{umbPublisher-Logo.svg => umbpublisher-logo.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename icons/img/{umbPublisher-Logo.svg => umbpublisher-logo.svg} (100%) diff --git a/icons/img/umbPublisher-Logo.svg b/icons/img/umbpublisher-logo.svg similarity index 100% rename from icons/img/umbPublisher-Logo.svg rename to icons/img/umbpublisher-logo.svg From 1ea5b5b8eb36698501c4e20856a31d40427e2618 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 10:15:34 +0100 Subject: [PATCH 09/14] error fixing --- icons/icons.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icons/icons.ts b/icons/icons.ts index b5ec248..c91266b 100644 --- a/icons/icons.ts +++ b/icons/icons.ts @@ -1,9 +1,9 @@ import { addIcon } from "obsidian"; -import umbracoLogo from "./img/umbpublisher-logo.svg"; +import umbPublisherLogo from "./img/umbpublisher-logo.svg"; export class umbpublisherIcons { - private icons = [{ iconId: "umbpublisher-logo", svg: umbracoLogo }]; + private icons = [{ iconId: "umbpublisher-logo", svg: umbPublisherLogo }]; registerIcons = () => { this.icons.forEach(({ iconId, svg }) => { From beafe030f9109d0105ff91ea39f3a63ccb4a1189 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 10:26:07 +0100 Subject: [PATCH 10/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4624948..2ed4f31 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Document Type +Document Type # umbPublisher - an Obsidian plugin. This plugin allows you to push your [Obsidian](https://obsidian.md/) notes to [Umbraco 15+](https://umbraco.com) as a content item. From 7af72435745a5d3d2525044a7633843e0da53b0e Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Tue, 24 Jun 2025 10:31:59 +0100 Subject: [PATCH 11/14] rename package --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index d401006..578e4d1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "id": "umbpublisher", - "name": "Umbraco Publisher", + "name": "umbPublisher", "version": "1.0.2", "minAppVersion": "1.8.10", "description": "Push notes to Umbraco CMS as content.", From 80c8e05d1d80d314e85bd21ca3eccb1697efe12c Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Thu, 26 Jun 2025 13:00:06 +0100 Subject: [PATCH 12/14] sanitise website url --- settings/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/settings/index.ts b/settings/index.ts index fe28957..03e50f5 100644 --- a/settings/index.ts +++ b/settings/index.ts @@ -21,7 +21,9 @@ export class SettingTab extends PluginSettingTab { .setPlaceholder('Enter the website URL') .setValue(this.plugin.settings.websiteUrl) .onChange(async (value) => { - this.plugin.settings.websiteUrl = value; + const match = value.match(/^(https?:\/\/[^\/]+)/i); + const sanitized = match ? match[1] : value.replace(/\/.*$/, ''); + this.plugin.settings.websiteUrl = sanitized; await this.plugin.saveSettings(); })), new Setting(containerEl) From de0b764cba53af02ea2f44a4c71aec2220093dea Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Mon, 15 Sep 2025 14:28:28 +0100 Subject: [PATCH 13/14] Add content picker to settings --- manifest.json | 4 +- package.json | 4 +- settings/index.ts | 173 ++++++++++++++++++++++++++++++++++++++-------- versions.json | 3 +- 4 files changed, 152 insertions(+), 32 deletions(-) diff --git a/manifest.json b/manifest.json index 578e4d1..f51dcec 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,8 @@ { "id": "umbpublisher", "name": "umbPublisher", - "version": "1.0.2", - "minAppVersion": "1.8.10", + "version": "1.1.0", + "minAppVersion": "1.9.12", "description": "Push notes to Umbraco CMS as content.", "author": "Owain Williams", "authorUrl": "https://owain.codes", diff --git a/package.json b/package.json index 7706beb..8e8ffc4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "umbpublisher", - "version": "1.0.2", - "description": "Send Blog Posts to Umbraco CMS via Management API", + "version": "1.1.0", + "description": "Send Obsidian Notes to Umbraco CMS via Management API", "main": "main.js", "scripts": { "dev": "node esbuild.config.mjs", diff --git a/settings/index.ts b/settings/index.ts index 03e50f5..06e7c1c 100644 --- a/settings/index.ts +++ b/settings/index.ts @@ -1,27 +1,91 @@ import umbpublisher from "main"; -import { App, PluginSettingTab, Setting } from "obsidian"; +import { App, PluginSettingTab, Setting, requestUrl, Notice } from "obsidian"; + +async function getBearerToken(websiteUrl: string, clientId: string, clientSecret: string): Promise { + const tokenEndpoint = `${websiteUrl}/umbraco/management/api/v1/security/back-office/token`; + const body = new URLSearchParams({ + grant_type: 'client_credentials', + client_id: clientId, + client_secret: clientSecret, + }); + try { + const response = await requestUrl({ + url: tokenEndpoint, + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: body.toString(), + }); + return (response.json as any).access_token; + } catch (e) { + new Notice('Failed to fetch bearer token'); + return null; + } +} + +async function fetchContentTree(websiteUrl: string, token: string): Promise { + const endpoint = `${websiteUrl}/umbraco/management/api/v1/tree/document-type/root`; + const response = await requestUrl({ + url: endpoint, + method: 'GET', + headers: { 'Authorization': `Bearer ${token}` }, + }); + return (response.json as any).items || []; +} + +// Recursively fetch all nodes and their children +async function fetchAllContentNodes( + websiteUrl: string, + token: string, + parentId: string | null = null, + depth: number = 0 +): Promise { + const endpoint = parentId + ? `${websiteUrl}/umbraco/management/api/v1/tree/document/children?parentId=${parentId}` + : `${websiteUrl}/umbraco/management/api/v1/tree/document/root?skip=0&take=100&foldersOnly=false`; + + const response = await requestUrl({ + url: endpoint, + method: 'GET', + headers: { 'Authorization': `Bearer ${token}` }, + }); + + const items = (response.json as any).items || []; + let allNodes: any[] = []; + + for (const item of items) { + // Add current node with depth for indentation + allNodes.push({ ...item, depth }); + // Recursively fetch children + const children = await fetchAllContentNodes(websiteUrl, token, item.id, depth + 1); + allNodes = allNodes.concat(children); + } + + return allNodes; +} export class SettingTab extends PluginSettingTab { - plugin: umbpublisher; + plugin: umbpublisher; + private cachedNodes: any[] = []; // Store fetched nodes - constructor(app: App, plugin: umbpublisher) { - super(app, plugin); - this.plugin = plugin; - } + constructor(app: App, plugin: umbpublisher) { + super(app, plugin); + this.plugin = plugin; + } - display(): void { - const { containerEl } = this; + display(): void { + let parentNodeDropdown: HTMLSelectElement | null = null; + let fetchButton: HTMLButtonElement | null = null; + const { containerEl } = this; + containerEl.empty(); - containerEl.empty(); - - new Setting(containerEl) - .setName('Website URL') - .setDesc('The URL of the Umbraco website e.g. https://example.com') - .addText(text => text - .setPlaceholder('Enter the website URL') - .setValue(this.plugin.settings.websiteUrl) - .onChange(async (value) => { - const match = value.match(/^(https?:\/\/[^\/]+)/i); + new Setting(containerEl) + .setName('Website URL') + .setDesc('The URL of the Umbraco website e.g. https://example.com') + .addText(text => text + .setPlaceholder('Enter the website URL') + .setValue(this.plugin.settings.websiteUrl) + .onChange(async (value) => { + const match = value.match(/^(https?:\/\/[^\/]+)/i); const sanitized = match ? match[1] : value.replace(/\/.*$/, ''); this.plugin.settings.websiteUrl = sanitized; await this.plugin.saveSettings(); @@ -46,16 +110,71 @@ export class SettingTab extends PluginSettingTab { this.plugin.settings.clientSecret = value; await this.plugin.saveSettings(); }).inputEl.setAttribute('type', 'password')), - new Setting(containerEl) + new Setting(containerEl) + .setName('Pick content parent node') + .setDesc('Fetch and select a parent node from Umbraco where content will be saved under') + .addButton(button => { + fetchButton = button.buttonEl; + button.setButtonText('Fetch nodes').onClick(async () => { + const { websiteUrl, clientId, clientSecret } = this.plugin.settings; + if (!websiteUrl || !clientId || !clientSecret) { + new Notice('Please enter Website URL, Client Id, and Client Secret first.'); + return; + } + const token = await getBearerToken(websiteUrl, clientId, clientSecret); + if (!token) return; + // Fetch all nodes recursively and cache them + this.cachedNodes = await fetchAllContentNodes(websiteUrl, token); + if (parentNodeDropdown) { + parentNodeDropdown.innerHTML = ''; + const rootOption = document.createElement('option'); + rootOption.value = ''; + rootOption.text = '[Select Node]'; + parentNodeDropdown.appendChild(rootOption); + this.cachedNodes.forEach(node => { + const option = document.createElement('option'); + option.value = node.id; + option.text = `${'—'.repeat(node.depth)} ${node.variants[0].name}`; + parentNodeDropdown?.appendChild(option); + }); + parentNodeDropdown.value = this.plugin.settings.blogParentNodeId || ''; + } + }); + }) + .addDropdown(dropdown => { + parentNodeDropdown = dropdown.selectEl; + // Populate dropdown from cache if available + parentNodeDropdown.innerHTML = ''; + const rootOption = document.createElement('option'); + rootOption.value = ''; + rootOption.text = '[Select Node]'; + parentNodeDropdown.appendChild(rootOption); + if (this.cachedNodes.length > 0) { + this.cachedNodes.forEach(node => { + const option = document.createElement('option'); + option.value = node.id; + option.text = `${'—'.repeat(node.depth)} ${node.variants[0].name}`; + parentNodeDropdown?.appendChild(option); + }); + } + parentNodeDropdown.value = this.plugin.settings.blogParentNodeId || ''; + + dropdown.onChange(async (value) => { + this.plugin.settings.blogParentNodeId = value; + this.display(); + await this.plugin.saveSettings(); + + }); + + }), + new Setting(containerEl) .setName('Blog parent node UUID') - .setDesc('The UUID of the parent node for blog posts e.g. 00000000-0000-0000-0000-00000000000, leave empty for root') + .setDesc('For reference, this is fetched from the node picker above') .addText(text => text - .setPlaceholder('Enter the parent node UUID') + .setPlaceholder('Fetched from node picker above') .setValue(this.plugin.settings.blogParentNodeId) - .onChange(async (value) => { - this.plugin.settings.blogParentNodeId = value; - await this.plugin.saveSettings(); - })), + .setDisabled(true) + ), new Setting(containerEl) .setName('DocType alias') .setDesc('This is the alias of the DocType you want to use for your blog posts') @@ -73,7 +192,7 @@ export class SettingTab extends PluginSettingTab { .setPlaceholder('Enter the Title alias') .setValue(this.plugin.settings.titleAlias) .onChange(async (value) => { - this.plugin.settings.titleAlias = value; + this.plugin.settings.titleAlias = value; await this.plugin.saveSettings(); })), new Setting(containerEl) @@ -85,6 +204,6 @@ export class SettingTab extends PluginSettingTab { .onChange(async (value) => { this.plugin.settings.blogContentAlias = value; await this.plugin.saveSettings(); - })) + })); } } diff --git a/versions.json b/versions.json index 7b2a176..d2f3132 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,4 @@ { - "1.0.2": "0.15.0" + "1.1.0": "0.15.0", + "1.2.0": "1.9.12" } From e7c2422a6d20ac2e48e886d4bff43f021531a014 Mon Sep 17 00:00:00 2001 From: Owain Williams Date: Mon, 15 Sep 2025 14:47:56 +0100 Subject: [PATCH 14/14] Fix version number --- versions.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/versions.json b/versions.json index d2f3132..df3d877 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,3 @@ { - "1.1.0": "0.15.0", - "1.2.0": "1.9.12" + "1.1.0": "0.15.0" }