@fsegurai/marked-extended-embeds 17.0.0-beta.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.
- package/README.custom.md +641 -0
- package/README.md +730 -0
- package/dist/index.cjs +744 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.esm.js +742 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/renderer.d.ts +23 -0
- package/dist/tokenizer.d.ts +10 -0
- package/dist/types.d.ts +136 -0
- package/dist/utils/constants.d.ts +29 -0
- package/dist/utils/helpers.d.ts +38 -0
- package/dist/utils/inject-styles.d.ts +4 -0
- package/package.json +53 -0
- package/src/global.d.ts +13 -0
- package/src/index.ts +61 -0
- package/src/renderer.ts +212 -0
- package/src/tokenizer.ts +133 -0
- package/src/types.ts +163 -0
- package/src/utils/constants.ts +154 -0
- package/src/utils/helpers.ts +318 -0
- package/src/utils/inject-styles.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img alt="Marked Extensions Logo" src="https://raw.githubusercontent.com/fsegurai/marked-extensions/main/public/marked-extensions.svg">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://github.com/fsegurai/marked-extensions">
|
|
7
|
+
<img src="https://img.shields.io/azure-devops/build/fsegurai/93779823-473d-4fb3-a5b1-27aaa1a88ea2/18/main?label=Build%20Status&"
|
|
8
|
+
alt="Build Main Status">
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://www.npmjs.org/package/@fsegurai/marked-extended-embeds">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/@fsegurai/marked-extended-embeds.svg"
|
|
12
|
+
alt="Latest Release">
|
|
13
|
+
</a>
|
|
14
|
+
<br>
|
|
15
|
+
<img alt="GitHub contributors" src="https://img.shields.io/github/contributors/fsegurai/marked-extensions">
|
|
16
|
+
<img alt="Dependency status for repo" src="https://img.shields.io/librariesio/github/fsegurai/marked-extensions">
|
|
17
|
+
<a href="https://opensource.org/licenses/MIT">
|
|
18
|
+
<img alt="GitHub License" src="https://img.shields.io/github/license/fsegurai/marked-extensions">
|
|
19
|
+
</a>
|
|
20
|
+
<br>
|
|
21
|
+
<img alt="Stars" src="https://img.shields.io/github/stars/fsegurai/marked-extensions?style=square&labelColor=343b41"/>
|
|
22
|
+
<img alt="Forks" src="https://img.shields.io/github/forks/fsegurai/marked-extensions?style=square&labelColor=343b41"/>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
**An extension library for Marked.js to enhance Markdown rendering.**
|
|
26
|
+
|
|
27
|
+
`@fsegurai/marked-extended-embeds` Marked extension for embedding rich media from various platforms
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
This extension enables seamless integration of external content with automatic platform detection, responsive layouts,
|
|
32
|
+
privacy controls, and extensive customization options. Perfect for documentation, blogs, portfolios, and educational
|
|
33
|
+
content.
|
|
34
|
+
|
|
35
|
+
### Table of contents
|
|
36
|
+
|
|
37
|
+
- [Installation](#installation)
|
|
38
|
+
- [Usage](#usage)
|
|
39
|
+
- [Basic Usage](#basic-usage)
|
|
40
|
+
- [Supported Platforms](#supported-platforms)
|
|
41
|
+
|
|
42
|
+
- [Configuration Options](#configuration-options)
|
|
43
|
+
- [Embed Properties](#embed-properties)
|
|
44
|
+
- [Advanced Examples](#advanced-examples)
|
|
45
|
+
- [More Resources](#more-resources)
|
|
46
|
+
- [Available Extensions](#available-extensions)
|
|
47
|
+
- [Demo Application](#demo-application)
|
|
48
|
+
- [License](#license)
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
To add `@fsegurai/marked-extended-embeds` along with Marked.js to your `package.json` use the following commands.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
bun install @fsegurai/marked-extended-embeds marked@>=17.0.0 --save
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
### Basic Usage
|
|
61
|
+
|
|
62
|
+
Import `@fsegurai/marked-extended-embeds` and apply it to your Marked instance as shown below.
|
|
63
|
+
|
|
64
|
+
**The extension automatically detects the platform from URLs or accepts explicit `provider` specification.**
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import { marked } from 'marked';
|
|
68
|
+
import markedExtendedEmbeds from '@fsegurai/marked-extended-embeds';
|
|
69
|
+
|
|
70
|
+
// or UMD script
|
|
71
|
+
// <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
|
|
72
|
+
// <script src="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-embeds/lib/index.umd.js"></script>
|
|
73
|
+
|
|
74
|
+
marked.use(markedExtendedEmbeds());
|
|
75
|
+
|
|
76
|
+
const markdown = `
|
|
77
|
+
::::embed{title="My Video" aspectRatio="16:9"}
|
|
78
|
+
https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
79
|
+
::::embedend
|
|
80
|
+
|
|
81
|
+
::::embed{provider="codepen" theme="dark"}
|
|
82
|
+
https://codepen.io/username/pen/abc123
|
|
83
|
+
::::embedend
|
|
84
|
+
|
|
85
|
+
::::embed{title="Spotify Playlist"}
|
|
86
|
+
https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M
|
|
87
|
+
::::embedend
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
marked.parse(markdown);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The extension automatically detects providers, applies responsive layouts with proper aspect ratios, and includes
|
|
94
|
+
accessibility features. All embeds support lazy loading, sandbox security, and customizable styling.
|
|
95
|
+
|
|
96
|
+
### Styling Your Embeds
|
|
97
|
+
|
|
98
|
+
This extension follows a **separation of concerns** approach, injecting only minimal structural CSS. Visual styling is completely separated for maximum flexibility.
|
|
99
|
+
|
|
100
|
+
#### Generated HTML Structure
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
|
|
104
|
+
<div class="marked-extended-embed-container"
|
|
105
|
+
data-provider="youtube"
|
|
106
|
+
data-embed-id="dQw4w9WgXcQ">
|
|
107
|
+
<!-- Loading state -->
|
|
108
|
+
<div class="marked-extended-embed-loading">
|
|
109
|
+
<div class="marked-extended-embed-spinner"></div>
|
|
110
|
+
<p>Loading...</p>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<!-- Embedded content (iframe) -->
|
|
114
|
+
<iframe
|
|
115
|
+
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
|
|
116
|
+
loading="lazy"
|
|
117
|
+
sandbox="allow-scripts allow-same-origin"
|
|
118
|
+
allowfullscreen>
|
|
119
|
+
</iframe>
|
|
120
|
+
|
|
121
|
+
<!-- Optional caption -->
|
|
122
|
+
<div class="marked-extended-embed-caption">
|
|
123
|
+
Video description
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### CSS Classes Reference
|
|
129
|
+
|
|
130
|
+
| Class | Purpose | Element |
|
|
131
|
+
|-------|---------|---------|
|
|
132
|
+
| `.marked-extended-embed-container` | Main wrapper | Container |
|
|
133
|
+
| `.marked-extended-embed-container[data-provider="youtube"]` | Provider-specific styling | Container |
|
|
134
|
+
| `.marked-extended-embed-loading` | Loading state overlay | Loading div |
|
|
135
|
+
| `.marked-extended-embed-spinner` | Loading spinner animation | Spinner div |
|
|
136
|
+
| `.marked-extended-embed-loading-text` | "Loading..." text | Text element |
|
|
137
|
+
| `.marked-extended-embed-caption` | Caption/description | Caption div |
|
|
138
|
+
| `iframe` | Embedded content | Iframe |
|
|
139
|
+
|
|
140
|
+
#### Complete Styling Example
|
|
141
|
+
|
|
142
|
+
```css
|
|
143
|
+
/* Base Container */
|
|
144
|
+
.marked-extended-embed-container {
|
|
145
|
+
position: relative;
|
|
146
|
+
width: 100%;
|
|
147
|
+
margin: 1.5rem 0;
|
|
148
|
+
border-radius: 8px;
|
|
149
|
+
overflow: hidden;
|
|
150
|
+
background: #f5f5f5;
|
|
151
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Responsive aspect ratio wrapper */
|
|
155
|
+
.marked-extended-embed-container::before {
|
|
156
|
+
content: '';
|
|
157
|
+
display: block;
|
|
158
|
+
padding-top: 56.25%; /* 16:9 aspect ratio */
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.marked-extended-embed-container iframe {
|
|
162
|
+
position: absolute;
|
|
163
|
+
top: 0;
|
|
164
|
+
left: 0;
|
|
165
|
+
width: 100%;
|
|
166
|
+
height: 100%;
|
|
167
|
+
border: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Loading State */
|
|
171
|
+
.marked-extended-embed-loading {
|
|
172
|
+
position: absolute;
|
|
173
|
+
top: 0;
|
|
174
|
+
left: 0;
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-direction: column;
|
|
179
|
+
align-items: center;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
background: rgba(0, 0, 0, 0.05);
|
|
182
|
+
z-index: 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.marked-extended-embed-spinner {
|
|
186
|
+
width: 40px;
|
|
187
|
+
height: 40px;
|
|
188
|
+
border: 4px solid #e0e0e0;
|
|
189
|
+
border-top-color: #2196F3;
|
|
190
|
+
border-radius: 50%;
|
|
191
|
+
animation: spin 1s linear infinite;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@keyframes spin {
|
|
195
|
+
0% { transform: rotate(0deg); }
|
|
196
|
+
100% { transform: rotate(360deg); }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.marked-extended-embed-loading-text {
|
|
200
|
+
margin-top: 1rem;
|
|
201
|
+
font-size: 0.875rem;
|
|
202
|
+
font-weight: 500;
|
|
203
|
+
color: #666;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Caption Styling */
|
|
207
|
+
.marked-extended-embed-caption {
|
|
208
|
+
padding: 0.75rem 1rem;
|
|
209
|
+
font-size: 0.875rem;
|
|
210
|
+
color: #666;
|
|
211
|
+
background: #fafafa;
|
|
212
|
+
border-top: 1px solid #e0e0e0;
|
|
213
|
+
text-align: center;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Provider-Specific Backgrounds */
|
|
217
|
+
.marked-extended-embed-container[data-provider="youtube"] {
|
|
218
|
+
background: #000;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.marked-extended-embed-container[data-provider="vimeo"] {
|
|
222
|
+
background: #000;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.marked-extended-embed-container[data-provider="codepen"] {
|
|
226
|
+
background: #1e1e1e;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.marked-extended-embed-container[data-provider="codesandbox"] {
|
|
230
|
+
background: #151515;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.marked-extended-embed-container[data-provider="spotify"] {
|
|
234
|
+
background: #191414;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.marked-extended-embed-container[data-provider="soundcloud"] {
|
|
238
|
+
background: #ff5500;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.marked-extended-embed-container[data-provider="twitter"] {
|
|
242
|
+
background: #fff;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.marked-extended-embed-container[data-provider="github-gist"] {
|
|
246
|
+
background: #f6f8fa;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.marked-extended-embed-container[data-provider="figma"] {
|
|
250
|
+
background: #fff;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.marked-extended-embed-container[data-provider="mermaid"] {
|
|
254
|
+
background: #fff;
|
|
255
|
+
padding: 1rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.marked-extended-embed-container[data-provider="pdf"] {
|
|
259
|
+
background: #525659;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.marked-extended-embed-container[data-provider="loom"] {
|
|
263
|
+
background: #000;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.marked-extended-embed-container[data-provider="miro"] {
|
|
267
|
+
background: #fff;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.marked-extended-embed-container[data-provider="excalidraw"] {
|
|
271
|
+
background: #fff;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.marked-extended-embed-container[data-provider="drawio"],
|
|
275
|
+
.marked-extended-embed-container[data-provider="diagrams-net"] {
|
|
276
|
+
background: #fff;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Dark Mode Support
|
|
281
|
+
|
|
282
|
+
```css
|
|
283
|
+
/* Light theme */
|
|
284
|
+
body.light .marked-extended-embed-container {
|
|
285
|
+
background: #f5f5f5;
|
|
286
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
body.light .marked-extended-embed-caption {
|
|
290
|
+
background: #fafafa;
|
|
291
|
+
color: #666;
|
|
292
|
+
border-top-color: #e0e0e0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
body.light .marked-extended-embed-loading {
|
|
296
|
+
color: #666;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
body.light .marked-extended-embed-spinner {
|
|
300
|
+
border-color: #e0e0e0;
|
|
301
|
+
border-top-color: #2196F3;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* Dark theme */
|
|
305
|
+
body.dark .marked-extended-embed-container {
|
|
306
|
+
background: #1e1e1e;
|
|
307
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
body.dark .marked-extended-embed-caption {
|
|
311
|
+
background: #2a2a2a;
|
|
312
|
+
color: #e0e0e0;
|
|
313
|
+
border-top-color: #3a3a3a;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
body.dark .marked-extended-embed-loading {
|
|
317
|
+
color: #ccc;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
body.dark .marked-extended-embed-spinner {
|
|
321
|
+
border-color: #333;
|
|
322
|
+
border-top-color: #2196F3;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* Provider-specific dark mode overrides */
|
|
326
|
+
body.dark .marked-extended-embed-container[data-provider="mermaid"],
|
|
327
|
+
body.dark .marked-extended-embed-container[data-provider="twitter"],
|
|
328
|
+
body.dark .marked-extended-embed-container[data-provider="figma"],
|
|
329
|
+
body.dark .marked-extended-embed-container[data-provider="miro"],
|
|
330
|
+
body.dark .marked-extended-embed-container[data-provider="excalidraw"],
|
|
331
|
+
body.dark .marked-extended-embed-container[data-provider="drawio"],
|
|
332
|
+
body.dark .marked-extended-embed-container[data-provider="diagrams-net"] {
|
|
333
|
+
background: #1e1e1e;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
body.dark .marked-extended-embed-container[data-provider="github-gist"] {
|
|
337
|
+
background: #0d1117;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### Custom Aspect Ratios
|
|
342
|
+
|
|
343
|
+
```css
|
|
344
|
+
/* 16:9 (default - videos) */
|
|
345
|
+
.marked-extended-embed-container[data-provider="youtube"]::before,
|
|
346
|
+
.marked-extended-embed-container[data-provider="vimeo"]::before,
|
|
347
|
+
.marked-extended-embed-container[data-provider="loom"]::before {
|
|
348
|
+
padding-top: 56.25%;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* 1:1 (square - music players) */
|
|
352
|
+
.marked-extended-embed-container[data-provider="spotify"]::before,
|
|
353
|
+
.marked-extended-embed-container[data-provider="soundcloud"]::before {
|
|
354
|
+
padding-top: 100%;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* 4:3 (presentations) */
|
|
358
|
+
.marked-extended-embed-container[data-provider="google-slides"]::before {
|
|
359
|
+
padding-top: 75%;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Full height (code editors) */
|
|
363
|
+
.marked-extended-embed-container[data-provider="codepen"]::before,
|
|
364
|
+
.marked-extended-embed-container[data-provider="codesandbox"]::before,
|
|
365
|
+
.marked-extended-embed-container[data-provider="replit"]::before {
|
|
366
|
+
padding-top: 100%;
|
|
367
|
+
min-height: 500px;
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
#### Responsive Adjustments
|
|
372
|
+
|
|
373
|
+
```css
|
|
374
|
+
@media (max-width: 768px) {
|
|
375
|
+
.marked-extended-embed-container {
|
|
376
|
+
margin: 1rem 0;
|
|
377
|
+
border-radius: 4px;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.marked-extended-embed-caption {
|
|
381
|
+
padding: 0.5rem 0.75rem;
|
|
382
|
+
font-size: 0.8125rem;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* Reduce height for code editors on mobile */
|
|
386
|
+
.marked-extended-embed-container[data-provider="codepen"]::before,
|
|
387
|
+
.marked-extended-embed-container[data-provider="codesandbox"]::before {
|
|
388
|
+
min-height: 400px;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### Print Styles
|
|
394
|
+
|
|
395
|
+
```css
|
|
396
|
+
@media print {
|
|
397
|
+
.marked-extended-embed-container {
|
|
398
|
+
break-inside: avoid;
|
|
399
|
+
box-shadow: none;
|
|
400
|
+
border: 1px solid #ccc;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.marked-extended-embed-loading {
|
|
404
|
+
display: none;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Show caption */
|
|
408
|
+
.marked-extended-embed-caption {
|
|
409
|
+
display: block !important;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Hide interactive embeds, show placeholder */
|
|
413
|
+
.marked-extended-embed-container iframe {
|
|
414
|
+
display: none;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.marked-extended-embed-container::after {
|
|
418
|
+
content: "Embedded content: " attr(data-provider);
|
|
419
|
+
display: block;
|
|
420
|
+
padding: 2rem;
|
|
421
|
+
text-align: center;
|
|
422
|
+
color: #666;
|
|
423
|
+
font-style: italic;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
#### Copy Demo Theme
|
|
429
|
+
|
|
430
|
+
For complete styling with all 18+ providers: [embed-theme.css](https://github.com/fsegurai/marked-extensions/blob/main/demo/styles/extensions/embed-theme.css)
|
|
431
|
+
|
|
432
|
+
Check the [demo](https://fsegurai.github.io/marked-extensions) to see all embed types in action.
|
|
433
|
+
|
|
434
|
+
### Supported Platforms
|
|
435
|
+
|
|
436
|
+
The extension supports **18 different platforms** with automatic URL detection:
|
|
437
|
+
|
|
438
|
+
| Platform | Type | Example URL |
|
|
439
|
+
|------------------|---------------|-------------------------------|
|
|
440
|
+
| **YouTube** | Video | `youtube.com/watch?v=...` |
|
|
441
|
+
| **Vimeo** | Video | `vimeo.com/123456789` |
|
|
442
|
+
| **CodePen** | Code | `codepen.io/user/pen/abc` |
|
|
443
|
+
| **CodeSandbox** | Code | `codesandbox.io/s/abc` |
|
|
444
|
+
| **Twitter** | Social | `twitter.com/user/status/123` |
|
|
445
|
+
| **GitHub Gist** | Code | `gist.github.com/user/abc` |
|
|
446
|
+
| **Spotify** | Music | `open.spotify.com/track/abc` |
|
|
447
|
+
| **SoundCloud** | Music | `soundcloud.com/user/track` |
|
|
448
|
+
| **SlideShare** | Presentation | `slideshare.net/user/slides` |
|
|
449
|
+
| **Figma** | Design | `figma.com/file/abc` |
|
|
450
|
+
| **Loom** | Video | `loom.com/share/abc` |
|
|
451
|
+
| **Miro** | Collaboration | `miro.com/app/board/abc` |
|
|
452
|
+
| **Mermaid** | Diagram | `mermaid://graph TD; A-->B;` |
|
|
453
|
+
| **Excalidraw** | Drawing | `excalidraw.com/#room=abc` |
|
|
454
|
+
| **Draw.io** | Diagram | `diagrams.net/...` |
|
|
455
|
+
| **Diagrams.net** | Diagram | `diagrams.net/...` |
|
|
456
|
+
| **PDF** | Document | Any PDF URL |
|
|
457
|
+
| **iframe** | Generic | Any URL |
|
|
458
|
+
|
|
459
|
+
Each platform is automatically detected from the URL pattern. You can also explicitly specify the provider using the
|
|
460
|
+
`provider` property.
|
|
461
|
+
|
|
462
|
+
## Configuration Options
|
|
463
|
+
|
|
464
|
+
The marked-extended-embeds extension accepts the following configuration options:
|
|
465
|
+
|
|
466
|
+
- `className`: The base CSS class name for embeds. Defaults to 'marked-extended-embed.'
|
|
467
|
+
- `prefixId`: The prefix ID for embed elements. Defaults to 'embed'.
|
|
468
|
+
- `defaultAspectRatio`: Default aspect ratio ('16:9', '4:3', '1:1', '21:9'). Defaults to '16:9'.
|
|
469
|
+
- `allowFullscreen`: Allow fullscreen mode for embeds. Defaults to true.
|
|
470
|
+
- `lazyLoad`: Enable lazy loading for better performance. Defaults to true.
|
|
471
|
+
- `privacyMode`: Use privacy-enhanced domains when available. Defaults to false.
|
|
472
|
+
- `template`: Custom HTML template for rendering embeds. Defaults to built-in template.
|
|
473
|
+
- `customizeToken`: Function to customize embed tokens. Defaults to null.
|
|
474
|
+
- `injectStyles`: Whether to inject default styles. Defaults to true.
|
|
475
|
+
- `enableSandbox`: Enable iframe sandbox for security. Defaults to true.
|
|
476
|
+
- `sandboxPermissions`: Array of sandbox permissions. Defaults
|
|
477
|
+
to ['allow-scripts', 'allow-same-origin', 'allow-popups', 'allow-presentation'].
|
|
478
|
+
- `providers`: Custom provider configurations. Defaults to {}.
|
|
479
|
+
- `onEmbedLoad`: Callback when embed loads. Defaults to null.
|
|
480
|
+
- `onEmbedError`: Callback when embed fails. Defaults to null.
|
|
481
|
+
|
|
482
|
+
### Embed Properties
|
|
483
|
+
|
|
484
|
+
Embed syntax supports the following properties:
|
|
485
|
+
|
|
486
|
+
**Common Properties:**
|
|
487
|
+
|
|
488
|
+
- `title`: Title/caption for the embed
|
|
489
|
+
- `aspectRatio`: Aspect ratio ('16:9', '4:3', '1:1', '21:9', 'custom')
|
|
490
|
+
- `width`: Custom width (e.g., '800px')
|
|
491
|
+
- `height`: Custom height (e.g., '600px')
|
|
492
|
+
- `provider`: Explicit provider name
|
|
493
|
+
- `id`: Custom identifier for the embed
|
|
494
|
+
- `className`: Custom CSS class
|
|
495
|
+
|
|
496
|
+
**Media Properties:**
|
|
497
|
+
|
|
498
|
+
- `autoplay`: Auto-play video/audio (boolean)
|
|
499
|
+
- `muted`: Start muted (boolean)
|
|
500
|
+
- `loop`: Loop playback (boolean)
|
|
501
|
+
- `startTime`: Start time for videos (e.g., '30')
|
|
502
|
+
- `controls`: Show media controls (boolean)
|
|
503
|
+
|
|
504
|
+
**Display Properties:**
|
|
505
|
+
|
|
506
|
+
- `lazyLoad`: Enable lazy loading (boolean)
|
|
507
|
+
- `allowFullscreen`: Allow fullscreen mode (boolean)
|
|
508
|
+
- `privacyMode`: Use privacy-enhanced mode (boolean)
|
|
509
|
+
- `theme`: Theme setting ('light', 'dark')
|
|
510
|
+
|
|
511
|
+
**Custom Parameters:**
|
|
512
|
+
|
|
513
|
+
- `param-*`: Any property starting with 'param-' becomes a URL parameter
|
|
514
|
+
|
|
515
|
+
### Advanced Examples
|
|
516
|
+
|
|
517
|
+
#### YouTube Video with Options
|
|
518
|
+
|
|
519
|
+
```markdown
|
|
520
|
+
::::embed{
|
|
521
|
+
title="Tutorial Video"
|
|
522
|
+
aspectRatio="16:9"
|
|
523
|
+
autoplay="true"
|
|
524
|
+
muted="true"
|
|
525
|
+
startTime="30"
|
|
526
|
+
privacyMode="true"
|
|
527
|
+
}
|
|
528
|
+
https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
529
|
+
::::embedend
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
#### CodePen with Dark Theme
|
|
533
|
+
|
|
534
|
+
```markdown
|
|
535
|
+
::::embed{title="Interactive Demo" theme="dark"}
|
|
536
|
+
https://codepen.io/username/pen/abc123
|
|
537
|
+
::::embedend
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
#### Responsive Design File
|
|
541
|
+
|
|
542
|
+
```markdown
|
|
543
|
+
::::embed{
|
|
544
|
+
title="Mobile App Design"
|
|
545
|
+
aspectRatio="4:3"
|
|
546
|
+
width="100%"
|
|
547
|
+
}
|
|
548
|
+
https://www.figma.com/file/abc123/Mobile-App
|
|
549
|
+
::::embedend
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
#### Spotify Playlist
|
|
553
|
+
|
|
554
|
+
```markdown
|
|
555
|
+
::::embed{title="Coding Playlist" aspectRatio="1:1"}
|
|
556
|
+
https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M
|
|
557
|
+
::::embedend
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
#### CodeSandbox Project
|
|
561
|
+
|
|
562
|
+
```markdown
|
|
563
|
+
::::embed{
|
|
564
|
+
title="React Example"
|
|
565
|
+
theme="dark"
|
|
566
|
+
param-view="preview"
|
|
567
|
+
}
|
|
568
|
+
https://codesandbox.io/s/react-new
|
|
569
|
+
::::embedend
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
#### Mermaid Diagram
|
|
573
|
+
|
|
574
|
+
```markdown
|
|
575
|
+
::::embed{provider="mermaid" title="System Architecture"}
|
|
576
|
+
mermaid://graph TD;
|
|
577
|
+
A[Client] -->|Request| B[API Gateway];
|
|
578
|
+
B --> C[Service 1];
|
|
579
|
+
B --> D[Service 2];
|
|
580
|
+
C --> E[Database];
|
|
581
|
+
D --> E;
|
|
582
|
+
::::embedend
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
#### PDF Document
|
|
586
|
+
|
|
587
|
+
```markdown
|
|
588
|
+
::::embed{
|
|
589
|
+
provider="pdf"
|
|
590
|
+
title="Technical Specification"
|
|
591
|
+
aspectRatio="4:3"
|
|
592
|
+
}
|
|
593
|
+
https://example.com/document.pdf
|
|
594
|
+
::::embedend
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
#### Loom Video with Custom Size
|
|
598
|
+
|
|
599
|
+
```markdown
|
|
600
|
+
::::embed{
|
|
601
|
+
title="Product Demo"
|
|
602
|
+
width="800px"
|
|
603
|
+
height="450px"
|
|
604
|
+
}
|
|
605
|
+
https://www.loom.com/share/abc123
|
|
606
|
+
::::embedend
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### Twitter Thread
|
|
610
|
+
|
|
611
|
+
```markdown
|
|
612
|
+
::::embed{title="Latest Announcement"}
|
|
613
|
+
https://twitter.com/username/status/1234567890
|
|
614
|
+
::::embedend
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
#### GitHub Gist
|
|
618
|
+
|
|
619
|
+
```markdown
|
|
620
|
+
::::embed{title="Code Snippet"}
|
|
621
|
+
https://gist.github.com/username/abc123
|
|
622
|
+
::::embedend
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
#### Excalidraw Sketch
|
|
626
|
+
|
|
627
|
+
```markdown
|
|
628
|
+
::::embed{title="Whiteboard Sketch" aspectRatio="16:9"}
|
|
629
|
+
https://excalidraw.com/#room=abc123,def456
|
|
630
|
+
::::embedend
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
#### Draw.io Diagram
|
|
634
|
+
|
|
635
|
+
```markdown
|
|
636
|
+
::::embed{provider="drawio" title="System Architecture" aspectRatio="4:3"}
|
|
637
|
+
https://viewer.diagrams.net/?highlight=0000ff&edit=_blank&title=diagram
|
|
638
|
+
::::embedend
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
## Privacy Mode
|
|
642
|
+
|
|
643
|
+
Enable privacy-enhanced embedding for supported platforms:
|
|
644
|
+
|
|
645
|
+
```markdown
|
|
646
|
+
::::embed{privacyMode="true"}
|
|
647
|
+
https://www.youtube.com/watch?v=abc123
|
|
648
|
+
::::embedend
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
This uses `youtube-nocookie.com` for YouTube and similar privacy-focused domains when available.
|
|
652
|
+
|
|
653
|
+
## Custom Provider Configuration
|
|
654
|
+
|
|
655
|
+
Configure provider-specific settings:
|
|
656
|
+
|
|
657
|
+
```javascript
|
|
658
|
+
marked.use(markedExtendedEmbeds({
|
|
659
|
+
providers: {
|
|
660
|
+
youtube: {
|
|
661
|
+
domain: 'www.youtube-nocookie.com',
|
|
662
|
+
params: {
|
|
663
|
+
rel: '0',
|
|
664
|
+
modestbranding: '1',
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
spotify: {
|
|
668
|
+
params: {
|
|
669
|
+
theme: '0',
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
}));
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
## Security Features
|
|
677
|
+
|
|
678
|
+
The extension includes several security features:
|
|
679
|
+
|
|
680
|
+
- **Sandbox by default**: Iframes use sandbox attribute with restricted permissions
|
|
681
|
+
- **Configurable permissions**: Customize allowed iframe capabilities
|
|
682
|
+
- **Privacy mode**: Use no-cookie domains when available
|
|
683
|
+
- **XSS protection**: All user input is escaped
|
|
684
|
+
- **HTTPS enforcement**: Embed URLs use secure protocols
|
|
685
|
+
|
|
686
|
+
## Accessibility
|
|
687
|
+
|
|
688
|
+
All embeds include proper accessibility features:
|
|
689
|
+
|
|
690
|
+
- Semantic HTML with proper roles
|
|
691
|
+
- Alt text and titles
|
|
692
|
+
- Keyboard navigation support
|
|
693
|
+
- Screen reader compatibility
|
|
694
|
+
- Loading states with aria-labels
|
|
695
|
+
|
|
696
|
+
### Available Extensions
|
|
697
|
+
|
|
698
|
+
| Extension | Package | Version | Description |
|
|
699
|
+
|-------------|--------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------|
|
|
700
|
+
| Accordion | [@fsegurai/marked-extended-accordion](https://www.npmjs.com/package/@fsegurai/marked-extended-accordion) |  | Add collapsible accordion sections to your markdown |
|
|
701
|
+
| Alert | [@fsegurai/marked-extended-alert](https://www.npmjs.com/package/@fsegurai/marked-extended-alert) |  | Create styled alert boxes for important information |
|
|
702
|
+
| Comments | [@fsegurai/marked-extended-comments](https://www.npmjs.com/package/@fsegurai/marked-extended-comments) |  | Add comment sections with author and timestamp metadata |
|
|
703
|
+
| Embeds | [@fsegurai/marked-extended-embeds](https://www.npmjs.com/package/@fsegurai/marked-extended-embeds) |  | Easily embed content from various platforms (YouTube, Twitter, etc.) |
|
|
704
|
+
| Footnote | [@fsegurai/marked-extended-footnote](https://www.npmjs.com/package/@fsegurai/marked-extended-footnote) |  | Add footnotes with automatic numbering |
|
|
705
|
+
| Kanban | [@fsegurai/marked-extended-kanban](https://www.npmjs.com/package/@fsegurai/marked-extended-kanban) |  | Create kanban boards with customizable columns and cards |
|
|
706
|
+
| Lists | [@fsegurai/marked-extended-lists](https://www.npmjs.com/package/@fsegurai/marked-extended-lists) |  | Enhanced list formatting options |
|
|
707
|
+
| Slide | [@fsegurai/marked-extended-slide](https://www.npmjs.com/package/@fsegurai/marked-extended-slide) |  | Create slide decks directly from markdown content |
|
|
708
|
+
| Spoiler | [@fsegurai/marked-extended-spoiler](https://www.npmjs.com/package/@fsegurai/marked-extended-spoiler) |  | Hide content behind spoiler tags |
|
|
709
|
+
| Tables | [@fsegurai/marked-extended-tables](https://www.npmjs.com/package/@fsegurai/marked-extended-tables) |  | Advanced table formatting with cell spanning |
|
|
710
|
+
| Tabs | [@fsegurai/marked-extended-tabs](https://www.npmjs.com/package/@fsegurai/marked-extended-tabs) |  | Create tabbed content sections |
|
|
711
|
+
| Timeline | [@fsegurai/marked-extended-timeline](https://www.npmjs.com/package/@fsegurai/marked-extended-timeline) |  | Display content in an interactive timeline format |
|
|
712
|
+
| Typographic | [@fsegurai/marked-extended-typographic](https://www.npmjs.com/package/@fsegurai/marked-extended-typographic) |  | Improve typography with smart quotes, dashes, and more |
|
|
713
|
+
|
|
714
|
+
### Demo Application
|
|
715
|
+
|
|
716
|
+
To see all extensions in action, check out the [[DEMO]](https://fsegurai.github.io/marked-extensions).
|
|
717
|
+
|
|
718
|
+
To set up the demo locally, follow the next steps:
|
|
719
|
+
|
|
720
|
+
```shell
|
|
721
|
+
git clone https://github.com/fsegurai/marked-extensions.git
|
|
722
|
+
bun install
|
|
723
|
+
bun start
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
This will serve the application locally at [http://[::1]:8000](http://[::1]:8000).
|
|
727
|
+
|
|
728
|
+
## License
|
|
729
|
+
|
|
730
|
+
Licensed under [MIT](https://opensource.org/licenses/MIT).
|