@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
|
|
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 =
|
|
114
|
-
toolsText.createSpan({ text: "
|
|
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 =
|
|
124
|
-
youtubeText.createSpan({ text: "
|
|
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 =
|
|
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: "
|
|
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: "
|
|
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
|
|
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
|
@@ -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 =
|
|
186
|
-
toolsText.createSpan({ text: "
|
|
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 =
|
|
197
|
-
youtubeText.createSpan({ text: "
|
|
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 =
|
|
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: "
|
|
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: "
|
|
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
|
|
500
|
+
text: "YouTube",
|
|
271
501
|
});
|
|
272
502
|
youtubeBtn.addEventListener("click", () => {
|
|
273
503
|
window.open(this.config.links.youtube ?? DEFAULT_WHATS_NEW_LINKS.YOUTUBE, "_blank");
|