@real1ty-obsidian-plugins/utils 2.31.0 → 2.32.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.
@@ -62,6 +62,232 @@ export interface WhatsNewModalConfig {
62
62
  /**
63
63
  * Generic "What's New" modal that displays changelog entries between versions.
64
64
  * Supports custom CSS prefixes, plugin names, and configurable links.
65
+ *
66
+ * ## CSS Classes
67
+ *
68
+ * This modal uses the following CSS classes (with your custom prefix).
69
+ * Replace `{prefix}` with your `cssPrefix` value (e.g., "my-plugin").
70
+ *
71
+ * ### Main Container
72
+ * - `.{prefix}-whats-new-modal` - Applied to the main content element
73
+ * - `.{prefix}-whats-new-modal .modal` - Modal dialog styling (max-width, width)
74
+ *
75
+ * ### Header Section
76
+ * - `.{prefix}-whats-new-header` - Container for the header section
77
+ * - Contains h2 (title) and subtitle paragraph
78
+ * - `.{prefix}-whats-new-header h2` - Main title styling
79
+ * - `.{prefix}-whats-new-subtitle` - Subtitle text ("Changes since vX.X.X")
80
+ *
81
+ * ### Support Section
82
+ * - `.{prefix}-whats-new-support` - Support section container
83
+ * - Contains donation, tools, and YouTube links
84
+ * - Should have background, padding, border-radius
85
+ * - `.{prefix}-whats-new-support h3` - Support section heading
86
+ * - `.{prefix}-whats-new-support p` - Support section paragraph text (one per row)
87
+ * - `.{prefix}-whats-new-support a` - Links in support section (consistent styling)
88
+ * - `.{prefix}-whats-new-support a:hover` - Link hover state
89
+ *
90
+ * ### Changelog Content
91
+ * - `.{prefix}-whats-new-content` - Changelog content container
92
+ * - Should have max-height, overflow-y: auto for scrolling
93
+ * - `.{prefix}-whats-new-content h2` - Version headings in changelog
94
+ * - `.{prefix}-whats-new-content h3` - Section headings in changelog
95
+ * - `.{prefix}-whats-new-content ul` - Changelog lists
96
+ * - `.{prefix}-whats-new-content li` - Changelog list items
97
+ * - `.{prefix}-whats-new-content code` - Inline code in changelog
98
+ * - `.{prefix}-whats-new-content pre` - Code blocks in changelog
99
+ * - `.{prefix}-whats-new-content a.external-link` - External links (auto-added)
100
+ * - `.{prefix}-whats-new-empty` - Empty state message
101
+ *
102
+ * ### Sticky Footer
103
+ * - `.{prefix}-whats-new-sticky-footer` - Footer container (should be sticky)
104
+ * - `.{prefix}-whats-new-modal hr` - Separator line in footer
105
+ * - `.{prefix}-whats-new-separator` - Separator with custom class
106
+ * - `.{prefix}-whats-new-buttons` - Button container
107
+ * - `.{prefix}-whats-new-buttons button` - Individual buttons
108
+ * - `.{prefix}-mod-cta` - Primary/CTA button state (applied to Close button)
109
+ *
110
+ * ## Example CSS Implementation
111
+ *
112
+ * ```css
113
+ * // Main Container
114
+ * .my-plugin-whats-new-modal .modal {
115
+ * max-width: 800px;
116
+ * width: 90%;
117
+ * }
118
+ *
119
+ * // Header
120
+ * .my-plugin-whats-new-header {
121
+ * margin-bottom: 1.5rem;
122
+ * }
123
+ *
124
+ * .my-plugin-whats-new-header h2 {
125
+ * margin-bottom: 0.5rem;
126
+ * color: var(--text-normal);
127
+ * }
128
+ *
129
+ * .my-plugin-whats-new-subtitle {
130
+ * color: var(--text-muted);
131
+ * font-size: 0.9rem;
132
+ * margin: 0;
133
+ * }
134
+ *
135
+ * // Support Section (with donation, tools, and YouTube links)
136
+ * .my-plugin-whats-new-support {
137
+ * margin: 1.5rem 0;
138
+ * padding: 1rem;
139
+ * background-color: var(--background-secondary);
140
+ * border-radius: 8px;
141
+ * }
142
+ *
143
+ * .my-plugin-whats-new-support h3 {
144
+ * margin-top: 0;
145
+ * margin-bottom: 0.5rem;
146
+ * font-size: 1rem;
147
+ * }
148
+ *
149
+ * .my-plugin-whats-new-support p {
150
+ * margin: 0.5rem 0;
151
+ * color: var(--text-normal);
152
+ * }
153
+ *
154
+ * .my-plugin-whats-new-support a {
155
+ * color: var(--link-color);
156
+ * text-decoration: none;
157
+ * }
158
+ *
159
+ * .my-plugin-whats-new-support a:hover {
160
+ * text-decoration: underline;
161
+ * }
162
+ *
163
+ * // Changelog Content (Scrollable Area)
164
+ * .my-plugin-whats-new-content {
165
+ * max-height: 500px;
166
+ * overflow-y: auto;
167
+ * margin-bottom: 1.5rem;
168
+ * padding-right: 0.5rem;
169
+ * border-radius: 8px;
170
+ * }
171
+ *
172
+ * .my-plugin-whats-new-content h2 {
173
+ * font-size: 1.3rem;
174
+ * margin-top: 1.5rem;
175
+ * margin-bottom: 0.5rem;
176
+ * color: var(--text-accent);
177
+ * }
178
+ *
179
+ * .my-plugin-whats-new-content h3 {
180
+ * font-size: 1.1rem;
181
+ * margin-top: 1rem;
182
+ * margin-bottom: 0.5rem;
183
+ * }
184
+ *
185
+ * .my-plugin-whats-new-content ul {
186
+ * padding-left: 1.5rem;
187
+ * }
188
+ *
189
+ * .my-plugin-whats-new-content li {
190
+ * margin-bottom: 0.5rem;
191
+ * line-height: 1.6;
192
+ * }
193
+ *
194
+ * .my-plugin-whats-new-content code {
195
+ * background: var(--code-background);
196
+ * padding: 0.2em 0.4em;
197
+ * border-radius: 3px;
198
+ * font-size: 0.9em;
199
+ * }
200
+ *
201
+ * .my-plugin-whats-new-content pre {
202
+ * background: var(--code-background);
203
+ * padding: 1rem;
204
+ * border-radius: 6px;
205
+ * overflow-x: auto;
206
+ * }
207
+ *
208
+ * .my-plugin-whats-new-content a.external-link {
209
+ * color: var(--link-external-color);
210
+ * }
211
+ *
212
+ * .my-plugin-whats-new-content a.external-link::after {
213
+ * content: "↗";
214
+ * margin-left: 0.2em;
215
+ * font-size: 0.8em;
216
+ * }
217
+ *
218
+ * .my-plugin-whats-new-empty {
219
+ * text-align: center;
220
+ * color: var(--text-muted);
221
+ * padding: 2rem;
222
+ * font-style: italic;
223
+ * }
224
+ *
225
+ * // Sticky Footer
226
+ * .my-plugin-whats-new-sticky-footer {
227
+ * position: sticky;
228
+ * bottom: 0;
229
+ * background: var(--background-primary);
230
+ * padding-top: 1rem;
231
+ * margin-top: 1rem;
232
+ * z-index: 10;
233
+ * border-top: 1px solid var(--background-modifier-border);
234
+ * }
235
+ *
236
+ * .my-plugin-whats-new-modal hr,
237
+ * .my-plugin-whats-new-separator {
238
+ * margin: 0 0 1rem 0;
239
+ * border: none;
240
+ * border-top: 1px solid var(--background-modifier-border);
241
+ * }
242
+ *
243
+ * .my-plugin-whats-new-buttons {
244
+ * display: flex;
245
+ * gap: 0.5rem;
246
+ * justify-content: flex-end;
247
+ * flex-wrap: wrap;
248
+ * margin-top: 1rem;
249
+ * padding-bottom: 0.5rem;
250
+ * }
251
+ *
252
+ * .my-plugin-whats-new-buttons button {
253
+ * padding: 0.5rem 1rem;
254
+ * border-radius: 4px;
255
+ * cursor: pointer;
256
+ * border: 1px solid var(--background-modifier-border);
257
+ * background: var(--interactive-normal);
258
+ * color: var(--text-normal);
259
+ * transition: background-color 0.2s;
260
+ * }
261
+ *
262
+ * .my-plugin-whats-new-buttons button:hover {
263
+ * background: var(--interactive-hover);
264
+ * }
265
+ *
266
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta {
267
+ * background: var(--interactive-accent);
268
+ * color: var(--text-on-accent);
269
+ * border-color: var(--interactive-accent);
270
+ * }
271
+ *
272
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta:hover {
273
+ * background: var(--interactive-accent-hover);
274
+ * }
275
+ * ```
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * const modal = new WhatsNewModal(app, plugin, {
280
+ * cssPrefix: "my-plugin",
281
+ * pluginName: "My Plugin",
282
+ * changelogContent: rawChangelog,
283
+ * links: {
284
+ * support: "https://...",
285
+ * changelog: "https://...",
286
+ * documentation: "https://..."
287
+ * }
288
+ * }, "1.0.0", "2.0.0");
289
+ * modal.open();
290
+ * ```
65
291
  */
66
292
  export declare class WhatsNewModal extends Modal {
67
293
  private plugin;
@@ -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;;;GAGG;AACH,eAAO,MAAM,uBAAuB;IACnC;;OAEG;;IAGH;;;OAGG;;CAEM,CAAC;AAEX,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;QAEtB;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QAEf;;;WAGG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,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;IA6IZ,OAAO;CAGP"}
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;;;GAGG;AACH,eAAO,MAAM,uBAAuB;IACnC;;OAEG;;IAGH;;;OAGG;;CAEM,CAAC;AAEX,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;QAEtB;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QAEf;;;WAGG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqOG;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;IAiJZ,OAAO;CAGP"}
@@ -19,6 +19,232 @@ export const DEFAULT_WHATS_NEW_LINKS = {
19
19
  /**
20
20
  * Generic "What's New" modal that displays changelog entries between versions.
21
21
  * Supports custom CSS prefixes, plugin names, and configurable links.
22
+ *
23
+ * ## CSS Classes
24
+ *
25
+ * This modal uses the following CSS classes (with your custom prefix).
26
+ * Replace `{prefix}` with your `cssPrefix` value (e.g., "my-plugin").
27
+ *
28
+ * ### Main Container
29
+ * - `.{prefix}-whats-new-modal` - Applied to the main content element
30
+ * - `.{prefix}-whats-new-modal .modal` - Modal dialog styling (max-width, width)
31
+ *
32
+ * ### Header Section
33
+ * - `.{prefix}-whats-new-header` - Container for the header section
34
+ * - Contains h2 (title) and subtitle paragraph
35
+ * - `.{prefix}-whats-new-header h2` - Main title styling
36
+ * - `.{prefix}-whats-new-subtitle` - Subtitle text ("Changes since vX.X.X")
37
+ *
38
+ * ### Support Section
39
+ * - `.{prefix}-whats-new-support` - Support section container
40
+ * - Contains donation, tools, and YouTube links
41
+ * - Should have background, padding, border-radius
42
+ * - `.{prefix}-whats-new-support h3` - Support section heading
43
+ * - `.{prefix}-whats-new-support p` - Support section paragraph text (one per row)
44
+ * - `.{prefix}-whats-new-support a` - Links in support section (consistent styling)
45
+ * - `.{prefix}-whats-new-support a:hover` - Link hover state
46
+ *
47
+ * ### Changelog Content
48
+ * - `.{prefix}-whats-new-content` - Changelog content container
49
+ * - Should have max-height, overflow-y: auto for scrolling
50
+ * - `.{prefix}-whats-new-content h2` - Version headings in changelog
51
+ * - `.{prefix}-whats-new-content h3` - Section headings in changelog
52
+ * - `.{prefix}-whats-new-content ul` - Changelog lists
53
+ * - `.{prefix}-whats-new-content li` - Changelog list items
54
+ * - `.{prefix}-whats-new-content code` - Inline code in changelog
55
+ * - `.{prefix}-whats-new-content pre` - Code blocks in changelog
56
+ * - `.{prefix}-whats-new-content a.external-link` - External links (auto-added)
57
+ * - `.{prefix}-whats-new-empty` - Empty state message
58
+ *
59
+ * ### Sticky Footer
60
+ * - `.{prefix}-whats-new-sticky-footer` - Footer container (should be sticky)
61
+ * - `.{prefix}-whats-new-modal hr` - Separator line in footer
62
+ * - `.{prefix}-whats-new-separator` - Separator with custom class
63
+ * - `.{prefix}-whats-new-buttons` - Button container
64
+ * - `.{prefix}-whats-new-buttons button` - Individual buttons
65
+ * - `.{prefix}-mod-cta` - Primary/CTA button state (applied to Close button)
66
+ *
67
+ * ## Example CSS Implementation
68
+ *
69
+ * ```css
70
+ * // Main Container
71
+ * .my-plugin-whats-new-modal .modal {
72
+ * max-width: 800px;
73
+ * width: 90%;
74
+ * }
75
+ *
76
+ * // Header
77
+ * .my-plugin-whats-new-header {
78
+ * margin-bottom: 1.5rem;
79
+ * }
80
+ *
81
+ * .my-plugin-whats-new-header h2 {
82
+ * margin-bottom: 0.5rem;
83
+ * color: var(--text-normal);
84
+ * }
85
+ *
86
+ * .my-plugin-whats-new-subtitle {
87
+ * color: var(--text-muted);
88
+ * font-size: 0.9rem;
89
+ * margin: 0;
90
+ * }
91
+ *
92
+ * // Support Section (with donation, tools, and YouTube links)
93
+ * .my-plugin-whats-new-support {
94
+ * margin: 1.5rem 0;
95
+ * padding: 1rem;
96
+ * background-color: var(--background-secondary);
97
+ * border-radius: 8px;
98
+ * }
99
+ *
100
+ * .my-plugin-whats-new-support h3 {
101
+ * margin-top: 0;
102
+ * margin-bottom: 0.5rem;
103
+ * font-size: 1rem;
104
+ * }
105
+ *
106
+ * .my-plugin-whats-new-support p {
107
+ * margin: 0.5rem 0;
108
+ * color: var(--text-normal);
109
+ * }
110
+ *
111
+ * .my-plugin-whats-new-support a {
112
+ * color: var(--link-color);
113
+ * text-decoration: none;
114
+ * }
115
+ *
116
+ * .my-plugin-whats-new-support a:hover {
117
+ * text-decoration: underline;
118
+ * }
119
+ *
120
+ * // Changelog Content (Scrollable Area)
121
+ * .my-plugin-whats-new-content {
122
+ * max-height: 500px;
123
+ * overflow-y: auto;
124
+ * margin-bottom: 1.5rem;
125
+ * padding-right: 0.5rem;
126
+ * border-radius: 8px;
127
+ * }
128
+ *
129
+ * .my-plugin-whats-new-content h2 {
130
+ * font-size: 1.3rem;
131
+ * margin-top: 1.5rem;
132
+ * margin-bottom: 0.5rem;
133
+ * color: var(--text-accent);
134
+ * }
135
+ *
136
+ * .my-plugin-whats-new-content h3 {
137
+ * font-size: 1.1rem;
138
+ * margin-top: 1rem;
139
+ * margin-bottom: 0.5rem;
140
+ * }
141
+ *
142
+ * .my-plugin-whats-new-content ul {
143
+ * padding-left: 1.5rem;
144
+ * }
145
+ *
146
+ * .my-plugin-whats-new-content li {
147
+ * margin-bottom: 0.5rem;
148
+ * line-height: 1.6;
149
+ * }
150
+ *
151
+ * .my-plugin-whats-new-content code {
152
+ * background: var(--code-background);
153
+ * padding: 0.2em 0.4em;
154
+ * border-radius: 3px;
155
+ * font-size: 0.9em;
156
+ * }
157
+ *
158
+ * .my-plugin-whats-new-content pre {
159
+ * background: var(--code-background);
160
+ * padding: 1rem;
161
+ * border-radius: 6px;
162
+ * overflow-x: auto;
163
+ * }
164
+ *
165
+ * .my-plugin-whats-new-content a.external-link {
166
+ * color: var(--link-external-color);
167
+ * }
168
+ *
169
+ * .my-plugin-whats-new-content a.external-link::after {
170
+ * content: "↗";
171
+ * margin-left: 0.2em;
172
+ * font-size: 0.8em;
173
+ * }
174
+ *
175
+ * .my-plugin-whats-new-empty {
176
+ * text-align: center;
177
+ * color: var(--text-muted);
178
+ * padding: 2rem;
179
+ * font-style: italic;
180
+ * }
181
+ *
182
+ * // Sticky Footer
183
+ * .my-plugin-whats-new-sticky-footer {
184
+ * position: sticky;
185
+ * bottom: 0;
186
+ * background: var(--background-primary);
187
+ * padding-top: 1rem;
188
+ * margin-top: 1rem;
189
+ * z-index: 10;
190
+ * border-top: 1px solid var(--background-modifier-border);
191
+ * }
192
+ *
193
+ * .my-plugin-whats-new-modal hr,
194
+ * .my-plugin-whats-new-separator {
195
+ * margin: 0 0 1rem 0;
196
+ * border: none;
197
+ * border-top: 1px solid var(--background-modifier-border);
198
+ * }
199
+ *
200
+ * .my-plugin-whats-new-buttons {
201
+ * display: flex;
202
+ * gap: 0.5rem;
203
+ * justify-content: flex-end;
204
+ * flex-wrap: wrap;
205
+ * margin-top: 1rem;
206
+ * padding-bottom: 0.5rem;
207
+ * }
208
+ *
209
+ * .my-plugin-whats-new-buttons button {
210
+ * padding: 0.5rem 1rem;
211
+ * border-radius: 4px;
212
+ * cursor: pointer;
213
+ * border: 1px solid var(--background-modifier-border);
214
+ * background: var(--interactive-normal);
215
+ * color: var(--text-normal);
216
+ * transition: background-color 0.2s;
217
+ * }
218
+ *
219
+ * .my-plugin-whats-new-buttons button:hover {
220
+ * background: var(--interactive-hover);
221
+ * }
222
+ *
223
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta {
224
+ * background: var(--interactive-accent);
225
+ * color: var(--text-on-accent);
226
+ * border-color: var(--interactive-accent);
227
+ * }
228
+ *
229
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta:hover {
230
+ * background: var(--interactive-accent-hover);
231
+ * }
232
+ * ```
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * const modal = new WhatsNewModal(app, plugin, {
237
+ * cssPrefix: "my-plugin",
238
+ * pluginName: "My Plugin",
239
+ * changelogContent: rawChangelog,
240
+ * links: {
241
+ * support: "https://...",
242
+ * changelog: "https://...",
243
+ * documentation: "https://..."
244
+ * }
245
+ * }, "1.0.0", "2.0.0");
246
+ * modal.open();
247
+ * ```
22
248
  */
23
249
  export class WhatsNewModal extends Modal {
24
250
  constructor(app, plugin, config, fromVersion, toVersion) {
@@ -95,6 +321,7 @@ export class WhatsNewModal extends Modal {
95
321
  cls: this.cls("whats-new-support"),
96
322
  });
97
323
  supportSection.createEl("h3", { text: "Support My Work" });
324
+ // Support/donate
98
325
  const supportText = supportSection.createEl("p");
99
326
  supportText.createSpan({ text: "If you enjoy using this plugin, please consider " });
100
327
  supportText.createEl("a", {
@@ -104,14 +331,9 @@ export class WhatsNewModal extends Modal {
104
331
  supportText.createSpan({
105
332
  text: ". Your support helps keep this plugin maintained and improved!",
106
333
  });
107
- // Discover more section
108
- const discoverSection = contentEl.createDiv({
109
- cls: this.cls("whats-new-discover"),
110
- });
111
- discoverSection.createEl("h3", { text: "Discover More" });
112
334
  // Other tools
113
- const toolsText = discoverSection.createEl("p");
114
- toolsText.createSpan({ text: "🔧 Check out my " });
335
+ const toolsText = supportSection.createEl("p");
336
+ toolsText.createSpan({ text: "Check out my " });
115
337
  toolsText.createEl("a", {
116
338
  text: "other plugins and productivity tools",
117
339
  href: (_a = this.config.links.tools) !== null && _a !== void 0 ? _a : DEFAULT_WHATS_NEW_LINKS.TOOLS,
@@ -120,8 +342,8 @@ export class WhatsNewModal extends Modal {
120
342
  text: " to enhance your workflow even further.",
121
343
  });
122
344
  // YouTube channel
123
- const youtubeText = discoverSection.createEl("p");
124
- youtubeText.createSpan({ text: "📺 Subscribe to my " });
345
+ const youtubeText = supportSection.createEl("p");
346
+ youtubeText.createSpan({ text: "Subscribe to my " });
125
347
  youtubeText.createEl("a", {
126
348
  text: "YouTube channel",
127
349
  href: (_b = this.config.links.youtube) !== null && _b !== void 0 ? _b : DEFAULT_WHATS_NEW_LINKS.YOUTUBE,
@@ -147,13 +369,21 @@ export class WhatsNewModal extends Modal {
147
369
  // Make external links clickable
148
370
  this.makeExternalLinksClickable(changelogContainer);
149
371
  }
372
+ // Sticky footer section (hr + buttons)
373
+ const stickyFooter = contentEl.createDiv({
374
+ cls: this.cls("whats-new-sticky-footer"),
375
+ });
376
+ // Separator line
377
+ stickyFooter.createEl("hr", {
378
+ cls: this.cls("whats-new-separator"),
379
+ });
150
380
  // Action buttons
151
- const buttonContainer = contentEl.createDiv({
381
+ const buttonContainer = stickyFooter.createDiv({
152
382
  cls: this.cls("whats-new-buttons"),
153
383
  });
154
384
  // Full changelog button
155
385
  const changelogBtn = buttonContainer.createEl("button", {
156
- text: "Full Changelog",
386
+ text: "Changelog",
157
387
  });
158
388
  changelogBtn.addEventListener("click", () => {
159
389
  window.open(this.config.links.changelog, "_blank");
@@ -167,7 +397,7 @@ export class WhatsNewModal extends Modal {
167
397
  });
168
398
  // Tools button
169
399
  const toolsBtn = buttonContainer.createEl("button", {
170
- text: "My Tools",
400
+ text: "Other Plugins",
171
401
  });
172
402
  toolsBtn.addEventListener("click", () => {
173
403
  var _a;
@@ -175,7 +405,7 @@ export class WhatsNewModal extends Modal {
175
405
  });
176
406
  // YouTube button
177
407
  const youtubeBtn = buttonContainer.createEl("button", {
178
- text: "YouTube Channel",
408
+ text: "YouTube",
179
409
  });
180
410
  youtubeBtn.addEventListener("click", () => {
181
411
  var _a;
@@ -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\n/**\n * Default URLs for the What's New modal.\n * These can be overridden in the config.\n */\nexport const DEFAULT_WHATS_NEW_LINKS = {\n\t/**\n\t * Default tools page showcasing all plugins and productivity software.\n\t */\n\tTOOLS: \"https://matejvavroproductivity.com/tools/\",\n\n\t/**\n\t * Default YouTube channel with Obsidian tutorials and productivity tips.\n\t * Includes subscription confirmation parameter.\n\t */\n\tYOUTUBE: \"https://www.youtube.com/@MatejVavroProductivity?sub_confirmation=1\",\n} as const;\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\n\t\t/**\n\t\t * URL to tools page showcasing all plugins and productivity tools.\n\t\t * Defaults to DEFAULT_WHATS_NEW_LINKS.TOOLS if not provided.\n\t\t */\n\t\ttools?: string;\n\n\t\t/**\n\t\t * URL to YouTube channel with tutorials and productivity tips.\n\t\t * Defaults to DEFAULT_WHATS_NEW_LINKS.YOUTUBE if not provided.\n\t\t */\n\t\tyoutube?: 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\t// Discover more section\n\t\tconst discoverSection = contentEl.createDiv({\n\t\t\tcls: this.cls(\"whats-new-discover\"),\n\t\t});\n\n\t\tdiscoverSection.createEl(\"h3\", { text: \"Discover More\" });\n\n\t\t// Other tools\n\t\tconst toolsText = discoverSection.createEl(\"p\");\n\t\ttoolsText.createSpan({ text: \"🔧 Check out my \" });\n\t\ttoolsText.createEl(\"a\", {\n\t\t\ttext: \"other plugins and productivity tools\",\n\t\t\thref: this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS,\n\t\t});\n\t\ttoolsText.createSpan({\n\t\t\ttext: \" to enhance your workflow even further.\",\n\t\t});\n\n\t\t// YouTube channel\n\t\tconst youtubeText = discoverSection.createEl(\"p\");\n\t\tyoutubeText.createSpan({ text: \"📺 Subscribe to my \" });\n\t\tyoutubeText.createEl(\"a\", {\n\t\t\ttext: \"YouTube channel\",\n\t\t\thref: this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE,\n\t\t});\n\t\tyoutubeText.createSpan({\n\t\t\ttext: \" for Obsidian tutorials and productivity tips!\",\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// Tools button\n\t\tconst toolsBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"My Tools\",\n\t\t});\n\t\ttoolsBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS, \"_blank\");\n\t\t});\n\n\t\t// YouTube button\n\t\tconst youtubeBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"YouTube Channel\",\n\t\t});\n\t\tyoutubeBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE, \"_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"]}
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\n/**\n * Default URLs for the What's New modal.\n * These can be overridden in the config.\n */\nexport const DEFAULT_WHATS_NEW_LINKS = {\n\t/**\n\t * Default tools page showcasing all plugins and productivity software.\n\t */\n\tTOOLS: \"https://matejvavroproductivity.com/tools/\",\n\n\t/**\n\t * Default YouTube channel with Obsidian tutorials and productivity tips.\n\t * Includes subscription confirmation parameter.\n\t */\n\tYOUTUBE: \"https://www.youtube.com/@MatejVavroProductivity?sub_confirmation=1\",\n} as const;\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\n\t\t/**\n\t\t * URL to tools page showcasing all plugins and productivity tools.\n\t\t * Defaults to DEFAULT_WHATS_NEW_LINKS.TOOLS if not provided.\n\t\t */\n\t\ttools?: string;\n\n\t\t/**\n\t\t * URL to YouTube channel with tutorials and productivity tips.\n\t\t * Defaults to DEFAULT_WHATS_NEW_LINKS.YOUTUBE if not provided.\n\t\t */\n\t\tyoutube?: 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 *\n * ## CSS Classes\n *\n * This modal uses the following CSS classes (with your custom prefix).\n * Replace `{prefix}` with your `cssPrefix` value (e.g., \"my-plugin\").\n *\n * ### Main Container\n * - `.{prefix}-whats-new-modal` - Applied to the main content element\n * - `.{prefix}-whats-new-modal .modal` - Modal dialog styling (max-width, width)\n *\n * ### Header Section\n * - `.{prefix}-whats-new-header` - Container for the header section\n * - Contains h2 (title) and subtitle paragraph\n * - `.{prefix}-whats-new-header h2` - Main title styling\n * - `.{prefix}-whats-new-subtitle` - Subtitle text (\"Changes since vX.X.X\")\n *\n * ### Support Section\n * - `.{prefix}-whats-new-support` - Support section container\n * - Contains donation, tools, and YouTube links\n * - Should have background, padding, border-radius\n * - `.{prefix}-whats-new-support h3` - Support section heading\n * - `.{prefix}-whats-new-support p` - Support section paragraph text (one per row)\n * - `.{prefix}-whats-new-support a` - Links in support section (consistent styling)\n * - `.{prefix}-whats-new-support a:hover` - Link hover state\n *\n * ### Changelog Content\n * - `.{prefix}-whats-new-content` - Changelog content container\n * - Should have max-height, overflow-y: auto for scrolling\n * - `.{prefix}-whats-new-content h2` - Version headings in changelog\n * - `.{prefix}-whats-new-content h3` - Section headings in changelog\n * - `.{prefix}-whats-new-content ul` - Changelog lists\n * - `.{prefix}-whats-new-content li` - Changelog list items\n * - `.{prefix}-whats-new-content code` - Inline code in changelog\n * - `.{prefix}-whats-new-content pre` - Code blocks in changelog\n * - `.{prefix}-whats-new-content a.external-link` - External links (auto-added)\n * - `.{prefix}-whats-new-empty` - Empty state message\n *\n * ### Sticky Footer\n * - `.{prefix}-whats-new-sticky-footer` - Footer container (should be sticky)\n * - `.{prefix}-whats-new-modal hr` - Separator line in footer\n * - `.{prefix}-whats-new-separator` - Separator with custom class\n * - `.{prefix}-whats-new-buttons` - Button container\n * - `.{prefix}-whats-new-buttons button` - Individual buttons\n * - `.{prefix}-mod-cta` - Primary/CTA button state (applied to Close button)\n *\n * ## Example CSS Implementation\n *\n * ```css\n * // Main Container\n * .my-plugin-whats-new-modal .modal {\n * max-width: 800px;\n * width: 90%;\n * }\n *\n * // Header\n * .my-plugin-whats-new-header {\n * margin-bottom: 1.5rem;\n * }\n *\n * .my-plugin-whats-new-header h2 {\n * margin-bottom: 0.5rem;\n * color: var(--text-normal);\n * }\n *\n * .my-plugin-whats-new-subtitle {\n * color: var(--text-muted);\n * font-size: 0.9rem;\n * margin: 0;\n * }\n *\n * // Support Section (with donation, tools, and YouTube links)\n * .my-plugin-whats-new-support {\n * margin: 1.5rem 0;\n * padding: 1rem;\n * background-color: var(--background-secondary);\n * border-radius: 8px;\n * }\n *\n * .my-plugin-whats-new-support h3 {\n * margin-top: 0;\n * margin-bottom: 0.5rem;\n * font-size: 1rem;\n * }\n *\n * .my-plugin-whats-new-support p {\n * margin: 0.5rem 0;\n * color: var(--text-normal);\n * }\n *\n * .my-plugin-whats-new-support a {\n * color: var(--link-color);\n * text-decoration: none;\n * }\n *\n * .my-plugin-whats-new-support a:hover {\n * text-decoration: underline;\n * }\n *\n * // Changelog Content (Scrollable Area)\n * .my-plugin-whats-new-content {\n * max-height: 500px;\n * overflow-y: auto;\n * margin-bottom: 1.5rem;\n * padding-right: 0.5rem;\n * border-radius: 8px;\n * }\n *\n * .my-plugin-whats-new-content h2 {\n * font-size: 1.3rem;\n * margin-top: 1.5rem;\n * margin-bottom: 0.5rem;\n * color: var(--text-accent);\n * }\n *\n * .my-plugin-whats-new-content h3 {\n * font-size: 1.1rem;\n * margin-top: 1rem;\n * margin-bottom: 0.5rem;\n * }\n *\n * .my-plugin-whats-new-content ul {\n * padding-left: 1.5rem;\n * }\n *\n * .my-plugin-whats-new-content li {\n * margin-bottom: 0.5rem;\n * line-height: 1.6;\n * }\n *\n * .my-plugin-whats-new-content code {\n * background: var(--code-background);\n * padding: 0.2em 0.4em;\n * border-radius: 3px;\n * font-size: 0.9em;\n * }\n *\n * .my-plugin-whats-new-content pre {\n * background: var(--code-background);\n * padding: 1rem;\n * border-radius: 6px;\n * overflow-x: auto;\n * }\n *\n * .my-plugin-whats-new-content a.external-link {\n * color: var(--link-external-color);\n * }\n *\n * .my-plugin-whats-new-content a.external-link::after {\n * content: \"↗\";\n * margin-left: 0.2em;\n * font-size: 0.8em;\n * }\n *\n * .my-plugin-whats-new-empty {\n * text-align: center;\n * color: var(--text-muted);\n * padding: 2rem;\n * font-style: italic;\n * }\n *\n * // Sticky Footer\n * .my-plugin-whats-new-sticky-footer {\n * position: sticky;\n * bottom: 0;\n * background: var(--background-primary);\n * padding-top: 1rem;\n * margin-top: 1rem;\n * z-index: 10;\n * border-top: 1px solid var(--background-modifier-border);\n * }\n *\n * .my-plugin-whats-new-modal hr,\n * .my-plugin-whats-new-separator {\n * margin: 0 0 1rem 0;\n * border: none;\n * border-top: 1px solid var(--background-modifier-border);\n * }\n *\n * .my-plugin-whats-new-buttons {\n * display: flex;\n * gap: 0.5rem;\n * justify-content: flex-end;\n * flex-wrap: wrap;\n * margin-top: 1rem;\n * padding-bottom: 0.5rem;\n * }\n *\n * .my-plugin-whats-new-buttons button {\n * padding: 0.5rem 1rem;\n * border-radius: 4px;\n * cursor: pointer;\n * border: 1px solid var(--background-modifier-border);\n * background: var(--interactive-normal);\n * color: var(--text-normal);\n * transition: background-color 0.2s;\n * }\n *\n * .my-plugin-whats-new-buttons button:hover {\n * background: var(--interactive-hover);\n * }\n *\n * .my-plugin-whats-new-buttons button.my-plugin-mod-cta {\n * background: var(--interactive-accent);\n * color: var(--text-on-accent);\n * border-color: var(--interactive-accent);\n * }\n *\n * .my-plugin-whats-new-buttons button.my-plugin-mod-cta:hover {\n * background: var(--interactive-accent-hover);\n * }\n * ```\n *\n * @example\n * ```typescript\n * const modal = new WhatsNewModal(app, plugin, {\n * cssPrefix: \"my-plugin\",\n * pluginName: \"My Plugin\",\n * changelogContent: rawChangelog,\n * links: {\n * support: \"https://...\",\n * changelog: \"https://...\",\n * documentation: \"https://...\"\n * }\n * }, \"1.0.0\", \"2.0.0\");\n * modal.open();\n * ```\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\t// Support/donate\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\t// Other tools\n\t\tconst toolsText = supportSection.createEl(\"p\");\n\t\ttoolsText.createSpan({ text: \"Check out my \" });\n\t\ttoolsText.createEl(\"a\", {\n\t\t\ttext: \"other plugins and productivity tools\",\n\t\t\thref: this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS,\n\t\t});\n\t\ttoolsText.createSpan({\n\t\t\ttext: \" to enhance your workflow even further.\",\n\t\t});\n\n\t\t// YouTube channel\n\t\tconst youtubeText = supportSection.createEl(\"p\");\n\t\tyoutubeText.createSpan({ text: \"Subscribe to my \" });\n\t\tyoutubeText.createEl(\"a\", {\n\t\t\ttext: \"YouTube channel\",\n\t\t\thref: this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE,\n\t\t});\n\t\tyoutubeText.createSpan({\n\t\t\ttext: \" for Obsidian tutorials and productivity tips!\",\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// Sticky footer section (hr + buttons)\n\t\tconst stickyFooter = contentEl.createDiv({\n\t\t\tcls: this.cls(\"whats-new-sticky-footer\"),\n\t\t});\n\n\t\t// Separator line\n\t\tstickyFooter.createEl(\"hr\", {\n\t\t\tcls: this.cls(\"whats-new-separator\"),\n\t\t});\n\n\t\t// Action buttons\n\t\tconst buttonContainer = stickyFooter.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: \"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// Tools button\n\t\tconst toolsBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Other Plugins\",\n\t\t});\n\t\ttoolsBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS, \"_blank\");\n\t\t});\n\n\t\t// YouTube button\n\t\tconst youtubeBtn = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"YouTube\",\n\t\t});\n\t\tyoutubeBtn.addEventListener(\"click\", () => {\n\t\t\twindow.open(this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE, \"_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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real1ty-obsidian-plugins/utils",
3
- "version": "2.31.0",
3
+ "version": "2.32.0",
4
4
  "description": "Shared utilities for Obsidian plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -74,6 +74,232 @@ export interface WhatsNewModalConfig {
74
74
  /**
75
75
  * Generic "What's New" modal that displays changelog entries between versions.
76
76
  * Supports custom CSS prefixes, plugin names, and configurable links.
77
+ *
78
+ * ## CSS Classes
79
+ *
80
+ * This modal uses the following CSS classes (with your custom prefix).
81
+ * Replace `{prefix}` with your `cssPrefix` value (e.g., "my-plugin").
82
+ *
83
+ * ### Main Container
84
+ * - `.{prefix}-whats-new-modal` - Applied to the main content element
85
+ * - `.{prefix}-whats-new-modal .modal` - Modal dialog styling (max-width, width)
86
+ *
87
+ * ### Header Section
88
+ * - `.{prefix}-whats-new-header` - Container for the header section
89
+ * - Contains h2 (title) and subtitle paragraph
90
+ * - `.{prefix}-whats-new-header h2` - Main title styling
91
+ * - `.{prefix}-whats-new-subtitle` - Subtitle text ("Changes since vX.X.X")
92
+ *
93
+ * ### Support Section
94
+ * - `.{prefix}-whats-new-support` - Support section container
95
+ * - Contains donation, tools, and YouTube links
96
+ * - Should have background, padding, border-radius
97
+ * - `.{prefix}-whats-new-support h3` - Support section heading
98
+ * - `.{prefix}-whats-new-support p` - Support section paragraph text (one per row)
99
+ * - `.{prefix}-whats-new-support a` - Links in support section (consistent styling)
100
+ * - `.{prefix}-whats-new-support a:hover` - Link hover state
101
+ *
102
+ * ### Changelog Content
103
+ * - `.{prefix}-whats-new-content` - Changelog content container
104
+ * - Should have max-height, overflow-y: auto for scrolling
105
+ * - `.{prefix}-whats-new-content h2` - Version headings in changelog
106
+ * - `.{prefix}-whats-new-content h3` - Section headings in changelog
107
+ * - `.{prefix}-whats-new-content ul` - Changelog lists
108
+ * - `.{prefix}-whats-new-content li` - Changelog list items
109
+ * - `.{prefix}-whats-new-content code` - Inline code in changelog
110
+ * - `.{prefix}-whats-new-content pre` - Code blocks in changelog
111
+ * - `.{prefix}-whats-new-content a.external-link` - External links (auto-added)
112
+ * - `.{prefix}-whats-new-empty` - Empty state message
113
+ *
114
+ * ### Sticky Footer
115
+ * - `.{prefix}-whats-new-sticky-footer` - Footer container (should be sticky)
116
+ * - `.{prefix}-whats-new-modal hr` - Separator line in footer
117
+ * - `.{prefix}-whats-new-separator` - Separator with custom class
118
+ * - `.{prefix}-whats-new-buttons` - Button container
119
+ * - `.{prefix}-whats-new-buttons button` - Individual buttons
120
+ * - `.{prefix}-mod-cta` - Primary/CTA button state (applied to Close button)
121
+ *
122
+ * ## Example CSS Implementation
123
+ *
124
+ * ```css
125
+ * // Main Container
126
+ * .my-plugin-whats-new-modal .modal {
127
+ * max-width: 800px;
128
+ * width: 90%;
129
+ * }
130
+ *
131
+ * // Header
132
+ * .my-plugin-whats-new-header {
133
+ * margin-bottom: 1.5rem;
134
+ * }
135
+ *
136
+ * .my-plugin-whats-new-header h2 {
137
+ * margin-bottom: 0.5rem;
138
+ * color: var(--text-normal);
139
+ * }
140
+ *
141
+ * .my-plugin-whats-new-subtitle {
142
+ * color: var(--text-muted);
143
+ * font-size: 0.9rem;
144
+ * margin: 0;
145
+ * }
146
+ *
147
+ * // Support Section (with donation, tools, and YouTube links)
148
+ * .my-plugin-whats-new-support {
149
+ * margin: 1.5rem 0;
150
+ * padding: 1rem;
151
+ * background-color: var(--background-secondary);
152
+ * border-radius: 8px;
153
+ * }
154
+ *
155
+ * .my-plugin-whats-new-support h3 {
156
+ * margin-top: 0;
157
+ * margin-bottom: 0.5rem;
158
+ * font-size: 1rem;
159
+ * }
160
+ *
161
+ * .my-plugin-whats-new-support p {
162
+ * margin: 0.5rem 0;
163
+ * color: var(--text-normal);
164
+ * }
165
+ *
166
+ * .my-plugin-whats-new-support a {
167
+ * color: var(--link-color);
168
+ * text-decoration: none;
169
+ * }
170
+ *
171
+ * .my-plugin-whats-new-support a:hover {
172
+ * text-decoration: underline;
173
+ * }
174
+ *
175
+ * // Changelog Content (Scrollable Area)
176
+ * .my-plugin-whats-new-content {
177
+ * max-height: 500px;
178
+ * overflow-y: auto;
179
+ * margin-bottom: 1.5rem;
180
+ * padding-right: 0.5rem;
181
+ * border-radius: 8px;
182
+ * }
183
+ *
184
+ * .my-plugin-whats-new-content h2 {
185
+ * font-size: 1.3rem;
186
+ * margin-top: 1.5rem;
187
+ * margin-bottom: 0.5rem;
188
+ * color: var(--text-accent);
189
+ * }
190
+ *
191
+ * .my-plugin-whats-new-content h3 {
192
+ * font-size: 1.1rem;
193
+ * margin-top: 1rem;
194
+ * margin-bottom: 0.5rem;
195
+ * }
196
+ *
197
+ * .my-plugin-whats-new-content ul {
198
+ * padding-left: 1.5rem;
199
+ * }
200
+ *
201
+ * .my-plugin-whats-new-content li {
202
+ * margin-bottom: 0.5rem;
203
+ * line-height: 1.6;
204
+ * }
205
+ *
206
+ * .my-plugin-whats-new-content code {
207
+ * background: var(--code-background);
208
+ * padding: 0.2em 0.4em;
209
+ * border-radius: 3px;
210
+ * font-size: 0.9em;
211
+ * }
212
+ *
213
+ * .my-plugin-whats-new-content pre {
214
+ * background: var(--code-background);
215
+ * padding: 1rem;
216
+ * border-radius: 6px;
217
+ * overflow-x: auto;
218
+ * }
219
+ *
220
+ * .my-plugin-whats-new-content a.external-link {
221
+ * color: var(--link-external-color);
222
+ * }
223
+ *
224
+ * .my-plugin-whats-new-content a.external-link::after {
225
+ * content: "↗";
226
+ * margin-left: 0.2em;
227
+ * font-size: 0.8em;
228
+ * }
229
+ *
230
+ * .my-plugin-whats-new-empty {
231
+ * text-align: center;
232
+ * color: var(--text-muted);
233
+ * padding: 2rem;
234
+ * font-style: italic;
235
+ * }
236
+ *
237
+ * // Sticky Footer
238
+ * .my-plugin-whats-new-sticky-footer {
239
+ * position: sticky;
240
+ * bottom: 0;
241
+ * background: var(--background-primary);
242
+ * padding-top: 1rem;
243
+ * margin-top: 1rem;
244
+ * z-index: 10;
245
+ * border-top: 1px solid var(--background-modifier-border);
246
+ * }
247
+ *
248
+ * .my-plugin-whats-new-modal hr,
249
+ * .my-plugin-whats-new-separator {
250
+ * margin: 0 0 1rem 0;
251
+ * border: none;
252
+ * border-top: 1px solid var(--background-modifier-border);
253
+ * }
254
+ *
255
+ * .my-plugin-whats-new-buttons {
256
+ * display: flex;
257
+ * gap: 0.5rem;
258
+ * justify-content: flex-end;
259
+ * flex-wrap: wrap;
260
+ * margin-top: 1rem;
261
+ * padding-bottom: 0.5rem;
262
+ * }
263
+ *
264
+ * .my-plugin-whats-new-buttons button {
265
+ * padding: 0.5rem 1rem;
266
+ * border-radius: 4px;
267
+ * cursor: pointer;
268
+ * border: 1px solid var(--background-modifier-border);
269
+ * background: var(--interactive-normal);
270
+ * color: var(--text-normal);
271
+ * transition: background-color 0.2s;
272
+ * }
273
+ *
274
+ * .my-plugin-whats-new-buttons button:hover {
275
+ * background: var(--interactive-hover);
276
+ * }
277
+ *
278
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta {
279
+ * background: var(--interactive-accent);
280
+ * color: var(--text-on-accent);
281
+ * border-color: var(--interactive-accent);
282
+ * }
283
+ *
284
+ * .my-plugin-whats-new-buttons button.my-plugin-mod-cta:hover {
285
+ * background: var(--interactive-accent-hover);
286
+ * }
287
+ * ```
288
+ *
289
+ * @example
290
+ * ```typescript
291
+ * const modal = new WhatsNewModal(app, plugin, {
292
+ * cssPrefix: "my-plugin",
293
+ * pluginName: "My Plugin",
294
+ * changelogContent: rawChangelog,
295
+ * links: {
296
+ * support: "https://...",
297
+ * changelog: "https://...",
298
+ * documentation: "https://..."
299
+ * }
300
+ * }, "1.0.0", "2.0.0");
301
+ * modal.open();
302
+ * ```
77
303
  */
78
304
  export class WhatsNewModal extends Modal {
79
305
  constructor(
@@ -164,6 +390,7 @@ export class WhatsNewModal extends Modal {
164
390
 
165
391
  supportSection.createEl("h3", { text: "Support My Work" });
166
392
 
393
+ // Support/donate
167
394
  const supportText = supportSection.createEl("p");
168
395
  supportText.createSpan({ text: "If you enjoy using this plugin, please consider " });
169
396
  supportText.createEl("a", {
@@ -174,16 +401,9 @@ export class WhatsNewModal extends Modal {
174
401
  text: ". Your support helps keep this plugin maintained and improved!",
175
402
  });
176
403
 
177
- // Discover more section
178
- const discoverSection = contentEl.createDiv({
179
- cls: this.cls("whats-new-discover"),
180
- });
181
-
182
- discoverSection.createEl("h3", { text: "Discover More" });
183
-
184
404
  // Other tools
185
- const toolsText = discoverSection.createEl("p");
186
- toolsText.createSpan({ text: "🔧 Check out my " });
405
+ const toolsText = supportSection.createEl("p");
406
+ toolsText.createSpan({ text: "Check out my " });
187
407
  toolsText.createEl("a", {
188
408
  text: "other plugins and productivity tools",
189
409
  href: this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS,
@@ -193,8 +413,8 @@ export class WhatsNewModal extends Modal {
193
413
  });
194
414
 
195
415
  // YouTube channel
196
- const youtubeText = discoverSection.createEl("p");
197
- youtubeText.createSpan({ text: "📺 Subscribe to my " });
416
+ const youtubeText = supportSection.createEl("p");
417
+ youtubeText.createSpan({ text: "Subscribe to my " });
198
418
  youtubeText.createEl("a", {
199
419
  text: "YouTube channel",
200
420
  href: this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE,
@@ -236,14 +456,24 @@ export class WhatsNewModal extends Modal {
236
456
  this.makeExternalLinksClickable(changelogContainer);
237
457
  }
238
458
 
459
+ // Sticky footer section (hr + buttons)
460
+ const stickyFooter = contentEl.createDiv({
461
+ cls: this.cls("whats-new-sticky-footer"),
462
+ });
463
+
464
+ // Separator line
465
+ stickyFooter.createEl("hr", {
466
+ cls: this.cls("whats-new-separator"),
467
+ });
468
+
239
469
  // Action buttons
240
- const buttonContainer = contentEl.createDiv({
470
+ const buttonContainer = stickyFooter.createDiv({
241
471
  cls: this.cls("whats-new-buttons"),
242
472
  });
243
473
 
244
474
  // Full changelog button
245
475
  const changelogBtn = buttonContainer.createEl("button", {
246
- text: "Full Changelog",
476
+ text: "Changelog",
247
477
  });
248
478
  changelogBtn.addEventListener("click", () => {
249
479
  window.open(this.config.links.changelog, "_blank");
@@ -259,7 +489,7 @@ export class WhatsNewModal extends Modal {
259
489
 
260
490
  // Tools button
261
491
  const toolsBtn = buttonContainer.createEl("button", {
262
- text: "My Tools",
492
+ text: "Other Plugins",
263
493
  });
264
494
  toolsBtn.addEventListener("click", () => {
265
495
  window.open(this.config.links.tools ?? DEFAULT_WHATS_NEW_LINKS.TOOLS, "_blank");
@@ -267,7 +497,7 @@ export class WhatsNewModal extends Modal {
267
497
 
268
498
  // YouTube button
269
499
  const youtubeBtn = buttonContainer.createEl("button", {
270
- text: "YouTube Channel",
500
+ text: "YouTube",
271
501
  });
272
502
  youtubeBtn.addEventListener("click", () => {
273
503
  window.open(this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE, "_blank");