mirror of
https://github.com/nathonius/obsidian-github-link.git
synced 2026-07-22 09:20:25 +00:00
🐛 fix: #144 Tolerate badly formatted URLs
URL constructor should not throw error anymore. Known special paths are ignored. Closes: #144
This commit is contained in:
parent
8d495d990d
commit
2d42cb3edf
6 changed files with 77 additions and 9 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import { logger } from "../plugin";
|
||||
|
||||
export interface ParsedUrl {
|
||||
url: string;
|
||||
host: string;
|
||||
|
|
@ -18,7 +20,7 @@ export function repoAPIToBrowserUrl(urlString: string): string {
|
|||
return urlString.replace(apiRegex, "https://github.com/");
|
||||
}
|
||||
|
||||
export function parseUrl(urlString: string): ParsedUrl {
|
||||
export function parseUrl(urlString: string): ParsedUrl | null {
|
||||
// Some potential URLs:
|
||||
// https://github.com/nathonius/alloy-theme
|
||||
// https://github.com/nathonius/obsidian-trello/issues/45
|
||||
|
|
@ -28,7 +30,14 @@ export function parseUrl(urlString: string): ParsedUrl {
|
|||
// https://github.com/nathonius/obsidian-trello/blob/markdown/src/constants.ts#L44-L58
|
||||
// https://github.com/nathonius/obsidian-trello/commit/7ea069dd0641441ec20fb194f50e746a21abbaf1
|
||||
// https://github.com/nathonius/obsidian-trello/commit/7ea069dd0641441ec20fb194f50e746a21abbaf1#diff-8fa4b52909f895e8cda060d2035234e0a42ca2c7d3f8f8de1b35a056537bf199R35
|
||||
const url = new URL(urlString);
|
||||
let url: URL;
|
||||
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
} catch (err) {
|
||||
logger.error(`Attempted and failed to parse invalid URL: ${urlString}`);
|
||||
return null;
|
||||
}
|
||||
const parsedUrl: ParsedUrl = { url: urlString, host: url.hostname };
|
||||
|
||||
const urlParts = url.pathname.split("/");
|
||||
|
|
|
|||
39
src/github/urls.ts
Normal file
39
src/github/urls.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* These are paths that begin with `https://github.com` but should not
|
||||
* be processed by the plugin.
|
||||
*/
|
||||
const knownPaths = [
|
||||
"about",
|
||||
"account",
|
||||
"codespaces",
|
||||
"dashboard",
|
||||
"discussions",
|
||||
"explore",
|
||||
"gist",
|
||||
"github-copilot",
|
||||
"issues",
|
||||
"logout",
|
||||
"marketplace",
|
||||
"mine",
|
||||
"new",
|
||||
"organizations",
|
||||
"projects",
|
||||
"pulls",
|
||||
"search",
|
||||
"security",
|
||||
"settings",
|
||||
"sponsors",
|
||||
];
|
||||
|
||||
export function isAllowedPath(link: string): boolean {
|
||||
try {
|
||||
const url = new URL(link);
|
||||
const basePath = url.pathname.split("/")[1];
|
||||
if (knownPaths.includes(basePath)) {
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -8,14 +8,18 @@ import { RequestError } from "../util";
|
|||
import { parseUrl } from "../github/url-parse";
|
||||
import type { ParsedUrl } from "../github/url-parse";
|
||||
import { getIssue, getPullRequest } from "../github/github";
|
||||
import { isAllowedPath } from "../github/urls";
|
||||
|
||||
interface TagConfig {
|
||||
icon: HTMLSpanElement;
|
||||
sections: HTMLElement[];
|
||||
}
|
||||
|
||||
export function createTag(href: string): HTMLAnchorElement {
|
||||
export function createTag(href: string): HTMLAnchorElement | null {
|
||||
const parsedUrl = parseUrl(href);
|
||||
if (!parsedUrl) {
|
||||
return null;
|
||||
}
|
||||
const container = createEl("a", { cls: "github-link-inline", href, attr: { target: "_blank" } });
|
||||
const config: TagConfig = {
|
||||
icon: createSpan({ cls: ["github-link-status-icon", "github-link-inline-icon"] }),
|
||||
|
|
@ -162,11 +166,17 @@ function createErrorSection(config: TagConfig, container: HTMLAnchorElement, err
|
|||
}
|
||||
|
||||
export function InlineRenderer(el: HTMLElement) {
|
||||
const githubLinks = el.querySelectorAll<HTMLAnchorElement>(`a.external-link[href^="https://github.com"]`);
|
||||
let githubLinks = Array.from(el.querySelectorAll<HTMLAnchorElement>(`a.external-link[href^="https://github.com"]`));
|
||||
|
||||
// Filter out some special URLs from github
|
||||
githubLinks = githubLinks.filter((l) => isAllowedPath(l.href));
|
||||
|
||||
for (const anchor of Array.from(githubLinks)) {
|
||||
if (anchor.href === anchor.innerText) {
|
||||
const container = createTag(anchor.href);
|
||||
anchor.replaceWith(container);
|
||||
if (container) {
|
||||
anchor.replaceWith(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type { DecorationSet, PluginValue, EditorView, ViewUpdate } from "@codemi
|
|||
import { Decoration, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
|
||||
|
||||
import type { GithubLinkPlugin } from "../plugin";
|
||||
import { isAllowedPath } from "../github/urls";
|
||||
import { createTag } from "./inline";
|
||||
|
||||
interface DecoSpec {
|
||||
|
|
@ -28,7 +29,9 @@ class InlineTagWidget extends WidgetType {
|
|||
toDOM(): HTMLElement {
|
||||
const container = createSpan();
|
||||
const tag = createTag(this.href);
|
||||
container.appendChild(tag);
|
||||
if (tag) {
|
||||
container.appendChild(tag);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
|
@ -83,6 +86,11 @@ export function createInlineViewPlugin(_plugin: GithubLinkPlugin) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if it's not an allowed URL
|
||||
if (!isAllowedPath(match[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we're in a codeblock
|
||||
// Note, codeblock check is more expensive than some others,
|
||||
// But we do it first to ensure this.inCodeblock remains accurate
|
||||
|
|
@ -116,7 +124,7 @@ export function createInlineViewPlugin(_plugin: GithubLinkPlugin) {
|
|||
}
|
||||
|
||||
// Ignore matches inside a markdown link
|
||||
// TODO: This could probably be a regex.
|
||||
// TODO: This can probably be removed now that the regex is updated
|
||||
const input = match.input ?? "";
|
||||
const index = match.index ?? 0;
|
||||
const matchValue = match[0];
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export const CommonIssuePRColumns: ColumnsMap = {
|
|||
el.classList.add("github-link-table-repo");
|
||||
const url = repoAPIToBrowserUrl((row as IssueListResponse[number]).repository_url);
|
||||
const parsed = parseUrl(url);
|
||||
el.createEl("a", { text: parsed.repo, href: url, attr: { target: "_blank" } });
|
||||
el.createEl("a", { text: parsed?.repo ?? "Repo", href: url, attr: { target: "_blank" } });
|
||||
},
|
||||
},
|
||||
author: {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ export const IssueColumns: ColumnsMap = {
|
|||
return;
|
||||
}
|
||||
const tag = createTag(pullRequestUrl);
|
||||
el.appendChild(tag);
|
||||
if (tag) {
|
||||
el.appendChild(tag);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue