@typefm/react-markdown-viewer 0.1.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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/ErrorBoundary.d.ts +25 -0
  4. package/dist/ErrorBoundary.d.ts.map +1 -0
  5. package/dist/ErrorBoundary.js +29 -0
  6. package/dist/ErrorBoundary.js.map +1 -0
  7. package/dist/MarkdownViewer.d.ts +41 -0
  8. package/dist/MarkdownViewer.d.ts.map +1 -0
  9. package/dist/MarkdownViewer.js +69 -0
  10. package/dist/MarkdownViewer.js.map +1 -0
  11. package/dist/index.d.ts +17 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +21 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lib/cache-manager.d.ts +59 -0
  16. package/dist/lib/cache-manager.d.ts.map +1 -0
  17. package/dist/lib/cache-manager.js +160 -0
  18. package/dist/lib/cache-manager.js.map +1 -0
  19. package/dist/lib/cursor-controller.d.ts +13 -0
  20. package/dist/lib/cursor-controller.d.ts.map +1 -0
  21. package/dist/lib/cursor-controller.js +93 -0
  22. package/dist/lib/cursor-controller.js.map +1 -0
  23. package/dist/lib/defaults/code-block.d.ts +71 -0
  24. package/dist/lib/defaults/code-block.d.ts.map +1 -0
  25. package/dist/lib/defaults/code-block.js +104 -0
  26. package/dist/lib/defaults/code-block.js.map +1 -0
  27. package/dist/lib/defaults/image.d.ts +41 -0
  28. package/dist/lib/defaults/image.d.ts.map +1 -0
  29. package/dist/lib/defaults/image.js +45 -0
  30. package/dist/lib/defaults/image.js.map +1 -0
  31. package/dist/lib/defaults/link.d.ts +45 -0
  32. package/dist/lib/defaults/link.d.ts.map +1 -0
  33. package/dist/lib/defaults/link.js +76 -0
  34. package/dist/lib/defaults/link.js.map +1 -0
  35. package/dist/lib/defaults/math.d.ts +51 -0
  36. package/dist/lib/defaults/math.d.ts.map +1 -0
  37. package/dist/lib/defaults/math.js +119 -0
  38. package/dist/lib/defaults/math.js.map +1 -0
  39. package/dist/lib/defaults/table.d.ts +18 -0
  40. package/dist/lib/defaults/table.d.ts.map +1 -0
  41. package/dist/lib/defaults/table.js +19 -0
  42. package/dist/lib/defaults/table.js.map +1 -0
  43. package/dist/lib/highlighter.d.ts +81 -0
  44. package/dist/lib/highlighter.d.ts.map +1 -0
  45. package/dist/lib/highlighter.js +421 -0
  46. package/dist/lib/highlighter.js.map +1 -0
  47. package/dist/lib/hook-utils.d.ts +32 -0
  48. package/dist/lib/hook-utils.d.ts.map +1 -0
  49. package/dist/lib/hook-utils.js +42 -0
  50. package/dist/lib/hook-utils.js.map +1 -0
  51. package/dist/lib/html.d.ts +2 -0
  52. package/dist/lib/html.d.ts.map +1 -0
  53. package/dist/lib/html.js +12 -0
  54. package/dist/lib/html.js.map +1 -0
  55. package/dist/lib/morph.d.ts +57 -0
  56. package/dist/lib/morph.d.ts.map +1 -0
  57. package/dist/lib/morph.js +204 -0
  58. package/dist/lib/morph.js.map +1 -0
  59. package/dist/lib/parser.d.ts +32 -0
  60. package/dist/lib/parser.d.ts.map +1 -0
  61. package/dist/lib/parser.js +645 -0
  62. package/dist/lib/parser.js.map +1 -0
  63. package/dist/lib/wasm-init.d.ts +33 -0
  64. package/dist/lib/wasm-init.d.ts.map +1 -0
  65. package/dist/lib/wasm-init.js +69 -0
  66. package/dist/lib/wasm-init.js.map +1 -0
  67. package/dist/styles/alerts.css +294 -0
  68. package/dist/styles/dotted.svg +3 -0
  69. package/dist/styles/hljs.css +332 -0
  70. package/dist/styles/index.css +17 -0
  71. package/dist/styles/katex.css +74 -0
  72. package/dist/styles/viewer.css +975 -0
  73. package/dist/types/hooks.d.ts +207 -0
  74. package/dist/types/hooks.d.ts.map +1 -0
  75. package/dist/types/hooks.js +7 -0
  76. package/dist/types/hooks.js.map +1 -0
  77. package/dist/useMarkdownViewer.d.ts +18 -0
  78. package/dist/useMarkdownViewer.d.ts.map +1 -0
  79. package/dist/useMarkdownViewer.js +403 -0
  80. package/dist/useMarkdownViewer.js.map +1 -0
  81. package/dist/utils.d.ts +20 -0
  82. package/dist/utils.d.ts.map +1 -0
  83. package/dist/utils.js +18 -0
  84. package/dist/utils.js.map +1 -0
  85. package/package.json +78 -0
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Unified LRU Cache Manager
3
+ * Coordinates memory usage across all caches in the markdown-viewer
4
+ */
5
+ class LRUCache {
6
+ cache = new Map();
7
+ sizeEstimates = new Map();
8
+ totalBytes = 0;
9
+ maxEntries;
10
+ maxBytes;
11
+ constructor(maxEntries, maxBytes = Infinity) {
12
+ this.maxEntries = maxEntries;
13
+ this.maxBytes = maxBytes;
14
+ }
15
+ get(key) {
16
+ const value = this.cache.get(key);
17
+ if (value !== undefined) {
18
+ // Move to end (most recently used)
19
+ this.cache.delete(key);
20
+ this.cache.set(key, value);
21
+ }
22
+ return value;
23
+ }
24
+ set(key, value, sizeBytes) {
25
+ // If key exists, remove old size
26
+ if (this.cache.has(key)) {
27
+ this.totalBytes -= this.sizeEstimates.get(key) ?? 0;
28
+ this.cache.delete(key);
29
+ this.sizeEstimates.delete(key);
30
+ }
31
+ // Estimate size if not provided
32
+ const size = sizeBytes ?? this.estimateSize(value);
33
+ // Evict if needed
34
+ while ((this.cache.size >= this.maxEntries || this.totalBytes + size > this.maxBytes) &&
35
+ this.cache.size > 0) {
36
+ const firstKey = this.cache.keys().next().value;
37
+ if (firstKey) {
38
+ this.totalBytes -= this.sizeEstimates.get(firstKey) ?? 0;
39
+ this.cache.delete(firstKey);
40
+ this.sizeEstimates.delete(firstKey);
41
+ }
42
+ }
43
+ this.cache.set(key, value);
44
+ this.sizeEstimates.set(key, size);
45
+ this.totalBytes += size;
46
+ }
47
+ has(key) {
48
+ return this.cache.has(key);
49
+ }
50
+ clear() {
51
+ this.cache.clear();
52
+ this.sizeEstimates.clear();
53
+ this.totalBytes = 0;
54
+ }
55
+ evictOldest(count) {
56
+ const keys = this.cache.keys();
57
+ for (let i = 0; i < count; i++) {
58
+ const { value: key, done } = keys.next();
59
+ if (done || !key)
60
+ break;
61
+ this.totalBytes -= this.sizeEstimates.get(key) ?? 0;
62
+ this.cache.delete(key);
63
+ this.sizeEstimates.delete(key);
64
+ }
65
+ }
66
+ get stats() {
67
+ return {
68
+ entries: this.cache.size,
69
+ estimatedBytes: this.totalBytes
70
+ };
71
+ }
72
+ estimateSize(value) {
73
+ if (typeof value === 'string') {
74
+ return value.length * 2; // UTF-16
75
+ }
76
+ return 100; // Default estimate for objects
77
+ }
78
+ }
79
+ // Total memory budget: ~10MB default
80
+ const DEFAULT_MEMORY_BUDGET = 10 * 1024 * 1024;
81
+ /**
82
+ * Global cache manager instance
83
+ * Coordinates memory across render cache, katex cache, and morph cache
84
+ */
85
+ class CacheManager {
86
+ memoryBudget;
87
+ // Individual caches with allocated budgets
88
+ // Separate render caches for sync/async strategies (avoids key concatenation)
89
+ renderCacheSync;
90
+ renderCacheAsync;
91
+ // Separate KaTeX caches for display/inline modes (avoids key concatenation)
92
+ katexCacheDisplay;
93
+ katexCacheInline;
94
+ // Highlight.js cache (key: "language:code", value: highlighted HTML)
95
+ highlightCache;
96
+ constructor(memoryBudget = DEFAULT_MEMORY_BUDGET) {
97
+ this.memoryBudget = memoryBudget;
98
+ // Allocate budget: 20% each for render sync/async, katex display/inline, highlight
99
+ // Note: morph state moved to WeakMap in morph.ts for per-instance isolation
100
+ this.renderCacheSync = new LRUCache(100, memoryBudget * 0.2);
101
+ this.renderCacheAsync = new LRUCache(100, memoryBudget * 0.2);
102
+ this.katexCacheDisplay = new LRUCache(250, memoryBudget * 0.2);
103
+ this.katexCacheInline = new LRUCache(250, memoryBudget * 0.2);
104
+ this.highlightCache = new LRUCache(200, memoryBudget * 0.2);
105
+ }
106
+ /**
107
+ * Get combined stats for all caches
108
+ */
109
+ get stats() {
110
+ const renderSync = this.renderCacheSync.stats;
111
+ const renderAsync = this.renderCacheAsync.stats;
112
+ const katexDisplay = this.katexCacheDisplay.stats;
113
+ const katexInline = this.katexCacheInline.stats;
114
+ const highlight = this.highlightCache.stats;
115
+ return {
116
+ renderSync,
117
+ renderAsync,
118
+ katexDisplay,
119
+ katexInline,
120
+ highlight,
121
+ total: {
122
+ entries: renderSync.entries + renderAsync.entries + katexDisplay.entries + katexInline.entries + highlight.entries,
123
+ estimatedBytes: renderSync.estimatedBytes + renderAsync.estimatedBytes + katexDisplay.estimatedBytes + katexInline.estimatedBytes + highlight.estimatedBytes
124
+ }
125
+ };
126
+ }
127
+ /**
128
+ * Clear all caches
129
+ */
130
+ clearAll() {
131
+ this.renderCacheSync.clear();
132
+ this.renderCacheAsync.clear();
133
+ this.katexCacheDisplay.clear();
134
+ this.katexCacheInline.clear();
135
+ this.highlightCache.clear();
136
+ }
137
+ /**
138
+ * Trim caches if under memory pressure
139
+ * Evicts ~25% of entries from each cache when budget exceeded
140
+ */
141
+ trimIfNeeded() {
142
+ const { total } = this.stats;
143
+ if (total.estimatedBytes > this.memoryBudget * 0.9) {
144
+ const caches = [
145
+ this.renderCacheSync,
146
+ this.renderCacheAsync,
147
+ this.katexCacheDisplay,
148
+ this.katexCacheInline,
149
+ this.highlightCache,
150
+ ];
151
+ for (const cache of caches) {
152
+ const targetEvictions = Math.ceil(cache.stats.entries * 0.25);
153
+ cache.evictOldest(targetEvictions);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ // Singleton instance
159
+ export const cacheManager = new CacheManager();
160
+ //# sourceMappingURL=cache-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-manager.js","sourceRoot":"","sources":["../../src/lib/cache-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface CursorBlinkOptions {
2
+ blinkEnabled?: boolean;
3
+ blinkSpeed?: number;
4
+ blinkDelay?: number;
5
+ }
6
+ export declare function createCursorController(options?: CursorBlinkOptions): {
7
+ update: (container: HTMLElement) => void;
8
+ setBlinking: (container: HTMLElement, blinking: boolean) => void;
9
+ reset: () => void;
10
+ destroy: () => void;
11
+ };
12
+ export type CursorController = ReturnType<typeof createCursorController>;
13
+ //# sourceMappingURL=cursor-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-controller.d.ts","sourceRoot":"","sources":["../../src/lib/cursor-controller.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,kBAAuB;wBAkD1C,WAAW,KAAG,IAAI;6BA0Bb,WAAW,YAAY,OAAO,KAAG,IAAI;iBAoBnD,IAAI;mBAUF,IAAI;EAWzB;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,93 @@
1
+ const DEFAULT_OPTIONS = {
2
+ blinkEnabled: true,
3
+ blinkSpeed: 1.0,
4
+ blinkDelay: 0.5,
5
+ };
6
+ export function createCursorController(options = {}) {
7
+ const config = { ...DEFAULT_OPTIONS, ...options };
8
+ // Time to wait after typing stops before blinking resumes.
9
+ const IDLE_TIMEOUT_MS = 500;
10
+ let activeTimer = null;
11
+ let isBlinkAlt = false;
12
+ let currentContainer = null;
13
+ // Initialize CSS variables on container
14
+ const initConfig = (el) => {
15
+ el.style.setProperty("--cursor-blink-name", "cursor-blink");
16
+ el.style.setProperty("--cursor-blink-duration", config.blinkEnabled ? `${config.blinkSpeed.toFixed(2)}s` : "0s");
17
+ el.style.setProperty("--cursor-blink-delay", `${config.blinkDelay.toFixed(2)}s`);
18
+ };
19
+ // Ensure container is initialized, returns cursor element if found
20
+ const ensureInit = (container) => {
21
+ if (container !== currentContainer) {
22
+ currentContainer = container;
23
+ initConfig(container);
24
+ }
25
+ return container.querySelector("[data-cursor]");
26
+ };
27
+ // Clear active timer if exists
28
+ const clearTimer = () => {
29
+ if (activeTimer) {
30
+ clearTimeout(activeTimer);
31
+ activeTimer = null;
32
+ }
33
+ };
34
+ // Toggle animation name to restart CSS animation at 0%
35
+ const resetBlinkAnimation = (el) => {
36
+ isBlinkAlt = !isBlinkAlt;
37
+ el.style.setProperty("--cursor-blink-name", isBlinkAlt ? "cursor-blink-" : "cursor-blink");
38
+ };
39
+ // Called on each content update during streaming
40
+ const update = (container) => {
41
+ const cursor = ensureInit(container);
42
+ if (!cursor)
43
+ return;
44
+ clearTimer();
45
+ resetBlinkAnimation(container);
46
+ // Restore configured blink delay (may have been set to 0 by setBlinking)
47
+ container.style.setProperty("--cursor-blink-delay", `${config.blinkDelay.toFixed(2)}s`);
48
+ // Make cursor solid while receiving updates
49
+ cursor.classList.add("cursor-active");
50
+ // Resume blinking after idle timeout
51
+ activeTimer = window.setTimeout(() => {
52
+ if (cursor.isConnected) {
53
+ cursor.classList.remove("cursor-active");
54
+ }
55
+ activeTimer = null;
56
+ }, IDLE_TIMEOUT_MS);
57
+ };
58
+ // Directly set blinking state (for empty content waiting state)
59
+ const setBlinking = (container, blinking) => {
60
+ const cursor = ensureInit(container);
61
+ if (!cursor)
62
+ return;
63
+ clearTimer();
64
+ if (blinking) {
65
+ // Set delay to 0 for immediate blinking (waiting state)
66
+ container.style.setProperty("--cursor-blink-delay", "0s");
67
+ cursor.classList.remove("cursor-active");
68
+ }
69
+ else {
70
+ // Restore configured delay
71
+ container.style.setProperty("--cursor-blink-delay", `${config.blinkDelay.toFixed(2)}s`);
72
+ cursor.classList.add("cursor-active");
73
+ }
74
+ };
75
+ const reset = () => {
76
+ clearTimer();
77
+ if (currentContainer) {
78
+ const cursor = currentContainer.querySelector("[data-cursor]");
79
+ cursor?.classList.remove("cursor-active");
80
+ }
81
+ };
82
+ const destroy = () => {
83
+ reset();
84
+ if (currentContainer) {
85
+ currentContainer.style.removeProperty("--cursor-blink-name");
86
+ currentContainer.style.removeProperty("--cursor-blink-duration");
87
+ currentContainer.style.removeProperty("--cursor-blink-delay");
88
+ }
89
+ currentContainer = null;
90
+ };
91
+ return { update, setBlinking, reset, destroy };
92
+ }
93
+ //# sourceMappingURL=cursor-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-controller.js","sourceRoot":"","sources":["../../src/lib/cursor-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Default code block processor with syntax highlighting and copy button.
3
+ *
4
+ * @module lib/defaults/code-block
5
+ */
6
+ import type { CodeBlockData, InlineCodeData } from '../../types/hooks';
7
+ /** SVG icon for copy button */
8
+ export declare const COPY_ICON = "<svg class=\"copy-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"></rect><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"></path></svg>";
9
+ /** SVG icon for copied state */
10
+ export declare const CHECK_ICON = "<svg class=\"check-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"></path></svg>";
11
+ /**
12
+ * Matches hex, rgb, rgba, hsl, hsla colors.
13
+ * Negative lookbehind prevents matching HTML entities like &#124; or &amp;#124;
14
+ */
15
+ export declare const COLOR_RE: RegExp;
16
+ export interface CodeBlockOptions {
17
+ /** Enable color preview injection (default: true) */
18
+ colorPreviews?: boolean;
19
+ /**
20
+ * Wrap lines in `<span class="code-line">` for streaming stability (default: false).
21
+ *
22
+ * Note: The default parser wraps lines automatically during streaming.
23
+ * Set this to `true` if you override `onCodeBlock` and want similar behavior.
24
+ */
25
+ wrapLines?: boolean;
26
+ }
27
+ export interface InlineCodeOptions {
28
+ /** Enable color preview injection (default: true) */
29
+ colorPreviews?: boolean;
30
+ }
31
+ /**
32
+ * Inject color preview boxes into content containing color codes.
33
+ *
34
+ * @param content - Content to process
35
+ * @returns Content with color preview boxes injected
36
+ */
37
+ export declare function injectColorPreviews(content: string): string;
38
+ /**
39
+ * Default code block processor.
40
+ *
41
+ * Applies syntax highlighting, optional color previews, and wraps in a
42
+ * container with a copy button.
43
+ *
44
+ * @param data - Code block data with code and language
45
+ * @param options - Processing options
46
+ * @returns HTML string for the code block
47
+ *
48
+ * @example
49
+ * const html = processCodeBlock(
50
+ * { code: 'const x = 1;', language: 'javascript' },
51
+ * { colorPreviews: true, wrapLines: false }
52
+ * );
53
+ */
54
+ export declare function processCodeBlock(data: CodeBlockData, options?: CodeBlockOptions): string;
55
+ /**
56
+ * Default inline code processor.
57
+ *
58
+ * Optionally injects color preview boxes for color codes.
59
+ *
60
+ * @param data - Inline code data
61
+ * @param options - Processing options
62
+ * @returns HTML string for the inline code
63
+ *
64
+ * @example
65
+ * const html = processInlineCode(
66
+ * { code: '#ff0000' },
67
+ * { colorPreviews: true }
68
+ * );
69
+ */
70
+ export declare function processInlineCode(data: InlineCodeData, options?: InlineCodeOptions): string;
71
+ //# sourceMappingURL=code-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../../src/lib/defaults/code-block.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMvE,+BAA+B;AAC/B,eAAO,MAAM,SAAS,2XAAyV,CAAC;AAEhX,gCAAgC;AAChC,eAAO,MAAM,UAAU,0QAAoP,CAAC;AAE5Q;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAsE,CAAC;AAM5F,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe3D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,aAAa,EACnB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAwBR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAYR"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Default code block processor with syntax highlighting and copy button.
3
+ *
4
+ * @module lib/defaults/code-block
5
+ */
6
+ import { highlight } from '../highlighter';
7
+ // --------------------------------------------------------------------------
8
+ // Constants (hoisted for performance)
9
+ // --------------------------------------------------------------------------
10
+ /** SVG icon for copy button */
11
+ export const COPY_ICON = `<svg class="copy-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>`;
12
+ /** SVG icon for copied state */
13
+ export const CHECK_ICON = `<svg class="check-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"></path></svg>`;
14
+ /**
15
+ * Matches hex, rgb, rgba, hsl, hsla colors.
16
+ * Negative lookbehind prevents matching HTML entities like &#124; or &amp;#124;
17
+ */
18
+ export const COLOR_RE = /(?<!&)(?<!;)#([0-9a-fA-F]{3,8})\b|(?:rgba?|hsla?)\([\d\s,.%]+\)/gi;
19
+ // --------------------------------------------------------------------------
20
+ // Processors
21
+ // --------------------------------------------------------------------------
22
+ /**
23
+ * Inject color preview boxes into content containing color codes.
24
+ *
25
+ * @param content - Content to process
26
+ * @returns Content with color preview boxes injected
27
+ */
28
+ export function injectColorPreviews(content) {
29
+ if (!content.includes('#') && !content.includes('rgb') && !content.includes('hsl')) {
30
+ return content;
31
+ }
32
+ return content.replace(COLOR_RE, (colorMatch) => {
33
+ // Validate hex colors
34
+ if (colorMatch.startsWith('#')) {
35
+ const hex = colorMatch.slice(1);
36
+ if (![3, 4, 6, 8].includes(hex.length)) {
37
+ return colorMatch;
38
+ }
39
+ }
40
+ return `<span style="white-space: nowrap;"><span class="color-box" style="background-color: ${colorMatch};"></span>${colorMatch}</span>`;
41
+ });
42
+ }
43
+ /**
44
+ * Default code block processor.
45
+ *
46
+ * Applies syntax highlighting, optional color previews, and wraps in a
47
+ * container with a copy button.
48
+ *
49
+ * @param data - Code block data with code and language
50
+ * @param options - Processing options
51
+ * @returns HTML string for the code block
52
+ *
53
+ * @example
54
+ * const html = processCodeBlock(
55
+ * { code: 'const x = 1;', language: 'javascript' },
56
+ * { colorPreviews: true, wrapLines: false }
57
+ * );
58
+ */
59
+ export function processCodeBlock(data, options = {}) {
60
+ const { code, language } = data;
61
+ const { colorPreviews = true, wrapLines = false } = options;
62
+ // 1. Apply syntax highlighting
63
+ let content = highlight(code, language);
64
+ // 2. Apply color previews if enabled
65
+ if (colorPreviews) {
66
+ content = injectColorPreviews(content);
67
+ }
68
+ // 3. Wrap lines for streaming stability
69
+ if (wrapLines && content) {
70
+ content = content.replace(/^(.*)$/gm, '<span class="code-line">$1</span>');
71
+ }
72
+ // 4. Build the code block with wrapper and copy button
73
+ const langClass = language ? `language-${language}` : '';
74
+ const codeTag = langClass
75
+ ? `<code class="${langClass}">${content}</code>`
76
+ : `<code>${content}</code>`;
77
+ return `<div class="code-block-wrapper"><button type="button" class="copy-btn" aria-label="Copy code">${COPY_ICON}${CHECK_ICON}</button><pre>${codeTag}</pre></div>`;
78
+ }
79
+ /**
80
+ * Default inline code processor.
81
+ *
82
+ * Optionally injects color preview boxes for color codes.
83
+ *
84
+ * @param data - Inline code data
85
+ * @param options - Processing options
86
+ * @returns HTML string for the inline code
87
+ *
88
+ * @example
89
+ * const html = processInlineCode(
90
+ * { code: '#ff0000' },
91
+ * { colorPreviews: true }
92
+ * );
93
+ */
94
+ export function processInlineCode(data, options = {}) {
95
+ const { code } = data;
96
+ const { colorPreviews = true } = options;
97
+ let content = code;
98
+ // Apply color previews if enabled
99
+ if (colorPreviews) {
100
+ content = injectColorPreviews(content);
101
+ }
102
+ return `<code>${content}</code>`;
103
+ }
104
+ //# sourceMappingURL=code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block.js","sourceRoot":"","sources":["../../../src/lib/defaults/code-block.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,6EAA6E;AAC7E,sCAAsC;AACtC,6EAA6E;AAE7E,+BAA+B;AAC/B,MAAM,CAAC,MAAM,SAAS,GAAG,sVAAsV,CAAC;AAEhX,gCAAgC;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG,iPAAiP,CAAC;AAE5Q;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,mEAAmE,CAAC;AAuB5F,6EAA6E;AAC7E,aAAa;AACb,6EAA6E;AAE7E;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAkB,EAAE,EAAE;QACtD,sBAAsB;QACtB,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;QACD,OAAO,uFAAuF,UAAU,aAAa,UAAU,SAAS,CAAC;IAC3I,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAmB,EACnB,UAA4B,EAAE;IAE9B,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE5D,+BAA+B;IAC/B,IAAI,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAExC,qCAAqC;IACrC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,wCAAwC;IACxC,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;QACzB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,mCAAmC,CAAC,CAAC;IAC7E,CAAC;IAED,uDAAuD;IACvD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,SAAS;QACvB,CAAC,CAAC,gBAAgB,SAAS,KAAK,OAAO,SAAS;QAChD,CAAC,CAAC,SAAS,OAAO,SAAS,CAAC;IAE9B,OAAO,iGAAiG,SAAS,GAAG,UAAU,iBAAiB,OAAO,cAAc,CAAC;AACvK,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAoB,EACpB,UAA6B,EAAE;IAE/B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzC,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,kCAAkC;IAClC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,SAAS,OAAO,SAAS,CAAC;AACnC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Default image processor with lazy loading and lightbox support.
3
+ *
4
+ * @module lib/defaults/image
5
+ */
6
+ import type { ImageData } from '../../types/hooks';
7
+ /**
8
+ * Options for image processing.
9
+ */
10
+ export interface ImageOptions {
11
+ /** Add loading="lazy" attribute (default: true) */
12
+ lazyLoad?: boolean;
13
+ /** Wrap in anchor for lightbox integration (default: false) */
14
+ linkWrapper?: boolean;
15
+ /** Custom class for the image (default: none) */
16
+ className?: string;
17
+ }
18
+ /**
19
+ * Process an image with optional lazy loading and lightbox wrapper.
20
+ *
21
+ * @param data - Image data from the hook
22
+ * @param options - Processing options
23
+ * @returns HTML string for the image
24
+ *
25
+ * @example
26
+ * // Basic usage with lazy loading (default)
27
+ * processImage({ src: 'photo.jpg', alt: 'A photo' })
28
+ * // => <img src="photo.jpg" alt="A photo" loading="lazy">
29
+ *
30
+ * @example
31
+ * // With lightbox wrapper
32
+ * processImage({ src: 'photo.jpg', alt: 'A photo' }, { linkWrapper: true })
33
+ * // => <a href="photo.jpg" data-lightbox><img src="photo.jpg" alt="A photo" loading="lazy"></a>
34
+ *
35
+ * @example
36
+ * // Custom class
37
+ * processImage({ src: 'photo.jpg', alt: 'A photo' }, { className: 'rounded shadow' })
38
+ * // => <img src="photo.jpg" alt="A photo" loading="lazy" class="rounded shadow">
39
+ */
40
+ export declare function processImage(data: ImageData, options?: ImageOptions): string;
41
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/lib/defaults/image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAGnD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAmB5E"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Default image processor with lazy loading and lightbox support.
3
+ *
4
+ * @module lib/defaults/image
5
+ */
6
+ import { escapeHtml } from '../hook-utils';
7
+ /**
8
+ * Process an image with optional lazy loading and lightbox wrapper.
9
+ *
10
+ * @param data - Image data from the hook
11
+ * @param options - Processing options
12
+ * @returns HTML string for the image
13
+ *
14
+ * @example
15
+ * // Basic usage with lazy loading (default)
16
+ * processImage({ src: 'photo.jpg', alt: 'A photo' })
17
+ * // => <img src="photo.jpg" alt="A photo" loading="lazy">
18
+ *
19
+ * @example
20
+ * // With lightbox wrapper
21
+ * processImage({ src: 'photo.jpg', alt: 'A photo' }, { linkWrapper: true })
22
+ * // => <a href="photo.jpg" data-lightbox><img src="photo.jpg" alt="A photo" loading="lazy"></a>
23
+ *
24
+ * @example
25
+ * // Custom class
26
+ * processImage({ src: 'photo.jpg', alt: 'A photo' }, { className: 'rounded shadow' })
27
+ * // => <img src="photo.jpg" alt="A photo" loading="lazy" class="rounded shadow">
28
+ */
29
+ export function processImage(data, options) {
30
+ const { lazyLoad = true, linkWrapper = false, className } = options || {};
31
+ const { src, alt, title } = data;
32
+ const attrs = [
33
+ `src="${escapeHtml(src)}"`,
34
+ `alt="${escapeHtml(alt)}"`,
35
+ title ? `title="${escapeHtml(title)}"` : '',
36
+ lazyLoad ? 'loading="lazy"' : '',
37
+ className ? `class="${escapeHtml(className)}"` : '',
38
+ ].filter(Boolean).join(' ');
39
+ const img = `<img ${attrs}>`;
40
+ if (linkWrapper) {
41
+ return `<a href="${escapeHtml(src)}" data-lightbox>${img}</a>`;
42
+ }
43
+ return img;
44
+ }
45
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../../../src/lib/defaults/image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAc3C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAe,EAAE,OAAsB;IAClE,MAAM,EAAE,QAAQ,GAAG,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAC1E,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAEjC,MAAM,KAAK,GAAG;QACZ,QAAQ,UAAU,CAAC,GAAG,CAAC,GAAG;QAC1B,QAAQ,UAAU,CAAC,GAAG,CAAC,GAAG;QAC1B,KAAK,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC3C,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;QAChC,SAAS,CAAC,CAAC,CAAC,UAAU,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;KACpD,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE5B,MAAM,GAAG,GAAG,QAAQ,KAAK,GAAG,CAAC;IAE7B,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,YAAY,UAAU,CAAC,GAAG,CAAC,mBAAmB,GAAG,MAAM,CAAC;IACjE,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Default link processor with security hardening.
3
+ *
4
+ * @module lib/defaults/link
5
+ */
6
+ import type { LinkData } from '../../types/hooks';
7
+ /**
8
+ * Check if a URL is potentially dangerous.
9
+ *
10
+ * @param href - URL to check
11
+ * @returns true if the URL should be sanitized
12
+ */
13
+ export declare function isDangerousUrl(href: string): boolean;
14
+ /**
15
+ * Check if a URL is external (not anchor or relative).
16
+ *
17
+ * @param href - URL to check
18
+ * @returns true if the URL is external
19
+ */
20
+ export declare function isExternalUrl(href: string): boolean;
21
+ /**
22
+ * Default link processor - sanitizes and adds security attributes.
23
+ *
24
+ * Security measures:
25
+ * - Sanitizes javascript:, vbscript:, and dangerous data: URLs
26
+ * - Adds target="_blank" and rel="noopener noreferrer" to external links
27
+ *
28
+ * @param data - Link data with href, text, and optional title
29
+ * @returns HTML string for the anchor tag
30
+ *
31
+ * @example
32
+ * // Internal link
33
+ * processLink({ href: '/about', text: 'About' });
34
+ * // Returns: '<a href="/about">About</a>'
35
+ *
36
+ * // External link
37
+ * processLink({ href: 'https://example.com', text: 'Example' });
38
+ * // Returns: '<a href="https://example.com" target="_blank" rel="noopener noreferrer">Example</a>'
39
+ *
40
+ * // Dangerous link (sanitized)
41
+ * processLink({ href: 'javascript:alert(1)', text: 'Click' });
42
+ * // Returns: '<a href="#">Click</a>'
43
+ */
44
+ export declare function processLink(data: LinkData): string;
45
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/lib/defaults/link.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAWlD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMpD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAsBlD"}