Skip to content

Commit 527e047

Browse files
authored
Merge pull request #34 from NomarCub/remove-link-support
Remove link support
2 parents 227de9d + 82f3062 commit 527e047

8 files changed

+126
-151
lines changed

.markdownlint.jsonc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"blanks-around-lists": false,
3+
"line-length": false,
4+
"no-inline-html": false
5+
}

README.md

+47-56
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,47 @@
1-
# Copy Image and URL context menu
2-
3-
This plugin context the following context menus
4-
- for images
5-
- Copy Image
6-
- Open image in default app
7-
- Show in system explorer
8-
- Reveal file in navigation
9-
- Copy URL
10-
- Open PDF externally
11-
12-
in reading view in [Obsidian](https://obsidian.md/).
13-
14-
This makes copying URLs in reading view like it is in editing view by deafult.
15-
16-
See these other plugins for related functionality:
17-
- [Ozan's Image in Editor Plugin](https://github.com/ozntel/oz-image-in-editor-obsidian)
18-
- [Image Toolkit](https://github.com/sissilab/obsidian-image-toolkit)
19-
20-
Copying images:
21-
22-
[Copying images video](https://user-images.githubusercontent.com/1992842/132140547-fead74c1-4bec-489a-945c-f28cbba43493.mp4)
23-
24-
Copying URLs:
25-
26-
![Copying URLs on desktop](https://user-images.githubusercontent.com/5298006/125515738-8fb2143d-6502-46d3-a1b8-57b025211c2f.gif)
27-
28-
Opening PDFs externally:
29-
30-
![Opening PDFs externally on desktop](https://user-images.githubusercontent.com/5298006/171170626-5a94f5dc-61fc-4661-a9f2-38a0fb0181f5.gif)
31-
32-
All features work on mobile, but were only tested on Android. Mobile uses the native image sharing functionality instead of the clipboard, and it downloads online images temporarily so they can be shared.
33-
34-
![Copying URLs on Android](https://user-images.githubusercontent.com/5298006/125515758-bdf77074-a58c-4a6d-affa-88d031991ab2.gif)
35-
36-
## Installation
37-
38-
You can install the plugin via the Community Plugins tab within the Obsidian app.
39-
[Here](https://obsidian.md/plugins?id=copy-url-in-preview)'s the plugin in Obsidian's Community Plugins website.
40-
You can install the plugin manually by copying a release to your `.obsidian/plugins/copy-url-in-preview` folder.
41-
42-
## Development
43-
44-
This plugin follows the structure of the [Obsidian Sample Plugin](https://github.com/obsidianmd/obsidian-sample-plugin), see further details there.
45-
Contributions are welcome.
46-
47-
## Credits
48-
49-
Original plugin by [NomarCub](https://github.com/NomarCub).
50-
If you like this plugin you can sponsor me here on GitHub: [![Sponsor NomarCub](https://img.shields.io/static/v1?label=Sponsor%20NomarCub&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/NomarCub), on Ko-fi here: <a href='https://ko-fi.com/nomarcub' target='_blank'><img height='35' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' alt='Buy Me a Coffee at ko-fi.com' /></a>, or on PayPal here: [![Paypal](https://img.shields.io/badge/paypal-nomarcub-yellow?style=social&logo=paypal)](https://paypal.me/nomarcub).
51-
52-
[Copying](https://github.com/NomarCub/obsidian-copy-url-in-preview/pull/2) [images](https://github.com/NomarCub/obsidian-copy-url-in-preview/pull/3) developed by [luckman212](https://github.com/luckman212).
53-
[Android image sharing](https://github.com/NomarCub/obsidian-copy-url-in-preview/issues/5) developed by [mnaoumov](https://github.com/mnaoumov).
54-
[Open PDF externally](https://github.com/NomarCub/obsidian-copy-url-in-preview/issues/9) feature developed by [mnaoumov](https://github.com/mnaoumov).
55-
56-
Thank you to the makers of the [Tag Wrangler plugin](https://github.com/pjeby/tag-wrangler), as it was a great starting point for working with context menus in Obsidian.
1+
# Image Context Menus
2+
3+
This plugin provides the following context menus for images in [Obsidian](https://obsidian.md/):
4+
- Copy Image
5+
- Open image in default app
6+
- Show in system explorer
7+
- Reveal file in navigation
8+
9+
It also has an `Open PDF externally` context menu for PDFs.
10+
11+
> This plugin used to be called "Copy Image and URL context menu". It had link URL copying functionality (see [1.5.2](https://github.com/NomarCub/obsidian-copy-url-in-preview/tree/1.5.2) and prior), but that was removed when it was included in Obsidian 1.5.
12+
13+
See these other plugins for related functionality:
14+
- [Ozan's Image in Editor Plugin](https://github.com/ozntel/oz-image-in-editor-obsidian)
15+
- [Image Toolkit](https://github.com/sissilab/obsidian-image-toolkit)
16+
17+
Copying images:
18+
19+
[Copying images video](https://user-images.githubusercontent.com/1992842/132140547-fead74c1-4bec-489a-945c-f28cbba43493.mp4)
20+
21+
Opening PDFs externally:
22+
23+
![Opening PDFs externally on desktop](https://user-images.githubusercontent.com/5298006/171170626-5a94f5dc-61fc-4661-a9f2-38a0fb0181f5.gif)
24+
25+
All features work on mobile, but were only tested on Android. Mobile uses the native image sharing functionality instead of the clipboard, and it downloads online images temporarily so they can be shared.
26+
27+
## Installation
28+
29+
You can install the plugin via the Community Plugins tab within the Obsidian app.
30+
[Here](https://obsidian.md/plugins?id=copy-url-in-preview)'s the plugin in Obsidian's Community Plugins website.
31+
You can install the plugin manually by copying a release to your `.obsidian/plugins/copy-url-in-preview` folder.
32+
33+
## Development
34+
35+
This plugin follows the structure of the [Obsidian Sample Plugin](https://github.com/obsidianmd/obsidian-sample-plugin), see further details there.
36+
Contributions are welcome.
37+
38+
## Credits
39+
40+
Original plugin by [NomarCub](https://github.com/NomarCub).
41+
If you like this plugin you can sponsor me here on GitHub: [![Sponsor NomarCub](https://img.shields.io/static/v1?label=Sponsor%20NomarCub&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/NomarCub), on Ko-fi here: <a href='https://ko-fi.com/nomarcub' target='_blank'><img height='35' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' alt='Buy Me a Coffee at ko-fi.com' /></a>, or on PayPal here: [![Paypal](https://img.shields.io/badge/paypal-nomarcub-yellow?style=social&logo=paypal)](https://paypal.me/nomarcub).
42+
43+
[Copying](https://github.com/NomarCub/obsidian-copy-url-in-preview/pull/2) [images](https://github.com/NomarCub/obsidian-copy-url-in-preview/pull/3) developed by [luckman212](https://github.com/luckman212).
44+
[Android image sharing](https://github.com/NomarCub/obsidian-copy-url-in-preview/issues/5) developed by [mnaoumov](https://github.com/mnaoumov).
45+
[Open PDF externally](https://github.com/NomarCub/obsidian-copy-url-in-preview/issues/9) feature developed by [mnaoumov](https://github.com/mnaoumov).
46+
47+
Thank you to the makers of the [Tag Wrangler plugin](https://github.com/pjeby/tag-wrangler), as it was a great starting point for working with context menus in Obsidian.

manifest.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"id": "copy-url-in-preview",
3-
"name": "Copy Image and URL context menu",
4-
"version": "1.5.2",
5-
"minAppVersion": "1.4.11",
6-
"description": "Copy Image, Copy URL and Open PDF externally context menu in reading view (formerly preview mode)",
3+
"name": "Image Context Menus",
4+
"version": "1.6.0",
5+
"minAppVersion": "1.5.7",
6+
"description": "Copy, open in default app, show in system explorer, reveal in navigation context menu for images. Also Open PDF externally context menu.",
77
"author": "NomarCub",
88
"authorUrl": "https://github.com/NomarCub",
99
"fundingUrl": "https://ko-fi.com/nomarcub",

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "copy-url-in-preview",
3-
"version": "1.5.2",
3+
"version": "1.6.0",
44
"description": "Copy Image, Copy URL and Open PDF externally context menu in reading view (formerly preview mode) for Obsidian (https://obsidian.md)",
55
"main": "main.js",
66
"scripts": {
@@ -18,7 +18,7 @@
1818
"builtin-modules": "3.3.0",
1919
"esbuild": "0.17.3",
2020
"eslint": "8.46.0",
21-
"obsidian": "^1.4.11",
21+
"obsidian": "~1.5.7-1",
2222
"tslib": "2.4.0",
2323
"typescript": "4.7.4"
2424
}

src/helpers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { App, Editor, EditorPosition, FileSystemAdapter } from "obsidian";
22

3-
const loadImageBlobTimeout = 5000;
3+
const loadImageBlobTimeout = 5_000;
44

55
export interface ElectronWindow extends Window {
66
WEBVIEW_SERVER_URL: string

src/main.ts

+64-86
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import {
66
import { CopyUrlInPreviewSettingTab, CopyUrlInPreviewSettings, DEFAULT_SETTINGS } from "settings";
77

88
const IMAGE_URL_PREFIX = "/_capacitor_file_";
9-
const SUCCESS_NOTICE_TIMEOUT = 1800;
9+
const SUCCESS_NOTICE_TIMEOUT = 1_800;
1010
const longTapTimeout = 500;
11-
const deleteTempFileTimeout = 60000;
11+
const deleteTempFileTimeout = 60_000;
1212
const OPEN_PDF_MENU_BORDER_SIZE = 100;
13-
const OPEN_PDF_MENU_TIMEOUT = 5000;
13+
const OPEN_PDF_MENU_TIMEOUT = 5_000;
1414

1515
export default class CopyUrlInPreview extends Plugin {
1616
longTapTimeoutId: number | null = null;
@@ -37,15 +37,6 @@ export default class CopyUrlInPreview extends Plugin {
3737
}
3838

3939
registerDocument(document: Document) {
40-
this.register(
41-
onElement(
42-
document,
43-
"contextmenu" as keyof HTMLElementEventMap,
44-
"a.external-link",
45-
this.onClick.bind(this)
46-
)
47-
)
48-
4940
this.register(
5041
onElement(
5142
document,
@@ -70,7 +61,7 @@ export default class CopyUrlInPreview extends Plugin {
7061
document,
7162
"contextmenu" as keyof HTMLElementEventMap,
7263
"img",
73-
this.onClick.bind(this)
64+
this.onClickImage.bind(this)
7465
)
7566
)
7667

@@ -274,89 +265,76 @@ export default class CopyUrlInPreview extends Plugin {
274265
// Positions are not accurate from PointerEvent.
275266
// There's also TouchEvent
276267
// The event has target, path, toEvent (null on Android) for finding the link
277-
onClick(event: MouseEvent) {
268+
onClickImage(event: MouseEvent) {
269+
const imgElement = event.target;
270+
if (!(imgElement instanceof HTMLImageElement)) {
271+
console.error("imgElement is supposed to be a HTMLImageElement. imgElement:");
272+
console.error(imgElement);
273+
return;
274+
}
275+
278276
event.preventDefault();
279-
const target = (event.target as Element);
280-
const imgType = target.localName;
281277
const menu = new Menu();
282-
switch (imgType) {
283-
case "img": {
284-
const image = (target as HTMLImageElement).currentSrc;
285-
const url = new URL(image);
286-
const protocol = url.protocol;
287-
switch (protocol) {
288-
case "app:":
289-
case "data:":
290-
case "http:":
291-
case "https:":
278+
const image = imgElement.currentSrc;
279+
const url = new URL(image);
280+
const protocol = url.protocol;
281+
switch (protocol) {
282+
case "app:":
283+
case "data:":
284+
case "http:":
285+
case "https:":
286+
menu.addItem((item: MenuItem) => item
287+
.setIcon("image-file")
288+
.setTitle("Copy image to clipboard")
289+
.onClick(async () => {
290+
try {
291+
const blob = await loadImageBlob(image);
292+
const data = new ClipboardItem({ [blob.type]: blob });
293+
await navigator.clipboard.write([data]);
294+
new Notice("Image copied to the clipboard!", SUCCESS_NOTICE_TIMEOUT);
295+
} catch {
296+
new Notice("Error, could not copy the image!");
297+
}
298+
})
299+
);
300+
if (protocol === "app:" && Platform.isDesktop) {
301+
// getResourcePath("") also works for root path
302+
const baseFilePath = (this.app.vault.adapter as FileSystemAdapterWithInternalApi).getFilePath("");
303+
const baseFilePathName: string = baseFilePath.replace("file://", "");
304+
const urlPathName: string = url.pathname;
305+
if (urlPathName.startsWith(baseFilePathName)) {
306+
let relativePath = urlPathName.replace(baseFilePathName, "");
307+
relativePath = decodeURI(relativePath);
308+
292309
menu.addItem((item: MenuItem) => item
293-
.setIcon("image-file")
294-
.setTitle("Copy image to clipboard")
295-
.onClick(async () => {
296-
try {
297-
const blob = await loadImageBlob(image);
298-
const data = new ClipboardItem({ [blob.type]: blob });
299-
await navigator.clipboard.write([data]);
300-
new Notice("Image copied to the clipboard!", SUCCESS_NOTICE_TIMEOUT);
301-
} catch {
302-
new Notice("Error, could not copy the image!");
303-
}
310+
.setIcon("arrow-up-right")
311+
.setTitle("Open in default app")
312+
.onClick(() => (this.app as AppWithDesktopInternalApi).openWithDefaultApp(relativePath))
313+
);
314+
menu.addItem((item: MenuItem) => item
315+
.setIcon("arrow-up-right")
316+
.setTitle(Platform.isMacOS ? "Reveal in finder" : "Show in system explorer")
317+
.onClick(() => {
318+
(this.app as AppWithDesktopInternalApi).showInFolder(relativePath);
304319
})
305320
);
306-
if (protocol === "app:" && Platform.isDesktop) {
307-
// getResourcePath("") also works for root path
308-
const baseFilePath = (this.app.vault.adapter as FileSystemAdapterWithInternalApi).getFilePath("");
309-
const baseFilePathName: string = baseFilePath.replace("file://", "");
310-
const urlPathName: string = (url as any).pathname;
311-
if (urlPathName.startsWith(baseFilePathName)) {
312-
let relativePath = urlPathName.replace(baseFilePathName, "");
313-
relativePath = decodeURI(relativePath);
314-
315-
menu.addItem((item: MenuItem) => item
316-
.setIcon("arrow-up-right")
317-
.setTitle("Open in default app")
318-
.onClick(() => (this.app as AppWithDesktopInternalApi).openWithDefaultApp(relativePath))
319-
);
320-
menu.addItem((item: MenuItem) => item
321-
.setIcon("arrow-up-right")
322-
.setTitle(Platform.isMacOS ? "Reveal in finder" : "Show in system explorer")
323-
.onClick(() => {
324-
(this.app as AppWithDesktopInternalApi).showInFolder(relativePath);
325-
})
326-
);
327-
menu.addItem((item: MenuItem) => item
328-
.setIcon("folder")
329-
.setTitle("Reveal file in navigation")
330-
.onClick(() => {
331-
const abstractFilePath = this.app.vault.getAbstractFileByPath(relativePath.substring(1));
332-
(this.app as any).internalPlugins.getEnabledPluginById("file-explorer").revealInFolder(abstractFilePath);
333-
})
334-
);
335-
}
336-
}
337-
break;
338-
default:
339-
new Notice(`no handler for ${protocol} protocol`);
340-
return;
321+
menu.addItem((item: MenuItem) => item
322+
.setIcon("folder")
323+
.setTitle("Reveal file in navigation")
324+
.onClick(() => {
325+
const file = this.app.vault.getFileByPath(relativePath.substring(1));
326+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
327+
(this.app as any).internalPlugins.getEnabledPluginById("file-explorer").revealInFolder(file);
328+
})
329+
);
330+
}
341331
}
342332
break;
343-
}
344-
case "a": {
345-
const link = (target as HTMLAnchorElement).href;
346-
menu.addItem((item: MenuItem) => item
347-
.setIcon("link")
348-
.setTitle("Copy URL")
349-
.onClick(() => {
350-
navigator.clipboard.writeText(link);
351-
new Notice("URL copied to your clipboard", SUCCESS_NOTICE_TIMEOUT);
352-
})
353-
);
354-
break;
355-
}
356333
default:
357-
new Notice("No handler for this image type!");
334+
new Notice(`no handler for ${protocol} protocol`);
358335
return;
359336
}
337+
360338
this.registerEscapeButton(menu);
361339
menu.showAtPosition({ x: event.pageX, y: event.pageY });
362340
this.app.workspace.trigger("copy-url-in-preview:contextmenu", menu);

src/settings.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class CopyUrlInPreviewSettingTab extends PluginSettingTab {
1818
display() {
1919
const { containerEl } = this;
2020
containerEl.empty();
21-
containerEl.createEl("h3", { text: "Copy Image and URL context menu settings" });
21+
containerEl.createEl("h3", { text: "Image Context Menus settings" });
2222
new Setting(containerEl)
2323
.setName("PDF context menu")
2424
.addToggle((toggle) => {

versions.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"1.3.2": "0.14.8",
44
"1.3.5": "0.15.4",
55
"1.4.0": "0.16.3",
6-
"1.5.2": "1.4.11"
6+
"1.5.2": "1.4.11",
7+
"1.6.0": "1.5.7"
78
}

0 commit comments

Comments
 (0)