mirror of
https://github.com/Ellpeck/ObsidianJustSharePlease.git
synced 2024-05-30 06:13:37 +02:00
Compare commits
5 commits
33bfe95ca5
...
0717165809
Author | SHA1 | Date | |
---|---|---|---|
Ell | 0717165809 | ||
Ell | ad6b1a223f | ||
Ell | fa85bd8d93 | ||
Ell | c9a1dae9a2 | ||
Ell | 36f68d47bc |
955
package-lock.json
generated
955
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,6 @@
|
|||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
"builtin-modules": "^3.2.0",
|
||||
"electron": "^13.6.2",
|
||||
"esbuild": "0.14.0",
|
||||
"esbuild-plugin-copy": "^1.3.0",
|
||||
"obsidian": "latest",
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.5/dist/purify.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/highlight.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked@7.0.2/lib/marked.umd.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked-katex-extension@3.0.3/lib/index.umd.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked-highlight@2.0.4/lib/index.umd.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it-texmath/texmath.min.js"></script>
|
||||
|
||||
<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">
|
||||
|
@ -27,14 +27,19 @@
|
|||
<div class="content">
|
||||
<div id="main">
|
||||
<script>
|
||||
marked.use(markedKatex());
|
||||
marked.use(markedHighlight.markedHighlight({
|
||||
let md = markdownit({
|
||||
html: true,
|
||||
linkify: true,
|
||||
langPrefix: "hljs language-",
|
||||
highlight: (c, l) => {
|
||||
const language = hljs.getLanguage(l) ? l : "plaintext";
|
||||
return hljs.highlight(c, {language}).value;
|
||||
}
|
||||
}));
|
||||
});
|
||||
md.use(texmath, {
|
||||
engine: katex,
|
||||
delimiters: ["dollars", "beg_end"]
|
||||
});
|
||||
|
||||
let main = $("#main");
|
||||
$(window).on("hashchange", display);
|
||||
|
@ -47,7 +52,7 @@
|
|||
$.ajax({
|
||||
method: "get",
|
||||
url: hash ? `share.php?id=${hash}` : "index.md",
|
||||
success: t => main.html(DOMPurify.sanitize(marked.parse(t))),
|
||||
success: t => main.html(DOMPurify.sanitize(md.render(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>`)
|
||||
});
|
||||
}
|
||||
|
|
65
src/main.ts
65
src/main.ts
|
@ -1,21 +1,30 @@
|
|||
import {Notice, Plugin, requestUrl, TFile} from "obsidian";
|
||||
import {arrayBufferToBase64, Notice, Plugin, requestUrl, TFile} from "obsidian";
|
||||
import {defaultSettings, JSPSettings, SharedItem} from "./settings";
|
||||
import {JSPSettingsTab} from "./settings-tab";
|
||||
import {basename, extname} from "path";
|
||||
import {JSPView} from "./view";
|
||||
|
||||
export default class JustSharePleasePlugin extends Plugin {
|
||||
|
||||
// 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;
|
||||
public settings: JSPSettings;
|
||||
|
||||
async onload(): Promise<void> {
|
||||
await this.loadSettings();
|
||||
this.addSettingTab(new JSPSettingsTab(this.app, this));
|
||||
|
||||
this.registerView(JSPView.type, l => new JSPView(this, l));
|
||||
this.addCommand({
|
||||
id: `open-${JSPView.type}`,
|
||||
name: `Open Just Share Please view`,
|
||||
callback: async () => {
|
||||
if (!this.app.workspace.getLeavesOfType(JSPView.type).length)
|
||||
await this.app.workspace.getRightLeaf(false).setViewState({type: JSPView.type, active: true});
|
||||
this.app.workspace.revealLeaf(this.app.workspace.getLeavesOfType(JSPView.type)[0]);
|
||||
}
|
||||
});
|
||||
|
||||
this.registerEvent(this.app.workspace.on("file-menu", async (m, f) => {
|
||||
if (f instanceof TFile) {
|
||||
if (f instanceof TFile && f.extension == "md") {
|
||||
let shared = this.getSharedItem(f);
|
||||
if (!shared) {
|
||||
m.addItem(i => {
|
||||
|
@ -94,6 +103,7 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async loadSettings(): Promise<void> {
|
||||
|
@ -113,7 +123,7 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
let response = await requestUrl({
|
||||
url: `${this.settings.url}/share.php`,
|
||||
method: "POST",
|
||||
body: JSON.stringify({content: await this.app.vault.cachedRead(file)})
|
||||
body: JSON.stringify({content: await this.preProcessMarkdown(file)})
|
||||
});
|
||||
let shared = response.json as SharedItem;
|
||||
shared.path = file.path;
|
||||
|
@ -123,6 +133,7 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
|
||||
this.settings.shared.push(shared);
|
||||
await this.saveSettings();
|
||||
this.refreshAllViews();
|
||||
|
||||
return shared;
|
||||
} catch (e) {
|
||||
|
@ -140,7 +151,7 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
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)})
|
||||
body: JSON.stringify({content: await this.preProcessMarkdown(file)})
|
||||
});
|
||||
new Notice(`Successfully updated ${file.basename} on JSP`);
|
||||
return true;
|
||||
|
@ -168,6 +179,7 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
|
||||
this.settings.shared.remove(item);
|
||||
await this.saveSettings();
|
||||
this.refreshAllViews();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
@ -184,4 +196,41 @@ export default class JustSharePleasePlugin extends Plugin {
|
|||
if (notice)
|
||||
new Notice(`Copied link to ${basename(item.path, extname(item.path))} to clipboard`);
|
||||
}
|
||||
|
||||
async preProcessMarkdown(file: TFile): Promise<string> {
|
||||
let text = await this.app.vault.cachedRead(file);
|
||||
|
||||
// strip frontmatter
|
||||
if (this.settings.stripFrontmatter)
|
||||
text = text.replace(/^---\s*\n.*?\n---\s*\n(.*)$/s, "$1");
|
||||
|
||||
// embed attachments directly
|
||||
let attachments = /!\[(.*)]\((.+)\)|!\[\[(.+)]]/g;
|
||||
let match: RegExpExecArray;
|
||||
while ((match = attachments.exec(text)) != null) {
|
||||
let alt = match[1] ?? "";
|
||||
let url = match[2] ?? match[3];
|
||||
if (url.startsWith("http"))
|
||||
continue;
|
||||
try {
|
||||
let resolved = this.app.metadataCache.getFirstLinkpathDest(url, file.path).path;
|
||||
let attachment = this.app.vault.getAbstractFileByPath(resolved);
|
||||
let data = arrayBufferToBase64(await this.app.vault.readBinary(attachment as TFile));
|
||||
let img = `<img src="data:image/${extname(resolved).substring(1)};base64, ${data}" alt="${alt}">`;
|
||||
text = text.substring(0, match.index) + img + text.substring(match.index + match[0].length);
|
||||
} catch (e) {
|
||||
console.log(`Error embedding attachment ${url}: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// TODO refresh when a file is moved or deleted in Obsidian
|
||||
refreshAllViews(): void {
|
||||
for (let leaf of this.app.workspace.getLeavesOfType(JSPView.type)) {
|
||||
if (leaf.view instanceof JSPView)
|
||||
leaf.view.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
export const defaultSettings: JSPSettings = {
|
||||
url: "http://localhost:8080",
|
||||
shared: []
|
||||
shared: [],
|
||||
stripFrontmatter: true
|
||||
};
|
||||
|
||||
// TODO add a setting for auto-refreshing uploads when saving
|
||||
// TODO add a setting for auto-removing JSP shares when the original file is deleted
|
||||
export interface JSPSettings {
|
||||
|
||||
url: string;
|
||||
shared: SharedItem[];
|
||||
stripFrontmatter: boolean;
|
||||
|
||||
}
|
||||
|
||||
|
@ -14,6 +18,7 @@ export interface SharedItem {
|
|||
|
||||
id: string;
|
||||
password: string;
|
||||
// TODO auto-update path when file is moved
|
||||
path: string;
|
||||
|
||||
}
|
||||
|
|
66
src/view.ts
Normal file
66
src/view.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import {ButtonComponent, ItemView, TFile, WorkspaceLeaf} from "obsidian";
|
||||
import {basename, extname} from "path";
|
||||
import JustSharePleasePlugin from "./main";
|
||||
|
||||
export class JSPView extends ItemView {
|
||||
|
||||
public static readonly type: string = "jsp-view";
|
||||
|
||||
private readonly plugin: JustSharePleasePlugin;
|
||||
|
||||
constructor(plugin: JustSharePleasePlugin, leaf: WorkspaceLeaf) {
|
||||
super(leaf);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public refresh(): void {
|
||||
this.contentEl.empty();
|
||||
let content = this.contentEl.createDiv({cls: "just-share-please-view"});
|
||||
for (let shared of this.plugin.settings.shared) {
|
||||
let file = this.plugin.app.vault.getAbstractFileByPath(shared.path) as TFile;
|
||||
let div = content.createDiv({cls: "just-share-please-shared-item"});
|
||||
div.createSpan({cls: "just-share-please-shared-name", text: basename(shared.path, extname(shared.path))});
|
||||
new ButtonComponent(div)
|
||||
.setClass("clickable-icon")
|
||||
.setTooltip("Copy JSP link")
|
||||
.setIcon("link")
|
||||
.onClick(async () => this.plugin.copyShareLink(shared));
|
||||
if (file) {
|
||||
new ButtonComponent(div)
|
||||
.setClass("clickable-icon")
|
||||
.setTooltip("Open in Obsidian")
|
||||
.setIcon("edit")
|
||||
.onClick(async () => {
|
||||
// TODO open in obsidian
|
||||
});
|
||||
new ButtonComponent(div)
|
||||
.setClass("clickable-icon")
|
||||
.setTooltip("Update in JSP")
|
||||
.setIcon("share")
|
||||
.onClick(async () => this.plugin.updateFile(shared, file));
|
||||
}
|
||||
new ButtonComponent(div)
|
||||
.setClass("clickable-icon")
|
||||
.setTooltip("Delete from JSP")
|
||||
.setIcon("trash")
|
||||
.onClick(async () => this.plugin.deleteFile(shared));
|
||||
}
|
||||
}
|
||||
|
||||
public onload(): void {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public getDisplayText(): string {
|
||||
return "Just Share Please";
|
||||
}
|
||||
|
||||
public getViewType(): string {
|
||||
return JSPView.type;
|
||||
}
|
||||
|
||||
public getIcon(): string {
|
||||
return "share";
|
||||
}
|
||||
|
||||
}
|
14
styles.css
14
styles.css
|
@ -3,3 +3,17 @@
|
|||
width: 400px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.just-share-please-view .clickable-icon {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.just-share-please-shared-name {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.just-share-please-shared-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
"url": "http://localhost:8080",
|
||||
"shared": [
|
||||
{
|
||||
"id": "7dd626d1",
|
||||
"password": "6253e1ab4b813dc08d52ee7c82b0990b",
|
||||
"path": "Second note.md"
|
||||
},
|
||||
{
|
||||
"id": "281d96f9",
|
||||
"password": "2eb4979a9e853df98f5fcdc2cdc4b770",
|
||||
"id": "de56fe78",
|
||||
"password": "2d276f4d3c0715be08ad1812faa97deb",
|
||||
"path": "Cool Test Note.md"
|
||||
}
|
||||
]
|
||||
],
|
||||
"stripFrontmatter": true
|
||||
}
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
test: yes
|
||||
---
|
||||
|
||||
yo
|
||||
# Cool Test Note
|
||||
|
||||
This is a cool test note, my friends!
|
||||
|
@ -30,4 +35,14 @@ cool!!
|
|||
The following is $x^2 = 7$, but more complicated!
|
||||
$$
|
||||
x^2 + \sum_{i = 1}^{10000} x^2 \cdot 0 = 7
|
||||
$$
|
||||
$$
|
||||
|
||||
image!
|
||||
|
||||
![this is an image my friends, and this is my alt text](Obsidian_TtC7w4GA86.png)
|
||||
|
||||
wikilink image!
|
||||
|
||||
![[Pasted image 20230816130420.png]]
|
||||
|
||||
nice
|
BIN
test-vault/Obsidian_TtC7w4GA86.png
Normal file
BIN
test-vault/Obsidian_TtC7w4GA86.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
BIN
test-vault/subdir/Pasted image 20230816130420.png
Normal file
BIN
test-vault/subdir/Pasted image 20230816130420.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 144 KiB |
Loading…
Reference in a new issue