mirror of
https://github.com/Ellpeck/ObsidianJustSharePlease.git
synced 2024-05-19 17:51:22 +02:00
Compare commits
6 commits
15c9cdbd16
...
33bfe95ca5
Author | SHA1 | Date | |
---|---|---|---|
Ell | 33bfe95ca5 | ||
Ell | 6c4b1022b0 | ||
Ell | a5f20a15f2 | ||
Ell | deae38984c | ||
Ell | 85cb03cda4 | ||
Ell | fd6184ae10 |
|
@ -17,8 +17,8 @@
|
|||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter&display=swap">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=JetBrains+Mono&display=swap">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github-dark.min.css" media="(prefers-color-scheme:dark)">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github.min.css" media="(prefers-color-scheme:light),(prefers-color-scheme:no-preference)">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github-dark.min.css" media="(prefers-color-scheme: dark)">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/github.min.css" media="not (prefers-color-scheme: dark)">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
</head>
|
||||
|
@ -27,10 +27,16 @@
|
|||
<div class="content">
|
||||
<div id="main">
|
||||
<script>
|
||||
marked.use(markedKatex());
|
||||
marked.use(markedHighlight.markedHighlight({
|
||||
langPrefix: "hljs language-",
|
||||
highlight: (c, l) => {
|
||||
const language = hljs.getLanguage(l) ? l : "plaintext";
|
||||
return hljs.highlight(c, {language}).value;
|
||||
}
|
||||
}));
|
||||
|
||||
let main = $("#main");
|
||||
|
||||
// TODO display nice message when there is no hash
|
||||
|
||||
$(window).on("hashchange", display);
|
||||
display();
|
||||
|
||||
|
@ -40,20 +46,9 @@
|
|||
hash = hash.substring(1);
|
||||
$.ajax({
|
||||
method: "get",
|
||||
url: `share.php?id=${hash}`,
|
||||
success: t => {
|
||||
marked.use(markedKatex());
|
||||
marked.use(markedHighlight.markedHighlight({
|
||||
langPrefix: "hljs language-",
|
||||
highlight: (c, l) => {
|
||||
const language = hljs.getLanguage(l) ? l : "plaintext";
|
||||
return hljs.highlight(c, {language}).value;
|
||||
}
|
||||
}));
|
||||
main.html(DOMPurify.sanitize(marked.parse(t)));
|
||||
},
|
||||
// TODO display this error more nicely
|
||||
error: (r, s, e) => main.html(e)
|
||||
url: hash ? `share.php?id=${hash}` : "index.md",
|
||||
success: t => main.html(DOMPurify.sanitize(marked.parse(t))),
|
||||
error: (r, s, e) => main.html(`<div class="error"><p>Error loading shared note with id <code>${hash}</code>: ${e}</p><p><a href="#">Home</a></p></div>`)
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
3
server/public/index.md
Normal file
3
server/public/index.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Just Share Please
|
||||
|
||||
Just Share Please is an [Obsidian](https://obsidian.md) plugin that allows quickly and easily sharing individual notes online using an anonymized link. It's pretty cool!
|
|
@ -46,6 +46,14 @@ a:hover {
|
|||
margin: 40px auto 80px;
|
||||
}
|
||||
|
||||
.error {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 50%;
|
||||
top: 40%;
|
||||
transform: translate(-50%, -60%);
|
||||
}
|
||||
|
||||
#footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
198
src/main.ts
198
src/main.ts
|
@ -1,10 +1,11 @@
|
|||
import {Plugin, requestUrl, TFile} from "obsidian";
|
||||
import {Notice, Plugin, requestUrl, TFile} from "obsidian";
|
||||
import {defaultSettings, JSPSettings, SharedItem} from "./settings";
|
||||
import {JSPSettingsTab} from "./settings-tab";
|
||||
import {basename, extname} from "path";
|
||||
|
||||
export default class JustSharePleasePlugin extends Plugin {
|
||||
|
||||
// TODO allow deleting uploads whose local files have been deleted (through command?)
|
||||
// TODO panel that displays all shares, including ones for removed files, and allows unsharing or updating them
|
||||
// TODO add a setting for auto-refreshing uploads when saving
|
||||
// TODO strip frontmatter before uploading? maybe optionally
|
||||
settings: JSPSettings;
|
||||
|
@ -15,82 +16,84 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
|
||||
this.registerEvent(this.app.workspace.on("file-menu", async (m, f) => {
|
||||
if (f instanceof TFile) {
|
||||
let shared = this.settings.shared.find(i => i.path == f.path);
|
||||
let shared = this.getSharedItem(f);
|
||||
if (!shared) {
|
||||
// (newly) share a note
|
||||
m.addItem(i => {
|
||||
i.setTitle("Share to JSP");
|
||||
i.setIcon("share");
|
||||
i.onClick(async () => {
|
||||
let response = await requestUrl({
|
||||
url: `${this.settings.url}/share.php`,
|
||||
method: "POST",
|
||||
body: JSON.stringify({content: await this.app.vault.cachedRead(f)}),
|
||||
throw: false
|
||||
});
|
||||
|
||||
// TODO display message about status success/fail and copy URL to clipboard
|
||||
console.log(response.status + " " + response.text);
|
||||
|
||||
if (response.status == 200) {
|
||||
shared = response.json;
|
||||
shared.path = f.path;
|
||||
this.settings.shared.push(shared);
|
||||
await this.saveSettings();
|
||||
}
|
||||
});
|
||||
i.onClick(async () => this.shareFile(f));
|
||||
});
|
||||
} else {
|
||||
// copy note link
|
||||
m.addItem(i => {
|
||||
i.setTitle("Copy JSP link");
|
||||
i.setIcon("link");
|
||||
// TODO let people know this happened
|
||||
i.onClick(() => navigator.clipboard.writeText(`${this.settings.url}#${shared.id}`));
|
||||
i.onClick(() => this.copyShareLink(shared));
|
||||
});
|
||||
|
||||
// update
|
||||
m.addItem(i => {
|
||||
i.setTitle("Update in JSP");
|
||||
i.setIcon("share");
|
||||
i.onClick(async () => {
|
||||
let response = await requestUrl({
|
||||
url: `${this.settings.url}/share.php?id=${shared.id}`,
|
||||
method: "PATCH",
|
||||
headers: {"Password": shared.password},
|
||||
body: JSON.stringify({content: await this.app.vault.cachedRead(f)}),
|
||||
throw: false
|
||||
});
|
||||
|
||||
// TODO display message about status success/fail after updating
|
||||
console.log(response.status + " " + response.text);
|
||||
});
|
||||
i.onClick(() => this.updateFile(shared, f));
|
||||
});
|
||||
|
||||
// delete
|
||||
m.addItem(i => {
|
||||
i.setTitle("Delete from JSP");
|
||||
i.setIcon("trash");
|
||||
i.onClick(async () => {
|
||||
let response = await requestUrl({
|
||||
url: `${this.settings.url}/share.php?id=${shared.id}`,
|
||||
method: "DELETE",
|
||||
headers: {"Password": shared.password},
|
||||
throw: false
|
||||
});
|
||||
|
||||
// TODO display message about status success/fail when deleting
|
||||
console.log(response.status);
|
||||
|
||||
if (response.status == 200) {
|
||||
this.settings.shared.remove(shared);
|
||||
await this.saveSettings();
|
||||
}
|
||||
});
|
||||
i.onClick(async () => this.deleteFile(shared));
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.addCommand({
|
||||
id: "share",
|
||||
name: "Share current file to JSP",
|
||||
editorCheckCallback: (checking, _, ctx) => {
|
||||
if (!this.getSharedItem(ctx.file)) {
|
||||
if (!checking)
|
||||
this.shareFile(ctx.file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.addCommand({
|
||||
id: "copy",
|
||||
name: "Copy current file's JSP link",
|
||||
editorCheckCallback: (checking, _, ctx) => {
|
||||
let shared = this.getSharedItem(ctx.file);
|
||||
if (shared) {
|
||||
if (!checking)
|
||||
this.copyShareLink(shared);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.addCommand({
|
||||
id: "update",
|
||||
name: "Update current file in JSP",
|
||||
editorCheckCallback: (checking, _, ctx) => {
|
||||
let shared = this.getSharedItem(ctx.file);
|
||||
if (shared) {
|
||||
if (!checking)
|
||||
this.updateFile(shared, ctx.file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.addCommand({
|
||||
id: "delete",
|
||||
name: "Delete current file from JSP",
|
||||
editorCheckCallback: (checking, _, ctx) => {
|
||||
let shared = this.getSharedItem(ctx.file);
|
||||
if (shared) {
|
||||
if (!checking)
|
||||
this.deleteFile(shared);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadSettings(): Promise<void> {
|
||||
|
@ -100,4 +103,85 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
async saveSettings(): Promise<void> {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
getSharedItem(file: TFile): SharedItem {
|
||||
return this.settings.shared.find(f => f.path == file.path);
|
||||
}
|
||||
|
||||
async shareFile(file: TFile): Promise<SharedItem> {
|
||||
try {
|
||||
let response = await requestUrl({
|
||||
url: `${this.settings.url}/share.php`,
|
||||
method: "POST",
|
||||
body: JSON.stringify({content: await this.app.vault.cachedRead(file)})
|
||||
});
|
||||
let shared = response.json as SharedItem;
|
||||
shared.path = file.path;
|
||||
|
||||
await this.copyShareLink(shared, false);
|
||||
new Notice(`Successfully shared ${file.basename} and copied link to clipboard`);
|
||||
|
||||
this.settings.shared.push(shared);
|
||||
await this.saveSettings();
|
||||
|
||||
return shared;
|
||||
} catch (e) {
|
||||
new Notice(createFragment(f => {
|
||||
f.createSpan({text: `There was an error sharing ${file.basename}: `});
|
||||
f.createEl("code", {text: e});
|
||||
}), 10000);
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
async updateFile(item: SharedItem, file: TFile, notice = true): Promise<boolean> {
|
||||
try {
|
||||
await requestUrl({
|
||||
url: `${this.settings.url}/share.php?id=${item.id}`,
|
||||
method: "PATCH",
|
||||
headers: {"Password": item.password},
|
||||
body: JSON.stringify({content: await this.app.vault.cachedRead(file)})
|
||||
});
|
||||
new Notice(`Successfully updated ${file.basename} on JSP`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (notice) {
|
||||
new Notice(createFragment(f => {
|
||||
f.createSpan({text: `There was an error updating ${file.basename}: `});
|
||||
f.createEl("code", {text: e});
|
||||
}), 10000);
|
||||
}
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async deleteFile(item: SharedItem): Promise<boolean> {
|
||||
let name = basename(item.path, extname(item.path));
|
||||
try {
|
||||
await requestUrl({
|
||||
url: `${this.settings.url}/share.php?id=${item.id}`,
|
||||
method: "DELETE",
|
||||
headers: {"Password": item.password}
|
||||
});
|
||||
new Notice(`Successfully deleted ${name} from JSP`);
|
||||
|
||||
this.settings.shared.remove(item);
|
||||
await this.saveSettings();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
new Notice(createFragment(f => {
|
||||
f.createSpan({text: `There was an error deleting ${name}: `});
|
||||
f.createEl("code", {text: e});
|
||||
}), 10000);
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
async copyShareLink(item: SharedItem, notice = true): Promise<void> {
|
||||
await navigator.clipboard.writeText(`${this.settings.url}#${item.id}`);
|
||||
if (notice)
|
||||
new Notice(`Copied link to ${basename(item.path, extname(item.path))} to clipboard`);
|
||||
}
|
||||
}
|
||||
|
|
2
test-vault/.obsidian/appearance.json
vendored
2
test-vault/.obsidian/appearance.json
vendored
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"accentColor": "",
|
||||
"theme": "moonstone"
|
||||
"theme": "obsidian"
|
||||
}
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"url": "http://localhost:8080",
|
||||
"shared": []
|
||||
"shared": [
|
||||
{
|
||||
"id": "7dd626d1",
|
||||
"password": "6253e1ab4b813dc08d52ee7c82b0990b",
|
||||
"path": "Second note.md"
|
||||
},
|
||||
{
|
||||
"id": "281d96f9",
|
||||
"password": "2eb4979a9e853df98f5fcdc2cdc4b770",
|
||||
"path": "Cool Test Note.md"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue