@real1ty-obsidian-plugins/utils 2.25.0 → 2.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -22,15 +22,16 @@ export interface WhatsNewModalConfig {
|
|
|
22
22
|
/**
|
|
23
23
|
* URL to support/donate page.
|
|
24
24
|
*/
|
|
25
|
-
support
|
|
25
|
+
support: string;
|
|
26
26
|
/**
|
|
27
27
|
* URL to full changelog page.
|
|
28
28
|
*/
|
|
29
|
-
changelog
|
|
29
|
+
changelog: string;
|
|
30
30
|
/**
|
|
31
|
-
* URL to
|
|
31
|
+
* Base URL for documentation (used to resolve relative links in changelog).
|
|
32
|
+
* Example: "https://docs.example.com" or "https://docs.example.com/"
|
|
32
33
|
*/
|
|
33
|
-
documentation
|
|
34
|
+
documentation: string;
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
@@ -53,8 +54,8 @@ export declare class WhatsNewModal extends Modal {
|
|
|
53
54
|
private addCls;
|
|
54
55
|
/**
|
|
55
56
|
* Makes external links in rendered markdown clickable by adding click handlers.
|
|
56
|
-
*
|
|
57
|
-
*
|
|
57
|
+
* Handles both absolute URLs (http/https) and relative URLs (starting with /).
|
|
58
|
+
* Relative URLs are resolved against the documentation base URL.
|
|
58
59
|
*/
|
|
59
60
|
private makeExternalLinksClickable;
|
|
60
61
|
onOpen(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whats-new-modal.d.ts","sourceRoot":"","sources":["../../src/components/whats-new-modal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAoB,KAAK,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE;QACN;;WAEG;QACH,OAAO,
|
|
1
|
+
{"version":3,"file":"whats-new-modal.d.ts","sourceRoot":"","sources":["../../src/components/whats-new-modal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAoB,KAAK,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE;QACN;;WAEG;QACH,OAAO,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;QAElB;;;WAGG;QACH,aAAa,EAAE,MAAM,CAAC;KACtB,CAAC;CACF;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAGtC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;gBAJjB,GAAG,EAAE,GAAG,EACA,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;IAK1B;;OAEG;IACH,OAAO,CAAC,GAAG;IAIX;;OAEG;IACH,OAAO,CAAC,MAAM;IAId;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;IAmC5B,MAAM;IAgGZ,OAAO;CAGP"}
|
|
@@ -27,22 +27,36 @@ export class WhatsNewModal extends Modal {
|
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Makes external links in rendered markdown clickable by adding click handlers.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Handles both absolute URLs (http/https) and relative URLs (starting with /).
|
|
31
|
+
* Relative URLs are resolved against the documentation base URL.
|
|
32
32
|
*/
|
|
33
33
|
makeExternalLinksClickable(container) {
|
|
34
34
|
const links = container.querySelectorAll("a[href]");
|
|
35
35
|
// Convert NodeList to Array for iteration
|
|
36
36
|
Array.from(links).forEach((link) => {
|
|
37
37
|
const href = link.getAttribute("href");
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if (!href)
|
|
39
|
+
return;
|
|
40
|
+
let finalUrl = null;
|
|
41
|
+
// Handle absolute HTTP(S) links
|
|
42
|
+
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
43
|
+
finalUrl = href;
|
|
44
|
+
}
|
|
45
|
+
// Handle relative links (starting with /)
|
|
46
|
+
else if (href.startsWith("/")) {
|
|
47
|
+
// Get base documentation URL and ensure proper slash handling
|
|
48
|
+
const baseUrl = this.config.links.documentation;
|
|
49
|
+
const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
50
|
+
finalUrl = `${normalizedBase}${href}`;
|
|
51
|
+
}
|
|
52
|
+
// Add click handler for external links
|
|
53
|
+
if (finalUrl) {
|
|
40
54
|
link.addEventListener("click", (event) => {
|
|
41
55
|
event.preventDefault();
|
|
42
|
-
window.open(
|
|
56
|
+
window.open(finalUrl, "_blank");
|
|
43
57
|
});
|
|
44
58
|
// Add visual indicator that it's an external link
|
|
45
|
-
link.
|
|
59
|
+
link.classList.add("external-link");
|
|
46
60
|
}
|
|
47
61
|
});
|
|
48
62
|
}
|
|
@@ -60,23 +74,21 @@ export class WhatsNewModal extends Modal {
|
|
|
60
74
|
text: `Changes since v${this.fromVersion}`,
|
|
61
75
|
cls: this.cls("whats-new-subtitle"),
|
|
62
76
|
});
|
|
63
|
-
// Support section
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
contentEl.createEl("hr");
|
|
79
|
-
}
|
|
77
|
+
// Support section
|
|
78
|
+
const supportSection = contentEl.createDiv({
|
|
79
|
+
cls: this.cls("whats-new-support"),
|
|
80
|
+
});
|
|
81
|
+
supportSection.createEl("h3", { text: "Support My Work" });
|
|
82
|
+
const supportText = supportSection.createEl("p");
|
|
83
|
+
supportText.createSpan({ text: "If you enjoy using this plugin, please consider " });
|
|
84
|
+
supportText.createEl("a", {
|
|
85
|
+
text: "supporting my work",
|
|
86
|
+
href: this.config.links.support,
|
|
87
|
+
});
|
|
88
|
+
supportText.createSpan({
|
|
89
|
+
text: ". Your support helps keep this plugin maintained and improved!",
|
|
90
|
+
});
|
|
91
|
+
contentEl.createEl("hr");
|
|
80
92
|
// Changelog content
|
|
81
93
|
const changelogSections = getChangelogSince(this.config.changelogContent, this.fromVersion, this.toVersion);
|
|
82
94
|
if (changelogSections.length === 0) {
|
|
@@ -98,24 +110,20 @@ export class WhatsNewModal extends Modal {
|
|
|
98
110
|
const buttonContainer = contentEl.createDiv({
|
|
99
111
|
cls: this.cls("whats-new-buttons"),
|
|
100
112
|
});
|
|
101
|
-
// Full changelog button
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
docsBtn.addEventListener("click", () => {
|
|
116
|
-
window.open(this.config.links.documentation, "_blank");
|
|
117
|
-
});
|
|
118
|
-
}
|
|
113
|
+
// Full changelog button
|
|
114
|
+
const changelogBtn = buttonContainer.createEl("button", {
|
|
115
|
+
text: "Full Changelog",
|
|
116
|
+
});
|
|
117
|
+
changelogBtn.addEventListener("click", () => {
|
|
118
|
+
window.open(this.config.links.changelog, "_blank");
|
|
119
|
+
});
|
|
120
|
+
// Documentation button
|
|
121
|
+
const docsBtn = buttonContainer.createEl("button", {
|
|
122
|
+
text: "Documentation",
|
|
123
|
+
});
|
|
124
|
+
docsBtn.addEventListener("click", () => {
|
|
125
|
+
window.open(this.config.links.documentation, "_blank");
|
|
126
|
+
});
|
|
119
127
|
// Close button (always present)
|
|
120
128
|
const closeBtn = buttonContainer.createEl("button", {
|
|
121
129
|
text: "Close",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whats-new-modal.js","sourceRoot":"","sources":["../../src/components/whats-new-modal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, Plugin } from \"obsidian\";\nimport { MarkdownRenderer, Modal } from \"obsidian\";\nimport { formatChangelogSections, getChangelogSince } from \"../string/changelog-parser\";\n\nexport interface WhatsNewModalConfig {\n\t/**\n\t * The CSS class prefix/suffix to use for styling.\n\t * Example: \"custom-calendar\" will generate classes like \"custom-calendar-whats-new-modal\"\n\t */\n\tcssPrefix: string;\n\n\t/**\n\t * Display name of the plugin.\n\t * Example: \"Custom Calendar\"\n\t */\n\tpluginName: string;\n\n\t/**\n\t * Raw changelog markdown content to parse.\n\t */\n\tchangelogContent: string;\n\n\t/**\n\t * Links to external resources.\n\t */\n\tlinks: {\n\t\t/**\n\t\t * URL to support/donate page.\n\t\t */\n\t\tsupport?: string;\n\n\t\t/**\n\t\t * URL to full changelog page.\n\t\t */\n\t\tchangelog?: string;\n\n\t\t/**\n\t\t * URL to documentation.\n\t\t */\n\t\tdocumentation?: string;\n\t};\n}\n\n/**\n * Generic \"What's New\" modal that displays changelog entries between versions.\n * Supports custom CSS prefixes, plugin names, and configurable links.\n */\nexport class WhatsNewModal extends Modal {\n\tconstructor(\n\t\tapp: App,\n\t\tprivate plugin: Plugin,\n\t\tprivate config: WhatsNewModalConfig,\n\t\tprivate fromVersion: string,\n\t\tprivate toVersion: string\n\t) {\n\t\tsuper(app);\n\t}\n\n\t/**\n\t * Helper to create CSS class names with the configured prefix.\n\t */\n\tprivate cls(suffix: string): string {\n\t\treturn `${this.config.cssPrefix}-${suffix}`;\n\t}\n\n\t/**\n\t * Helper to add CSS class to an element.\n\t */\n\tprivate addCls(el: HTMLElement, suffix: string): void {\n\t\tel.classList.add(this.cls(suffix));\n\t}\n\n\t/**\n\t * Makes external links in rendered markdown clickable by adding click handlers.\n\t * Finds all anchor tags with external URLs (http/https) and adds click events\n\t * that open the links in the user's default browser.\n\t */\n\tprivate makeExternalLinksClickable(container: HTMLElement): void {\n\t\tconst links = container.querySelectorAll<HTMLAnchorElement>(\"a[href]\");\n\n\t\t// Convert NodeList to Array for iteration\n\t\tArray.from(links).forEach((link) => {\n\t\t\tconst href = link.getAttribute(\"href\");\n\n\t\t\t// Only handle external HTTP(S) links\n\t\t\tif (href && (href.startsWith(\"http://\") || href.startsWith(\"https://\"))) {\n\t\t\t\tlink.addEventListener(\"click\", (event: MouseEvent) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\twindow.open(href, \"_blank\");\n\t\t\t\t});\n\n\t\t\t\t// Add visual indicator that it's an external link\n\t\t\t\tlink.addClass(\"external-link\");\n\t\t\t}\n\t\t});\n\t}\n\n\tasync onOpen() {\n\t\tconst { contentEl } = this;\n\t\tcontentEl.empty();\n\n\t\tthis.addCls(contentEl, \"whats-new-modal\");\n\n\t\t// Header section\n\t\tconst header = contentEl.createDiv({ cls: this.cls(\"whats-new-header\") });\n\t\theader.createEl(\"h2\", {\n\t\t\ttext: `${this.config.pluginName} updated to v${this.toVersion}`,\n\t\t});\n\n\t\theader.createEl(\"p\", {\n\t\t\ttext: `Changes since v${this.fromVersion}`,\n\t\t\tcls: this.cls(\"whats-new-subtitle\"),\n\t\t});\n\n\t\t// Support section (optional)\n\t\tif (this.config.links.support) {\n\t\t\tconst supportSection = contentEl.createDiv({\n\t\t\t\tcls: this.cls(\"whats-new-support\"),\n\t\t\t});\n\n\t\t\tsupportSection.createEl(\"h3\", { text: \"Support My Work\" });\n\n\t\t\tconst supportText = supportSection.createEl(\"p\");\n\t\t\tsupportText.createSpan({ text: \"If you enjoy using this plugin, please consider \" });\n\t\t\tsupportText.createEl(\"a\", {\n\t\t\t\ttext: \"supporting my work\",\n\t\t\t\thref: this.config.links.support,\n\t\t\t});\n\t\t\tsupportText.createSpan({\n\t\t\t\ttext: \". Your support helps keep this plugin maintained and improved!\",\n\t\t\t});\n\n\t\t\tcontentEl.createEl(\"hr\");\n\t\t}\n\n\t\t// Changelog content\n\t\tconst changelogSections = getChangelogSince(\n\t\t\tthis.config.changelogContent,\n\t\t\tthis.fromVersion,\n\t\t\tthis.toVersion\n\t\t);\n\n\t\tif (changelogSections.length === 0) {\n\t\t\tcontentEl.createEl(\"p\", {\n\t\t\t\ttext: \"No significant changes found in this update.\",\n\t\t\t\tcls: this.cls(\"whats-new-empty\"),\n\t\t\t});\n\t\t} else {\n\t\t\tconst changelogContainer = contentEl.createDiv({\n\t\t\t\tcls: this.cls(\"whats-new-content\"),\n\t\t\t});\n\n\t\t\tconst markdownContent = formatChangelogSections(changelogSections);\n\n\t\t\tawait MarkdownRenderer.render(\n\t\t\t\tthis.app,\n\t\t\t\tmarkdownContent,\n\t\t\t\tchangelogContainer,\n\t\t\t\t\"/\",\n\t\t\t\tthis.plugin\n\t\t\t);\n\n\t\t\t// Make external links clickable\n\t\t\tthis.makeExternalLinksClickable(changelogContainer);\n\t\t}\n\n\t\t// Action buttons\n\t\tconst buttonContainer = contentEl.createDiv({\n\t\t\tcls: this.cls(\"whats-new-buttons\"),\n\t\t});\n\n\t\t// Full changelog button (optional)\n\t\tif (this.config.links.changelog) {\n\t\t\tconst changelogBtn = buttonContainer.createEl(\"button\", {\n\t\t\t\ttext: \"Full Changelog\",\n\t\t\t});\n\t\t\tchangelogBtn.addEventListener(\"click\", () => {\n\t\t\t\twindow.open(this.config.links.changelog, \"_blank\");\n\t\t\t});\n\t\t}\n\n\t\t// Documentation button (optional)\n\t\tif (this.config.links.documentation) {\n\t\t\tconst docsBtn = buttonContainer.createEl(\"button\", {\n\t\t\t\ttext: \"Documentation\",\n\t\t\t});\n\t\t\tdocsBtn.addEventListener(\"click\", () => {\n\t\t\t\twindow.open(this.config.links.documentation, \"_blank\");\n\t\t\t});\n\t\t}\n\n\t\t// Close button (always present)\n\t\tconst closeBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Close\",\n\t\t\tcls: this.cls(\"mod-cta\"),\n\t\t});\n\t\tcloseBtn.addEventListener(\"click\", () => this.close());\n\t}\n\n\tonClose() {\n\t\tthis.contentEl.empty();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"whats-new-modal.js","sourceRoot":"","sources":["../../src/components/whats-new-modal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, Plugin } from \"obsidian\";\nimport { MarkdownRenderer, Modal } from \"obsidian\";\nimport { formatChangelogSections, getChangelogSince } from \"../string/changelog-parser\";\n\nexport interface WhatsNewModalConfig {\n\t/**\n\t * The CSS class prefix/suffix to use for styling.\n\t * Example: \"custom-calendar\" will generate classes like \"custom-calendar-whats-new-modal\"\n\t */\n\tcssPrefix: string;\n\n\t/**\n\t * Display name of the plugin.\n\t * Example: \"Custom Calendar\"\n\t */\n\tpluginName: string;\n\n\t/**\n\t * Raw changelog markdown content to parse.\n\t */\n\tchangelogContent: string;\n\n\t/**\n\t * Links to external resources.\n\t */\n\tlinks: {\n\t\t/**\n\t\t * URL to support/donate page.\n\t\t */\n\t\tsupport: string;\n\n\t\t/**\n\t\t * URL to full changelog page.\n\t\t */\n\t\tchangelog: string;\n\n\t\t/**\n\t\t * Base URL for documentation (used to resolve relative links in changelog).\n\t\t * Example: \"https://docs.example.com\" or \"https://docs.example.com/\"\n\t\t */\n\t\tdocumentation: string;\n\t};\n}\n\n/**\n * Generic \"What's New\" modal that displays changelog entries between versions.\n * Supports custom CSS prefixes, plugin names, and configurable links.\n */\nexport class WhatsNewModal extends Modal {\n\tconstructor(\n\t\tapp: App,\n\t\tprivate plugin: Plugin,\n\t\tprivate config: WhatsNewModalConfig,\n\t\tprivate fromVersion: string,\n\t\tprivate toVersion: string\n\t) {\n\t\tsuper(app);\n\t}\n\n\t/**\n\t * Helper to create CSS class names with the configured prefix.\n\t */\n\tprivate cls(suffix: string): string {\n\t\treturn `${this.config.cssPrefix}-${suffix}`;\n\t}\n\n\t/**\n\t * Helper to add CSS class to an element.\n\t */\n\tprivate addCls(el: HTMLElement, suffix: string): void {\n\t\tel.classList.add(this.cls(suffix));\n\t}\n\n\t/**\n\t * Makes external links in rendered markdown clickable by adding click handlers.\n\t * Handles both absolute URLs (http/https) and relative URLs (starting with /).\n\t * Relative URLs are resolved against the documentation base URL.\n\t */\n\tprivate makeExternalLinksClickable(container: HTMLElement): void {\n\t\tconst links = container.querySelectorAll<HTMLAnchorElement>(\"a[href]\");\n\n\t\t// Convert NodeList to Array for iteration\n\t\tArray.from(links).forEach((link) => {\n\t\t\tconst href = link.getAttribute(\"href\");\n\t\t\tif (!href) return;\n\n\t\t\tlet finalUrl: string | null = null;\n\n\t\t\t// Handle absolute HTTP(S) links\n\t\t\tif (href.startsWith(\"http://\") || href.startsWith(\"https://\")) {\n\t\t\t\tfinalUrl = href;\n\t\t\t}\n\t\t\t// Handle relative links (starting with /)\n\t\t\telse if (href.startsWith(\"/\")) {\n\t\t\t\t// Get base documentation URL and ensure proper slash handling\n\t\t\t\tconst baseUrl = this.config.links.documentation;\n\t\t\t\tconst normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n\t\t\t\tfinalUrl = `${normalizedBase}${href}`;\n\t\t\t}\n\n\t\t\t// Add click handler for external links\n\t\t\tif (finalUrl) {\n\t\t\t\tlink.addEventListener(\"click\", (event: MouseEvent) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\twindow.open(finalUrl, \"_blank\");\n\t\t\t\t});\n\n\t\t\t\t// Add visual indicator that it's an external link\n\t\t\t\tlink.classList.add(\"external-link\");\n\t\t\t}\n\t\t});\n\t}\n\n\tasync onOpen() {\n\t\tconst { contentEl } = this;\n\t\tcontentEl.empty();\n\n\t\tthis.addCls(contentEl, \"whats-new-modal\");\n\n\t\t// Header section\n\t\tconst header = contentEl.createDiv({ cls: this.cls(\"whats-new-header\") });\n\t\theader.createEl(\"h2\", {\n\t\t\ttext: `${this.config.pluginName} updated to v${this.toVersion}`,\n\t\t});\n\n\t\theader.createEl(\"p\", {\n\t\t\ttext: `Changes since v${this.fromVersion}`,\n\t\t\tcls: this.cls(\"whats-new-subtitle\"),\n\t\t});\n\n\t\t// Support section\n\t\tconst supportSection = contentEl.createDiv({\n\t\t\tcls: this.cls(\"whats-new-support\"),\n\t\t});\n\n\t\tsupportSection.createEl(\"h3\", { text: \"Support My Work\" });\n\n\t\tconst supportText = supportSection.createEl(\"p\");\n\t\tsupportText.createSpan({ text: \"If you enjoy using this plugin, please consider \" });\n\t\tsupportText.createEl(\"a\", {\n\t\t\ttext: \"supporting my work\",\n\t\t\thref: this.config.links.support,\n\t\t});\n\t\tsupportText.createSpan({\n\t\t\ttext: \". Your support helps keep this plugin maintained and improved!\",\n\t\t});\n\n\t\tcontentEl.createEl(\"hr\");\n\n\t\t// Changelog content\n\t\tconst changelogSections = getChangelogSince(\n\t\t\tthis.config.changelogContent,\n\t\t\tthis.fromVersion,\n\t\t\tthis.toVersion\n\t\t);\n\n\t\tif (changelogSections.length === 0) {\n\t\t\tcontentEl.createEl(\"p\", {\n\t\t\t\ttext: \"No significant changes found in this update.\",\n\t\t\t\tcls: this.cls(\"whats-new-empty\"),\n\t\t\t});\n\t\t} else {\n\t\t\tconst changelogContainer = contentEl.createDiv({\n\t\t\t\tcls: this.cls(\"whats-new-content\"),\n\t\t\t});\n\n\t\t\tconst markdownContent = formatChangelogSections(changelogSections);\n\n\t\t\tawait MarkdownRenderer.render(\n\t\t\t\tthis.app,\n\t\t\t\tmarkdownContent,\n\t\t\t\tchangelogContainer,\n\t\t\t\t\"/\",\n\t\t\t\tthis.plugin\n\t\t\t);\n\n\t\t\t// Make external links clickable\n\t\t\tthis.makeExternalLinksClickable(changelogContainer);\n\t\t}\n\n\t\t// Action buttons\n\t\tconst buttonContainer = contentEl.createDiv({\n\t\t\tcls: this.cls(\"whats-new-buttons\"),\n\t\t});\n\n\t\t// Full changelog button\n\t\tconst changelogBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Full Changelog\",\n\t\t});\n\t\tchangelogBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.changelog, \"_blank\");\n\t\t});\n\n\t\t// Documentation button\n\t\tconst docsBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Documentation\",\n\t\t});\n\t\tdocsBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.documentation, \"_blank\");\n\t\t});\n\n\t\t// Close button (always present)\n\t\tconst closeBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Close\",\n\t\t\tcls: this.cls(\"mod-cta\"),\n\t\t});\n\t\tcloseBtn.addEventListener(\"click\", () => this.close());\n\t}\n\n\tonClose() {\n\t\tthis.contentEl.empty();\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -27,17 +27,18 @@ export interface WhatsNewModalConfig {
|
|
|
27
27
|
/**
|
|
28
28
|
* URL to support/donate page.
|
|
29
29
|
*/
|
|
30
|
-
support
|
|
30
|
+
support: string;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* URL to full changelog page.
|
|
34
34
|
*/
|
|
35
|
-
changelog
|
|
35
|
+
changelog: string;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* URL to
|
|
38
|
+
* Base URL for documentation (used to resolve relative links in changelog).
|
|
39
|
+
* Example: "https://docs.example.com" or "https://docs.example.com/"
|
|
39
40
|
*/
|
|
40
|
-
documentation
|
|
41
|
+
documentation: string;
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -72,8 +73,8 @@ export class WhatsNewModal extends Modal {
|
|
|
72
73
|
|
|
73
74
|
/**
|
|
74
75
|
* Makes external links in rendered markdown clickable by adding click handlers.
|
|
75
|
-
*
|
|
76
|
-
*
|
|
76
|
+
* Handles both absolute URLs (http/https) and relative URLs (starting with /).
|
|
77
|
+
* Relative URLs are resolved against the documentation base URL.
|
|
77
78
|
*/
|
|
78
79
|
private makeExternalLinksClickable(container: HTMLElement): void {
|
|
79
80
|
const links = container.querySelectorAll<HTMLAnchorElement>("a[href]");
|
|
@@ -81,16 +82,31 @@ export class WhatsNewModal extends Modal {
|
|
|
81
82
|
// Convert NodeList to Array for iteration
|
|
82
83
|
Array.from(links).forEach((link) => {
|
|
83
84
|
const href = link.getAttribute("href");
|
|
85
|
+
if (!href) return;
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
let finalUrl: string | null = null;
|
|
88
|
+
|
|
89
|
+
// Handle absolute HTTP(S) links
|
|
90
|
+
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
91
|
+
finalUrl = href;
|
|
92
|
+
}
|
|
93
|
+
// Handle relative links (starting with /)
|
|
94
|
+
else if (href.startsWith("/")) {
|
|
95
|
+
// Get base documentation URL and ensure proper slash handling
|
|
96
|
+
const baseUrl = this.config.links.documentation;
|
|
97
|
+
const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
98
|
+
finalUrl = `${normalizedBase}${href}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Add click handler for external links
|
|
102
|
+
if (finalUrl) {
|
|
87
103
|
link.addEventListener("click", (event: MouseEvent) => {
|
|
88
104
|
event.preventDefault();
|
|
89
|
-
window.open(
|
|
105
|
+
window.open(finalUrl, "_blank");
|
|
90
106
|
});
|
|
91
107
|
|
|
92
108
|
// Add visual indicator that it's an external link
|
|
93
|
-
link.
|
|
109
|
+
link.classList.add("external-link");
|
|
94
110
|
}
|
|
95
111
|
});
|
|
96
112
|
}
|
|
@@ -112,26 +128,24 @@ export class WhatsNewModal extends Modal {
|
|
|
112
128
|
cls: this.cls("whats-new-subtitle"),
|
|
113
129
|
});
|
|
114
130
|
|
|
115
|
-
// Support section
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
});
|
|
131
|
+
// Support section
|
|
132
|
+
const supportSection = contentEl.createDiv({
|
|
133
|
+
cls: this.cls("whats-new-support"),
|
|
134
|
+
});
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
supportSection.createEl("h3", { text: "Support My Work" });
|
|
122
137
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
const supportText = supportSection.createEl("p");
|
|
139
|
+
supportText.createSpan({ text: "If you enjoy using this plugin, please consider " });
|
|
140
|
+
supportText.createEl("a", {
|
|
141
|
+
text: "supporting my work",
|
|
142
|
+
href: this.config.links.support,
|
|
143
|
+
});
|
|
144
|
+
supportText.createSpan({
|
|
145
|
+
text: ". Your support helps keep this plugin maintained and improved!",
|
|
146
|
+
});
|
|
132
147
|
|
|
133
|
-
|
|
134
|
-
}
|
|
148
|
+
contentEl.createEl("hr");
|
|
135
149
|
|
|
136
150
|
// Changelog content
|
|
137
151
|
const changelogSections = getChangelogSince(
|
|
@@ -169,25 +183,21 @@ export class WhatsNewModal extends Modal {
|
|
|
169
183
|
cls: this.cls("whats-new-buttons"),
|
|
170
184
|
});
|
|
171
185
|
|
|
172
|
-
// Full changelog button
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
});
|
|
180
|
-
}
|
|
186
|
+
// Full changelog button
|
|
187
|
+
const changelogBtn = buttonContainer.createEl("button", {
|
|
188
|
+
text: "Full Changelog",
|
|
189
|
+
});
|
|
190
|
+
changelogBtn.addEventListener("click", () => {
|
|
191
|
+
window.open(this.config.links.changelog, "_blank");
|
|
192
|
+
});
|
|
181
193
|
|
|
182
|
-
// Documentation button
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
});
|
|
190
|
-
}
|
|
194
|
+
// Documentation button
|
|
195
|
+
const docsBtn = buttonContainer.createEl("button", {
|
|
196
|
+
text: "Documentation",
|
|
197
|
+
});
|
|
198
|
+
docsBtn.addEventListener("click", () => {
|
|
199
|
+
window.open(this.config.links.documentation, "_blank");
|
|
200
|
+
});
|
|
191
201
|
|
|
192
202
|
// Close button (always present)
|
|
193
203
|
const closeBtn = buttonContainer.createEl("button", {
|