quikdown 1.2.10 → 1.2.12
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.md +2 -2
- package/dist/quikdown.cjs +96 -3
- package/dist/quikdown.d.ts +12 -0
- package/dist/quikdown.dark.css +1 -1
- package/dist/quikdown.esm.js +96 -3
- package/dist/quikdown.esm.min.js +2 -2
- package/dist/quikdown.esm.min.js.gz +0 -0
- package/dist/quikdown.esm.min.js.map +1 -1
- package/dist/quikdown.light.css +1 -1
- package/dist/quikdown.umd.js +96 -3
- package/dist/quikdown.umd.min.js +2 -2
- package/dist/quikdown.umd.min.js.gz +0 -0
- package/dist/quikdown.umd.min.js.map +1 -1
- package/dist/quikdown_ast.cjs +2 -2
- package/dist/quikdown_ast.esm.js +2 -2
- package/dist/quikdown_ast.esm.min.js +2 -2
- package/dist/quikdown_ast.esm.min.js.gz +0 -0
- package/dist/quikdown_ast.umd.js +2 -2
- package/dist/quikdown_ast.umd.min.js +2 -2
- package/dist/quikdown_ast.umd.min.js.gz +0 -0
- package/dist/quikdown_ast_html.cjs +3 -3
- package/dist/quikdown_ast_html.esm.js +3 -3
- package/dist/quikdown_ast_html.esm.min.js +2 -2
- package/dist/quikdown_ast_html.esm.min.js.gz +0 -0
- package/dist/quikdown_ast_html.umd.js +3 -3
- package/dist/quikdown_ast_html.umd.min.js +2 -2
- package/dist/quikdown_ast_html.umd.min.js.gz +0 -0
- package/dist/quikdown_bd.cjs +96 -3
- package/dist/quikdown_bd.esm.js +96 -3
- package/dist/quikdown_bd.esm.min.js +2 -2
- package/dist/quikdown_bd.esm.min.js.gz +0 -0
- package/dist/quikdown_bd.esm.min.js.map +1 -1
- package/dist/quikdown_bd.umd.js +96 -3
- package/dist/quikdown_bd.umd.min.js +2 -2
- package/dist/quikdown_bd.umd.min.js.gz +0 -0
- package/dist/quikdown_bd.umd.min.js.map +1 -1
- package/dist/quikdown_edit.cjs +232 -6
- package/dist/quikdown_edit.esm.js +232 -6
- package/dist/quikdown_edit.esm.min.js +3 -3
- package/dist/quikdown_edit.esm.min.js.gz +0 -0
- package/dist/quikdown_edit.esm.min.js.map +1 -1
- package/dist/quikdown_edit.umd.js +232 -6
- package/dist/quikdown_edit.umd.min.js +3 -3
- package/dist/quikdown_edit.umd.min.js.gz +0 -0
- package/dist/quikdown_edit.umd.min.js.map +1 -1
- package/dist/quikdown_json.cjs +3 -3
- package/dist/quikdown_json.esm.js +3 -3
- package/dist/quikdown_json.esm.min.js +2 -2
- package/dist/quikdown_json.esm.min.js.gz +0 -0
- package/dist/quikdown_json.umd.js +3 -3
- package/dist/quikdown_json.umd.min.js +2 -2
- package/dist/quikdown_json.umd.min.js.gz +0 -0
- package/dist/quikdown_yaml.cjs +3 -3
- package/dist/quikdown_yaml.esm.js +3 -3
- package/dist/quikdown_yaml.esm.min.js +2 -2
- package/dist/quikdown_yaml.esm.min.js.gz +0 -0
- package/dist/quikdown_yaml.umd.js +3 -3
- package/dist/quikdown_yaml.umd.min.js +2 -2
- package/dist/quikdown_yaml.umd.min.js.gz +0 -0
- package/package.json +2 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Quikdown Editor - Drop-in Markdown Parser
|
|
3
|
-
* @version 1.2.
|
|
3
|
+
* @version 1.2.12
|
|
4
4
|
* @license BSD-2-Clause
|
|
5
5
|
* @copyright DeftIO 2025
|
|
6
6
|
*/
|
|
@@ -228,7 +228,7 @@
|
|
|
228
228
|
// ────────────────────────────────────────────────────────────────────
|
|
229
229
|
|
|
230
230
|
/** Build-time version stamp (injected by tools/updateVersion) */
|
|
231
|
-
const quikdownVersion = '1.2.
|
|
231
|
+
const quikdownVersion = '1.2.12';
|
|
232
232
|
|
|
233
233
|
/** CSS class prefix used for all generated elements */
|
|
234
234
|
const CLASS_PREFIX = 'quikdown-';
|
|
@@ -236,6 +236,10 @@
|
|
|
236
236
|
/** Placeholder sigils — chosen to be extremely unlikely in real text */
|
|
237
237
|
const PLACEHOLDER_CB = '§CB'; // fenced code blocks
|
|
238
238
|
const PLACEHOLDER_IC = '§IC'; // inline code spans
|
|
239
|
+
const PLACEHOLDER_HT = '§HT'; // safe HTML tags (limited mode)
|
|
240
|
+
|
|
241
|
+
/** Attributes whose values need URL sanitization */
|
|
242
|
+
const URL_ATTRIBUTES = { href:1, src:1, action:1, formaction:1 };
|
|
239
243
|
|
|
240
244
|
/** HTML entity escape map */
|
|
241
245
|
const ESC_MAP = {'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
@@ -370,6 +374,46 @@
|
|
|
370
374
|
return trimmedUrl;
|
|
371
375
|
}
|
|
372
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Sanitize attributes on an HTML tag string for limited mode.
|
|
379
|
+
* Strips on* event handlers (case-insensitive) and runs sanitizeUrl()
|
|
380
|
+
* on href/src/action/formaction values.
|
|
381
|
+
*/
|
|
382
|
+
function sanitizeHtmlTagAttrs(tagStr) {
|
|
383
|
+
// Self-closing or void tag without attributes — pass through
|
|
384
|
+
if (!/\s/.test(tagStr.replace(/<\/?[a-zA-Z][a-zA-Z0-9]*/, '').replace(/\/?>$/, ''))) {
|
|
385
|
+
return tagStr;
|
|
386
|
+
}
|
|
387
|
+
// Parse: <tagname ...attrs... > or <tagname ...attrs... />
|
|
388
|
+
const m = tagStr.match(/^(<\/?[a-zA-Z][a-zA-Z0-9]*)([\s\S]*?)(\/?>)$/);
|
|
389
|
+
/* istanbul ignore next - defensive: Phase 1.5 regex guarantees valid tag shape */
|
|
390
|
+
if (!m) return tagStr;
|
|
391
|
+
|
|
392
|
+
const [, open, attrStr, close] = m;
|
|
393
|
+
// Match individual attributes: name="value", name='value', name=value, or bare name
|
|
394
|
+
// eslint-disable-next-line security/detect-unsafe-regex -- linear: no nested quantifiers
|
|
395
|
+
const attrRe = /([a-zA-Z_][\w\-.:]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/g;
|
|
396
|
+
const attrs = [];
|
|
397
|
+
let am;
|
|
398
|
+
while ((am = attrRe.exec(attrStr)) !== null) {
|
|
399
|
+
const name = am[1];
|
|
400
|
+
const value = am[2] !== undefined ? am[2] : am[3] !== undefined ? am[3] : am[4];
|
|
401
|
+
// Strip event handlers (on*)
|
|
402
|
+
if (/^on/i.test(name)) continue;
|
|
403
|
+
if (value === undefined) {
|
|
404
|
+
// Boolean attribute (e.g. disabled, checked)
|
|
405
|
+
attrs.push(name);
|
|
406
|
+
} else {
|
|
407
|
+
let sanitized = value;
|
|
408
|
+
if (name.toLowerCase() in URL_ATTRIBUTES) {
|
|
409
|
+
sanitized = sanitizeUrl(value);
|
|
410
|
+
}
|
|
411
|
+
attrs.push(`${name}="${sanitized}"`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return open + (attrs.length ? ' ' + attrs.join(' ') : '') + close;
|
|
415
|
+
}
|
|
416
|
+
|
|
373
417
|
// ────────────────────────────────────────────────────────────────
|
|
374
418
|
// Phase 1 — Code Extraction
|
|
375
419
|
// ────────────────────────────────────────────────────────────────
|
|
@@ -421,17 +465,57 @@
|
|
|
421
465
|
return placeholder;
|
|
422
466
|
});
|
|
423
467
|
|
|
468
|
+
// ────────────────────────────────────────────────────────────────
|
|
469
|
+
// Phase 1.5 — Safe HTML Extraction (whitelist mode)
|
|
470
|
+
// ────────────────────────────────────────────────────────────────
|
|
471
|
+
// When allow_unsafe_html is an object or array, extract whitelisted
|
|
472
|
+
// HTML tags, sanitize their attributes, and replace with placeholders.
|
|
473
|
+
// Non-whitelisted tags stay in text so Phase 2 will escape them.
|
|
474
|
+
|
|
475
|
+
const safeTags = [];
|
|
476
|
+
// Normalize: array → object for O(1) lookup; object used as-is
|
|
477
|
+
const htmlAllow = Array.isArray(allow_unsafe_html)
|
|
478
|
+
? Object.fromEntries(allow_unsafe_html.map(t => [t, 1]))
|
|
479
|
+
: (allow_unsafe_html && typeof allow_unsafe_html === 'object') ? allow_unsafe_html : null;
|
|
480
|
+
|
|
481
|
+
if (htmlAllow) {
|
|
482
|
+
// Pass through HTML comments — browsers render them as nothing
|
|
483
|
+
html = html.replace(/<!--[\s\S]*?-->/g, (match) => {
|
|
484
|
+
const idx = safeTags.length;
|
|
485
|
+
safeTags.push(match);
|
|
486
|
+
return `${PLACEHOLDER_HT}${idx}§`;
|
|
487
|
+
});
|
|
488
|
+
html = html.replace(/<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*\/?>/g, (match, tagName) => {
|
|
489
|
+
if (tagName.toLowerCase() in htmlAllow) {
|
|
490
|
+
const sanitized = sanitizeHtmlTagAttrs(match);
|
|
491
|
+
const idx = safeTags.length;
|
|
492
|
+
safeTags.push(sanitized);
|
|
493
|
+
return `${PLACEHOLDER_HT}${idx}§`;
|
|
494
|
+
}
|
|
495
|
+
// Not whitelisted — leave in text for Phase 2 to escape
|
|
496
|
+
return match;
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
424
500
|
// ────────────────────────────────────────────────────────────────
|
|
425
501
|
// Phase 2 — HTML Escaping
|
|
426
502
|
// ────────────────────────────────────────────────────────────────
|
|
427
503
|
// All remaining text (everything except code placeholders) is escaped
|
|
428
504
|
// to prevent XSS. The `allow_unsafe_html` option skips this for
|
|
429
505
|
// trusted pipelines that intentionally embed raw HTML.
|
|
506
|
+
// For whitelist mode, escaping still runs (only `true` bypasses it).
|
|
430
507
|
|
|
431
|
-
if (
|
|
508
|
+
if (allow_unsafe_html !== true) {
|
|
432
509
|
html = escapeHtml(html);
|
|
433
510
|
}
|
|
434
511
|
|
|
512
|
+
// Restore safe HTML tag placeholders after escaping
|
|
513
|
+
if (htmlAllow) {
|
|
514
|
+
safeTags.forEach((tag, i) => {
|
|
515
|
+
html = html.replace(`${PLACEHOLDER_HT}${i}§`, tag);
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
|
|
435
519
|
// ────────────────────────────────────────────────────────────────
|
|
436
520
|
// Phase 3 — Block Scanning + Inline Formatting + Paragraphs
|
|
437
521
|
// ────────────────────────────────────────────────────────────────
|
|
@@ -673,6 +757,14 @@
|
|
|
673
757
|
while (i < lines.length) {
|
|
674
758
|
const line = lines[i];
|
|
675
759
|
|
|
760
|
+
// ── Markdown comment (reference-link hack) ──
|
|
761
|
+
// [//]: # (comment) or [//]: # "comment" or [//]: #
|
|
762
|
+
// These produce no output — standard markdown comment convention.
|
|
763
|
+
if (/^\[\/\/\]: #/.test(line)) {
|
|
764
|
+
i++;
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
|
|
676
768
|
// ── Heading ──
|
|
677
769
|
// Count leading '#' characters. Valid heading: 1-6 hashes then a space.
|
|
678
770
|
// Example: "## Hello World ##" → <h2>Hello World</h2>
|
|
@@ -1037,6 +1129,7 @@
|
|
|
1037
1129
|
/** Semantic version (injected at build time) */
|
|
1038
1130
|
quikdown.version = quikdownVersion;
|
|
1039
1131
|
|
|
1132
|
+
|
|
1040
1133
|
// ════════════════════════════════════════════════════════════════════
|
|
1041
1134
|
// Exports
|
|
1042
1135
|
// ════════════════════════════════════════════════════════════════════
|
|
@@ -2934,6 +3027,37 @@
|
|
|
2934
3027
|
*/
|
|
2935
3028
|
|
|
2936
3029
|
|
|
3030
|
+
/**
|
|
3031
|
+
* Curated safe HTML tag whitelist.
|
|
3032
|
+
* Pass to quikdown's `allow_unsafe_html` option to allow these tags
|
|
3033
|
+
* through while escaping everything else. Callers can use this as-is,
|
|
3034
|
+
* pass a subset, or build their own object — any object whose keys are
|
|
3035
|
+
* lowercase tag names works.
|
|
3036
|
+
*
|
|
3037
|
+
* @example
|
|
3038
|
+
* // Use the curated list
|
|
3039
|
+
* quikdown(md, { allow_unsafe_html: QuikdownEditor.SAFE_HTML_TAGS });
|
|
3040
|
+
*
|
|
3041
|
+
* // Or a minimal subset
|
|
3042
|
+
* quikdown(md, { allow_unsafe_html: { img: 1, a: 1, br: 1 } });
|
|
3043
|
+
*
|
|
3044
|
+
* // Or an array (converted internally)
|
|
3045
|
+
* quikdown(md, { allow_unsafe_html: ['img', 'a', 'br'] });
|
|
3046
|
+
*/
|
|
3047
|
+
const SAFE_HTML_TAGS = {
|
|
3048
|
+
b:1, i:1, em:1, strong:1, del:1, s:1, u:1, mark:1, sup:1, sub:1,
|
|
3049
|
+
kbd:1, abbr:1, var:1, samp:1, cite:1, small:1, ins:1, dfn:1,
|
|
3050
|
+
ruby:1, rt:1, rp:1, time:1, wbr:1,
|
|
3051
|
+
img:1, picture:1, source:1, video:1, audio:1, figure:1, figcaption:1,
|
|
3052
|
+
a:1, br:1, hr:1,
|
|
3053
|
+
div:1, span:1, p:1, details:1, summary:1,
|
|
3054
|
+
section:1, article:1, aside:1, header:1, footer:1, nav:1, main:1,
|
|
3055
|
+
table:1, thead:1, tbody:1, tfoot:1, tr:1, th:1, td:1, caption:1, col:1, colgroup:1,
|
|
3056
|
+
ul:1, ol:1, li:1, dl:1, dt:1, dd:1,
|
|
3057
|
+
h1:1, h2:1, h3:1, h4:1, h5:1, h6:1,
|
|
3058
|
+
blockquote:1, pre:1, code:1
|
|
3059
|
+
};
|
|
3060
|
+
|
|
2937
3061
|
// Default options
|
|
2938
3062
|
const DEFAULT_OPTIONS = {
|
|
2939
3063
|
mode: 'split', // 'source' | 'preview' | 'split'
|
|
@@ -2973,7 +3097,9 @@
|
|
|
2973
3097
|
customFences: {}, // { 'language': (code, lang) => html }
|
|
2974
3098
|
enableComplexFences: true, // Enable CSV tables, math rendering, SVG, etc.
|
|
2975
3099
|
showUndoRedo: false, // Show undo/redo toolbar buttons
|
|
2976
|
-
undoStackSize: 100
|
|
3100
|
+
undoStackSize: 100, // Maximum number of undo states to keep
|
|
3101
|
+
allowUnsafeHTML: false, // false | 'limited' | true — controls HTML passthrough
|
|
3102
|
+
showAllowUnsafeHTML: false // Show toolbar button to cycle HTML mode
|
|
2977
3103
|
};
|
|
2978
3104
|
|
|
2979
3105
|
// Library catalog used by preloadFences. Each entry knows how to:
|
|
@@ -3218,7 +3344,17 @@
|
|
|
3218
3344
|
lazyLFBtn.title = 'Convert single newlines to paragraph breaks (one-time transform)';
|
|
3219
3345
|
toolbar.appendChild(lazyLFBtn);
|
|
3220
3346
|
}
|
|
3221
|
-
|
|
3347
|
+
|
|
3348
|
+
// Allow unsafe HTML toggle button (if enabled)
|
|
3349
|
+
if (this.options.showAllowUnsafeHTML) {
|
|
3350
|
+
const htmlModeBtn = document.createElement('button');
|
|
3351
|
+
htmlModeBtn.className = 'qde-btn';
|
|
3352
|
+
htmlModeBtn.dataset.action = 'toggle-html-mode';
|
|
3353
|
+
htmlModeBtn.textContent = this._getHtmlModeLabel(this.options.allowUnsafeHTML);
|
|
3354
|
+
htmlModeBtn.title = this._getHtmlModeTooltip(this.options.allowUnsafeHTML);
|
|
3355
|
+
toolbar.appendChild(htmlModeBtn);
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3222
3358
|
return toolbar;
|
|
3223
3359
|
}
|
|
3224
3360
|
|
|
@@ -3277,6 +3413,25 @@
|
|
|
3277
3413
|
opacity: 0.4;
|
|
3278
3414
|
pointer-events: none;
|
|
3279
3415
|
}
|
|
3416
|
+
.qde-btn[data-action="toggle-html-mode"] {
|
|
3417
|
+
position: relative;
|
|
3418
|
+
}
|
|
3419
|
+
.qde-btn[data-action="toggle-html-mode"]:hover::after {
|
|
3420
|
+
content: attr(title);
|
|
3421
|
+
position: absolute;
|
|
3422
|
+
bottom: calc(100% + 6px);
|
|
3423
|
+
left: 50%;
|
|
3424
|
+
transform: translateX(-50%);
|
|
3425
|
+
padding: 5px 10px;
|
|
3426
|
+
background: #1f2937;
|
|
3427
|
+
color: #fff;
|
|
3428
|
+
font-size: 0.75rem;
|
|
3429
|
+
font-weight: 400;
|
|
3430
|
+
white-space: nowrap;
|
|
3431
|
+
border-radius: 4px;
|
|
3432
|
+
pointer-events: none;
|
|
3433
|
+
z-index: 10;
|
|
3434
|
+
}
|
|
3280
3435
|
|
|
3281
3436
|
.qde-spacer {
|
|
3282
3437
|
flex: 1;
|
|
@@ -3381,6 +3536,9 @@
|
|
|
3381
3536
|
.qde-preview > svg {
|
|
3382
3537
|
max-width: 100%;
|
|
3383
3538
|
}
|
|
3539
|
+
.qde-preview img {
|
|
3540
|
+
display: inline;
|
|
3541
|
+
}
|
|
3384
3542
|
.qde-preview .leaflet-container { box-sizing: border-box; }
|
|
3385
3543
|
|
|
3386
3544
|
/* Standard markdown tables (the .quikdown-table class) need to
|
|
@@ -3801,10 +3959,16 @@
|
|
|
3801
3959
|
this.previewPanel.innerHTML = '<div style="color: #999; font-style: italic; padding: 16px;">Start typing markdown in the source panel...</div>';
|
|
3802
3960
|
}
|
|
3803
3961
|
} else {
|
|
3962
|
+
// Translate editor's allowUnsafeHTML to parser's allow_unsafe_html:
|
|
3963
|
+
// false → false, true → true, 'limited' → quikdown_bd.SAFE_HTML_TAGS
|
|
3964
|
+
const htmlMode = this.options.allowUnsafeHTML;
|
|
3965
|
+
const allowHtml = htmlMode === 'limited' ? SAFE_HTML_TAGS : htmlMode;
|
|
3966
|
+
|
|
3804
3967
|
this._html = quikdown_bd(markdown, {
|
|
3805
3968
|
fence_plugin: this.createFencePlugin(),
|
|
3806
3969
|
lazy_linefeeds: this.options.lazy_linefeeds,
|
|
3807
|
-
inline_styles: this.options.inline_styles
|
|
3970
|
+
inline_styles: this.options.inline_styles,
|
|
3971
|
+
allow_unsafe_html: allowHtml
|
|
3808
3972
|
});
|
|
3809
3973
|
|
|
3810
3974
|
// Update preview if visible
|
|
@@ -5038,6 +5202,9 @@
|
|
|
5038
5202
|
case 'redo':
|
|
5039
5203
|
this.redo();
|
|
5040
5204
|
break;
|
|
5205
|
+
case 'toggle-html-mode':
|
|
5206
|
+
this.cycleAllowUnsafeHTML();
|
|
5207
|
+
break;
|
|
5041
5208
|
}
|
|
5042
5209
|
}
|
|
5043
5210
|
|
|
@@ -5392,6 +5559,62 @@
|
|
|
5392
5559
|
}
|
|
5393
5560
|
}
|
|
5394
5561
|
|
|
5562
|
+
/**
|
|
5563
|
+
* Get the label for the current HTML passthrough mode.
|
|
5564
|
+
* @private
|
|
5565
|
+
*/
|
|
5566
|
+
_getHtmlModeLabel(mode) {
|
|
5567
|
+
if (mode === true) return 'HTML: Raw';
|
|
5568
|
+
if (mode === 'limited') return 'HTML: Safe';
|
|
5569
|
+
return 'HTML: Off';
|
|
5570
|
+
}
|
|
5571
|
+
|
|
5572
|
+
/** @private */
|
|
5573
|
+
_getHtmlModeTooltip(mode) {
|
|
5574
|
+
if (mode === true) return 'All HTML passes through — no protection';
|
|
5575
|
+
if (mode === 'limited') return 'Safe tags render, dangerous tags escaped';
|
|
5576
|
+
return 'All HTML tags shown as text';
|
|
5577
|
+
}
|
|
5578
|
+
|
|
5579
|
+
/**
|
|
5580
|
+
* Cycle allowUnsafeHTML through false → "limited" → true → false.
|
|
5581
|
+
*/
|
|
5582
|
+
cycleAllowUnsafeHTML() {
|
|
5583
|
+
const current = this.options.allowUnsafeHTML;
|
|
5584
|
+
let next;
|
|
5585
|
+
if (current === false) next = 'limited';
|
|
5586
|
+
else if (current === 'limited') next = true;
|
|
5587
|
+
else next = false;
|
|
5588
|
+
this.setAllowUnsafeHTML(next);
|
|
5589
|
+
}
|
|
5590
|
+
|
|
5591
|
+
/**
|
|
5592
|
+
* Set the HTML passthrough mode.
|
|
5593
|
+
* @param {boolean|'limited'} mode - false, 'limited', or true
|
|
5594
|
+
*/
|
|
5595
|
+
setAllowUnsafeHTML(mode) {
|
|
5596
|
+
if (mode !== false && mode !== true && mode !== 'limited') return;
|
|
5597
|
+
this.options.allowUnsafeHTML = mode;
|
|
5598
|
+
// Update toolbar button label
|
|
5599
|
+
if (this.toolbar) {
|
|
5600
|
+
const btn = this.toolbar.querySelector('[data-action="toggle-html-mode"]');
|
|
5601
|
+
if (btn) {
|
|
5602
|
+
btn.textContent = this._getHtmlModeLabel(mode);
|
|
5603
|
+
btn.title = this._getHtmlModeTooltip(mode);
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
// Re-render
|
|
5607
|
+
this.updateFromMarkdown(this._markdown);
|
|
5608
|
+
}
|
|
5609
|
+
|
|
5610
|
+
/**
|
|
5611
|
+
* Get the current HTML passthrough mode.
|
|
5612
|
+
* @returns {boolean|'limited'}
|
|
5613
|
+
*/
|
|
5614
|
+
getAllowUnsafeHTML() {
|
|
5615
|
+
return this.options.allowUnsafeHTML;
|
|
5616
|
+
}
|
|
5617
|
+
|
|
5395
5618
|
/**
|
|
5396
5619
|
* Destroy the editor
|
|
5397
5620
|
*/
|
|
@@ -5412,6 +5635,9 @@
|
|
|
5412
5635
|
}
|
|
5413
5636
|
}
|
|
5414
5637
|
|
|
5638
|
+
/** Static: curated safe HTML tag whitelist for allow_unsafe_html */
|
|
5639
|
+
QuikdownEditor.SAFE_HTML_TAGS = SAFE_HTML_TAGS;
|
|
5640
|
+
|
|
5415
5641
|
// Export for CommonJS (needed for bundled ESM to work with Jest)
|
|
5416
5642
|
if (typeof module !== 'undefined' && module.exports) {
|
|
5417
5643
|
module.exports = QuikdownEditor;
|