@humanspeak/svelte-markdown 0.8.12 → 0.8.14
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 +135 -0
- package/dist/Parser.svelte +9 -6
- package/dist/SvelteMarkdown.svelte +14 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/renderers/Image.svelte +91 -2
- package/dist/renderers/Image.svelte.d.ts +2 -0
- package/dist/utils/cache.d.ts +5 -0
- package/dist/utils/cache.js +5 -0
- package/dist/utils/createFilterUtilities.d.ts +52 -0
- package/dist/utils/createFilterUtilities.js +126 -0
- package/dist/utils/parse-and-cache.d.ts +31 -0
- package/dist/utils/parse-and-cache.js +48 -0
- package/dist/utils/rendererKeys.d.ts +1 -1
- package/dist/utils/token-cache.d.ts +178 -0
- package/dist/utils/token-cache.js +238 -0
- package/dist/utils/token-cleanup.js +6 -1
- package/dist/utils/unsupportedHtmlRenderers.d.ts +4 -4
- package/dist/utils/unsupportedHtmlRenderers.js +8 -43
- package/dist/utils/unsupportedRenderers.d.ts +8 -8
- package/dist/utils/unsupportedRenderers.js +11 -48
- package/package.json +44 -35
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Cache
|
|
3
|
+
*
|
|
4
|
+
* Efficient caching layer for parsed markdown tokens.
|
|
5
|
+
* Built on top of the existing MemoryCache infrastructure with
|
|
6
|
+
* specialized features for markdown parsing optimization.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Fast FNV-1a hashing for cache keys
|
|
10
|
+
* - LRU eviction (inherited from MemoryCache)
|
|
11
|
+
* - TTL support (inherited from MemoryCache)
|
|
12
|
+
* - Handles large markdown documents efficiently
|
|
13
|
+
*
|
|
14
|
+
* @module token-cache
|
|
15
|
+
*/
|
|
16
|
+
import type { SvelteMarkdownOptions } from '../types.js';
|
|
17
|
+
import { MemoryCache } from './cache.js';
|
|
18
|
+
import type { Token, TokensList } from './markdown-parser.js';
|
|
19
|
+
/**
|
|
20
|
+
* Fast non-cryptographic hash function using FNV-1a algorithm.
|
|
21
|
+
* Optimized for speed over cryptographic security.
|
|
22
|
+
*
|
|
23
|
+
* FNV-1a (Fowler-Noll-Vo) provides:
|
|
24
|
+
* - Fast computation (single pass through string)
|
|
25
|
+
* - Good distribution (minimal collisions)
|
|
26
|
+
* - Small output size (base36 string)
|
|
27
|
+
*
|
|
28
|
+
* @param str - String to hash
|
|
29
|
+
* @returns Base36 hash string
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const hash1 = hashString('# Hello World')
|
|
34
|
+
* const hash2 = hashString('# Hello World!')
|
|
35
|
+
* console.log(hash1 !== hash2) // true - different content = different hash
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function hashString(str: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Specialized cache for markdown token storage.
|
|
41
|
+
* Extends MemoryCache with markdown-specific convenience methods.
|
|
42
|
+
*
|
|
43
|
+
* Inherits from MemoryCache:
|
|
44
|
+
* - Automatic LRU eviction when maxSize is reached
|
|
45
|
+
* - TTL-based expiration for time-sensitive content
|
|
46
|
+
* - Advanced deletion (deleteByPrefix, deleteByMagicString)
|
|
47
|
+
*
|
|
48
|
+
* Performance characteristics:
|
|
49
|
+
* - Cache hit: <1ms (vs 50-200ms parsing)
|
|
50
|
+
* - Memory: ~5MB for 50 cached documents (default maxSize)
|
|
51
|
+
* - Hash computation: ~0.05ms for 10KB, ~0.5ms for 100KB
|
|
52
|
+
*
|
|
53
|
+
* @class TokenCache
|
|
54
|
+
* @extends MemoryCache<Token[] | TokensList>
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Create cache with custom settings
|
|
59
|
+
* const cache = new TokenCache({
|
|
60
|
+
* maxSize: 100, // Cache up to 100 documents
|
|
61
|
+
* ttl: 5 * 60 * 1000 // Expire after 5 minutes
|
|
62
|
+
* })
|
|
63
|
+
*
|
|
64
|
+
* // Check cache before parsing
|
|
65
|
+
* const cached = cache.getTokens(markdown, options)
|
|
66
|
+
* if (cached) {
|
|
67
|
+
* return cached // Fast path - no parsing needed
|
|
68
|
+
* }
|
|
69
|
+
*
|
|
70
|
+
* // Parse and cache
|
|
71
|
+
* const tokens = lexer.lex(markdown)
|
|
72
|
+
* cache.setTokens(markdown, options, tokens)
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare class TokenCache extends MemoryCache<Token[] | TokensList> {
|
|
76
|
+
/**
|
|
77
|
+
* Creates a new TokenCache instance.
|
|
78
|
+
*
|
|
79
|
+
* @param options - Cache configuration
|
|
80
|
+
* @param options.maxSize - Maximum number of documents to cache (default: 50)
|
|
81
|
+
* @param options.ttl - Time-to-live in milliseconds (default: 5 minutes)
|
|
82
|
+
*/
|
|
83
|
+
constructor(options?: {
|
|
84
|
+
maxSize?: number;
|
|
85
|
+
ttl?: number;
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves cached tokens for given markdown source and options.
|
|
89
|
+
* Returns undefined if not cached or expired.
|
|
90
|
+
*
|
|
91
|
+
* @param source - Raw markdown string
|
|
92
|
+
* @param options - Svelte markdown parser options
|
|
93
|
+
* @returns Cached tokens or undefined
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const tokens = cache.getTokens('# Hello', { gfm: true })
|
|
98
|
+
* if (tokens) {
|
|
99
|
+
* console.log('Cache hit!')
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
getTokens(source: string, options: SvelteMarkdownOptions): Token[] | TokensList | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Stores parsed tokens in cache for given markdown source and options.
|
|
106
|
+
* If cache is full, oldest entry is evicted (LRU).
|
|
107
|
+
*
|
|
108
|
+
* @param source - Raw markdown string
|
|
109
|
+
* @param options - Svelte markdown parser options
|
|
110
|
+
* @param tokens - Parsed token array or token list
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const tokens = lexer.lex(markdown)
|
|
115
|
+
* cache.setTokens(markdown, options, tokens)
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
setTokens(source: string, options: SvelteMarkdownOptions, tokens: Token[] | TokensList): void;
|
|
119
|
+
/**
|
|
120
|
+
* Checks if tokens are cached without retrieving them.
|
|
121
|
+
* Useful for cache statistics or conditional logic.
|
|
122
|
+
*
|
|
123
|
+
* @param source - Raw markdown string
|
|
124
|
+
* @param options - Svelte markdown parser options
|
|
125
|
+
* @returns True if cached and not expired
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* if (cache.hasTokens(markdown, options)) {
|
|
130
|
+
* console.log('Cache hit - no parsing needed')
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
hasTokens(source: string, options: SvelteMarkdownOptions): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Removes cached tokens for specific source and options.
|
|
137
|
+
*
|
|
138
|
+
* @param source - Raw markdown string
|
|
139
|
+
* @param options - Svelte markdown parser options
|
|
140
|
+
* @returns True if entry was removed, false if not found
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* cache.deleteTokens(markdown, options) // Remove specific cached entry
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
deleteTokens(source: string, options: SvelteMarkdownOptions): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Removes all cached tokens from the cache.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* cache.clearAllTokens() // Clear entire cache
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
clearAllTokens(): void;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Global singleton instance for shared token caching.
|
|
160
|
+
* Use this instance across your application for maximum cache efficiency.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* import { tokenCache } from './token-cache.js'
|
|
165
|
+
*
|
|
166
|
+
* const cached = tokenCache.getTokens(markdown, options)
|
|
167
|
+
* if (!cached) {
|
|
168
|
+
* const tokens = lexer.lex(markdown)
|
|
169
|
+
* tokenCache.setTokens(markdown, options, tokens)
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export declare const tokenCache: TokenCache;
|
|
174
|
+
/**
|
|
175
|
+
* Export hash function for testing purposes.
|
|
176
|
+
* @internal
|
|
177
|
+
*/
|
|
178
|
+
export { hashString };
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Cache
|
|
3
|
+
*
|
|
4
|
+
* Efficient caching layer for parsed markdown tokens.
|
|
5
|
+
* Built on top of the existing MemoryCache infrastructure with
|
|
6
|
+
* specialized features for markdown parsing optimization.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Fast FNV-1a hashing for cache keys
|
|
10
|
+
* - LRU eviction (inherited from MemoryCache)
|
|
11
|
+
* - TTL support (inherited from MemoryCache)
|
|
12
|
+
* - Handles large markdown documents efficiently
|
|
13
|
+
*
|
|
14
|
+
* @module token-cache
|
|
15
|
+
*/
|
|
16
|
+
import { MemoryCache } from './cache.js';
|
|
17
|
+
/**
|
|
18
|
+
* Fast non-cryptographic hash function using FNV-1a algorithm.
|
|
19
|
+
* Optimized for speed over cryptographic security.
|
|
20
|
+
*
|
|
21
|
+
* FNV-1a (Fowler-Noll-Vo) provides:
|
|
22
|
+
* - Fast computation (single pass through string)
|
|
23
|
+
* - Good distribution (minimal collisions)
|
|
24
|
+
* - Small output size (base36 string)
|
|
25
|
+
*
|
|
26
|
+
* @param str - String to hash
|
|
27
|
+
* @returns Base36 hash string
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const hash1 = hashString('# Hello World')
|
|
32
|
+
* const hash2 = hashString('# Hello World!')
|
|
33
|
+
* console.log(hash1 !== hash2) // true - different content = different hash
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
function hashString(str) {
|
|
37
|
+
let hash = 2166136261; // FNV offset basis (32-bit)
|
|
38
|
+
for (let i = 0; i < str.length; i++) {
|
|
39
|
+
hash ^= str.charCodeAt(i);
|
|
40
|
+
// FNV prime multiply using bit shifts (faster than multiplication)
|
|
41
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
42
|
+
}
|
|
43
|
+
// Convert to unsigned 32-bit integer and base36 string
|
|
44
|
+
return (hash >>> 0).toString(36);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Generates a cache key from markdown source and parser options.
|
|
48
|
+
* Combines hashes of both source content and options to ensure
|
|
49
|
+
* different parsing configurations are cached separately.
|
|
50
|
+
*
|
|
51
|
+
* Handles non-serializable options (extensions, tokenizer, hooks, etc.) by:
|
|
52
|
+
* - Serializing functions by name/toString for stable keys
|
|
53
|
+
* - Detecting and handling circular references
|
|
54
|
+
* - Including ALL options that affect parsing
|
|
55
|
+
*
|
|
56
|
+
* @param source - Raw markdown string
|
|
57
|
+
* @param options - Svelte markdown parser options
|
|
58
|
+
* @returns Composite cache key
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const key1 = getCacheKey('# Test', { gfm: true })
|
|
63
|
+
* const key2 = getCacheKey('# Test', { gfm: false })
|
|
64
|
+
* console.log(key1 !== key2) // true - different options = different key
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
function getCacheKey(source, options) {
|
|
68
|
+
const sourceHash = hashString(source);
|
|
69
|
+
// Safely serialize all options including functions and objects
|
|
70
|
+
const seen = new WeakSet();
|
|
71
|
+
const optionsHash = hashString(JSON.stringify(options, (_, value) => {
|
|
72
|
+
// Serialize functions by their name or source code
|
|
73
|
+
if (typeof value === 'function') {
|
|
74
|
+
return value.name || value.toString();
|
|
75
|
+
}
|
|
76
|
+
// Handle circular references
|
|
77
|
+
if (value && typeof value === 'object') {
|
|
78
|
+
if (seen.has(value))
|
|
79
|
+
return '[Circular]';
|
|
80
|
+
seen.add(value);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}));
|
|
84
|
+
return `${sourceHash}:${optionsHash}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Specialized cache for markdown token storage.
|
|
88
|
+
* Extends MemoryCache with markdown-specific convenience methods.
|
|
89
|
+
*
|
|
90
|
+
* Inherits from MemoryCache:
|
|
91
|
+
* - Automatic LRU eviction when maxSize is reached
|
|
92
|
+
* - TTL-based expiration for time-sensitive content
|
|
93
|
+
* - Advanced deletion (deleteByPrefix, deleteByMagicString)
|
|
94
|
+
*
|
|
95
|
+
* Performance characteristics:
|
|
96
|
+
* - Cache hit: <1ms (vs 50-200ms parsing)
|
|
97
|
+
* - Memory: ~5MB for 50 cached documents (default maxSize)
|
|
98
|
+
* - Hash computation: ~0.05ms for 10KB, ~0.5ms for 100KB
|
|
99
|
+
*
|
|
100
|
+
* @class TokenCache
|
|
101
|
+
* @extends MemoryCache<Token[] | TokensList>
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* // Create cache with custom settings
|
|
106
|
+
* const cache = new TokenCache({
|
|
107
|
+
* maxSize: 100, // Cache up to 100 documents
|
|
108
|
+
* ttl: 5 * 60 * 1000 // Expire after 5 minutes
|
|
109
|
+
* })
|
|
110
|
+
*
|
|
111
|
+
* // Check cache before parsing
|
|
112
|
+
* const cached = cache.getTokens(markdown, options)
|
|
113
|
+
* if (cached) {
|
|
114
|
+
* return cached // Fast path - no parsing needed
|
|
115
|
+
* }
|
|
116
|
+
*
|
|
117
|
+
* // Parse and cache
|
|
118
|
+
* const tokens = lexer.lex(markdown)
|
|
119
|
+
* cache.setTokens(markdown, options, tokens)
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export class TokenCache extends MemoryCache {
|
|
123
|
+
/**
|
|
124
|
+
* Creates a new TokenCache instance.
|
|
125
|
+
*
|
|
126
|
+
* @param options - Cache configuration
|
|
127
|
+
* @param options.maxSize - Maximum number of documents to cache (default: 50)
|
|
128
|
+
* @param options.ttl - Time-to-live in milliseconds (default: 5 minutes)
|
|
129
|
+
*/
|
|
130
|
+
constructor(options) {
|
|
131
|
+
super({ maxSize: 50, ttl: 5 * 60 * 1000, ...options });
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Retrieves cached tokens for given markdown source and options.
|
|
135
|
+
* Returns undefined if not cached or expired.
|
|
136
|
+
*
|
|
137
|
+
* @param source - Raw markdown string
|
|
138
|
+
* @param options - Svelte markdown parser options
|
|
139
|
+
* @returns Cached tokens or undefined
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const tokens = cache.getTokens('# Hello', { gfm: true })
|
|
144
|
+
* if (tokens) {
|
|
145
|
+
* console.log('Cache hit!')
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
getTokens(source, options) {
|
|
150
|
+
const key = getCacheKey(source, options);
|
|
151
|
+
return this.get(key);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Stores parsed tokens in cache for given markdown source and options.
|
|
155
|
+
* If cache is full, oldest entry is evicted (LRU).
|
|
156
|
+
*
|
|
157
|
+
* @param source - Raw markdown string
|
|
158
|
+
* @param options - Svelte markdown parser options
|
|
159
|
+
* @param tokens - Parsed token array or token list
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const tokens = lexer.lex(markdown)
|
|
164
|
+
* cache.setTokens(markdown, options, tokens)
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
setTokens(source, options, tokens) {
|
|
168
|
+
const key = getCacheKey(source, options);
|
|
169
|
+
this.set(key, tokens);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Checks if tokens are cached without retrieving them.
|
|
173
|
+
* Useful for cache statistics or conditional logic.
|
|
174
|
+
*
|
|
175
|
+
* @param source - Raw markdown string
|
|
176
|
+
* @param options - Svelte markdown parser options
|
|
177
|
+
* @returns True if cached and not expired
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* if (cache.hasTokens(markdown, options)) {
|
|
182
|
+
* console.log('Cache hit - no parsing needed')
|
|
183
|
+
* }
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
hasTokens(source, options) {
|
|
187
|
+
const key = getCacheKey(source, options);
|
|
188
|
+
return this.has(key);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Removes cached tokens for specific source and options.
|
|
192
|
+
*
|
|
193
|
+
* @param source - Raw markdown string
|
|
194
|
+
* @param options - Svelte markdown parser options
|
|
195
|
+
* @returns True if entry was removed, false if not found
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* cache.deleteTokens(markdown, options) // Remove specific cached entry
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
deleteTokens(source, options) {
|
|
203
|
+
const key = getCacheKey(source, options);
|
|
204
|
+
return this.delete(key);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Removes all cached tokens from the cache.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* cache.clearAllTokens() // Clear entire cache
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
clearAllTokens() {
|
|
215
|
+
this.clear();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Global singleton instance for shared token caching.
|
|
220
|
+
* Use this instance across your application for maximum cache efficiency.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* import { tokenCache } from './token-cache.js'
|
|
225
|
+
*
|
|
226
|
+
* const cached = tokenCache.getTokens(markdown, options)
|
|
227
|
+
* if (!cached) {
|
|
228
|
+
* const tokens = lexer.lex(markdown)
|
|
229
|
+
* tokenCache.setTokens(markdown, options, tokens)
|
|
230
|
+
* }
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
export const tokenCache = new TokenCache();
|
|
234
|
+
/**
|
|
235
|
+
* Export hash function for testing purposes.
|
|
236
|
+
* @internal
|
|
237
|
+
*/
|
|
238
|
+
export { hashString };
|
|
@@ -273,7 +273,12 @@ export const containsMultipleTags = (html) => {
|
|
|
273
273
|
export const shrinkHtmlTokens = (tokens) => {
|
|
274
274
|
const result = [];
|
|
275
275
|
for (const token of tokens) {
|
|
276
|
-
if (token
|
|
276
|
+
if ('tokens' in token && Array.isArray(token.tokens)) {
|
|
277
|
+
const t = token;
|
|
278
|
+
t.tokens = shrinkHtmlTokens(t.tokens);
|
|
279
|
+
result.push(token);
|
|
280
|
+
}
|
|
281
|
+
else if (token.type === 'list') {
|
|
277
282
|
token.items = token.items.map((item, index) => ({
|
|
278
283
|
...item,
|
|
279
284
|
listItemIndex: index,
|
|
@@ -19,7 +19,7 @@ export declare const buildUnsupportedHTML: () => HtmlRenderers;
|
|
|
19
19
|
* Produces an HTML renderer map that allows only the specified tags.
|
|
20
20
|
* All non‑listed tags are set to `UnsupportedHTML`.
|
|
21
21
|
*
|
|
22
|
-
* Each entry can be either a tag name (to use the library
|
|
22
|
+
* Each entry can be either a tag name (to use the library's default component for that tag),
|
|
23
23
|
* or a tuple `[tag, component]` to specify a custom component for that tag.
|
|
24
24
|
*
|
|
25
25
|
* @function allowHtmlOnly
|
|
@@ -35,11 +35,11 @@ export declare const buildUnsupportedHTML: () => HtmlRenderers;
|
|
|
35
35
|
* // Allow a custom component for div while allowing the default for a
|
|
36
36
|
* const html = allowHtmlOnly([['div', MyDiv], 'a'])
|
|
37
37
|
*/
|
|
38
|
-
export declare const allowHtmlOnly: (
|
|
38
|
+
export declare const allowHtmlOnly: (_allowed: Array<HtmlKey | [HtmlKey, Component | null]>) => HtmlRenderers;
|
|
39
39
|
/**
|
|
40
40
|
* Produces an HTML renderer map that excludes only the specified tags.
|
|
41
41
|
* Excluded tags are mapped to `UnsupportedHTML`, while all other tags use the
|
|
42
|
-
* library
|
|
42
|
+
* library's default components. Optionally, you can override specific non‑excluded
|
|
43
43
|
* tags with custom components using `[tag, component]` tuples.
|
|
44
44
|
*
|
|
45
45
|
* Exclusions take precedence over overrides. If a tag is listed in `excluded`, an
|
|
@@ -59,4 +59,4 @@ export declare const allowHtmlOnly: (allowed: Array<HtmlKey | [HtmlKey, Componen
|
|
|
59
59
|
* // Disable span; override 'a' to CustomA component
|
|
60
60
|
* const html = excludeHtmlOnly(['span'], [['a', CustomA]])
|
|
61
61
|
*/
|
|
62
|
-
export declare const excludeHtmlOnly: (
|
|
62
|
+
export declare const excludeHtmlOnly: (_excluded: HtmlKey[], _overrides?: Array<[HtmlKey, Component | null]>) => HtmlRenderers;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import Html, { UnsupportedHTML } from '../renderers/html/index.js';
|
|
2
2
|
import { htmlRendererKeysInternal } from './rendererKeys.js';
|
|
3
|
+
import { createFilterUtilities } from './createFilterUtilities.js';
|
|
4
|
+
// Create filter utilities using the generic factory
|
|
5
|
+
const filterUtils = createFilterUtilities(htmlRendererKeysInternal, UnsupportedHTML, Html);
|
|
3
6
|
/**
|
|
4
7
|
* Builds a map of HTML renderers where every known HTML tag is mapped to `UnsupportedHTML`.
|
|
5
8
|
* This is useful when you want to disable all built‑in HTML rendering and provide
|
|
@@ -13,18 +16,12 @@ import { htmlRendererKeysInternal } from './rendererKeys.js';
|
|
|
13
16
|
* html: buildUnsupportedHTML()
|
|
14
17
|
* }
|
|
15
18
|
*/
|
|
16
|
-
export const buildUnsupportedHTML =
|
|
17
|
-
const result = {};
|
|
18
|
-
for (const key of htmlRendererKeysInternal) {
|
|
19
|
-
result[key] = UnsupportedHTML;
|
|
20
|
-
}
|
|
21
|
-
return result;
|
|
22
|
-
};
|
|
19
|
+
export const buildUnsupportedHTML = filterUtils.buildUnsupported;
|
|
23
20
|
/**
|
|
24
21
|
* Produces an HTML renderer map that allows only the specified tags.
|
|
25
22
|
* All non‑listed tags are set to `UnsupportedHTML`.
|
|
26
23
|
*
|
|
27
|
-
* Each entry can be either a tag name (to use the library
|
|
24
|
+
* Each entry can be either a tag name (to use the library's default component for that tag),
|
|
28
25
|
* or a tuple `[tag, component]` to specify a custom component for that tag.
|
|
29
26
|
*
|
|
30
27
|
* @function allowHtmlOnly
|
|
@@ -40,27 +37,11 @@ export const buildUnsupportedHTML = () => {
|
|
|
40
37
|
* // Allow a custom component for div while allowing the default for a
|
|
41
38
|
* const html = allowHtmlOnly([['div', MyDiv], 'a'])
|
|
42
39
|
*/
|
|
43
|
-
export const allowHtmlOnly =
|
|
44
|
-
const result = buildUnsupportedHTML();
|
|
45
|
-
for (const entry of allowed) {
|
|
46
|
-
if (Array.isArray(entry)) {
|
|
47
|
-
const [tag, component] = entry;
|
|
48
|
-
// Only set if the tag exists in our Html map
|
|
49
|
-
if (tag in Html)
|
|
50
|
-
result[tag] = component;
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
const tag = entry;
|
|
54
|
-
if (tag in Html)
|
|
55
|
-
result[tag] = Html[tag];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
};
|
|
40
|
+
export const allowHtmlOnly = filterUtils.allowOnly;
|
|
60
41
|
/**
|
|
61
42
|
* Produces an HTML renderer map that excludes only the specified tags.
|
|
62
43
|
* Excluded tags are mapped to `UnsupportedHTML`, while all other tags use the
|
|
63
|
-
* library
|
|
44
|
+
* library's default components. Optionally, you can override specific non‑excluded
|
|
64
45
|
* tags with custom components using `[tag, component]` tuples.
|
|
65
46
|
*
|
|
66
47
|
* Exclusions take precedence over overrides. If a tag is listed in `excluded`, an
|
|
@@ -80,20 +61,4 @@ export const allowHtmlOnly = (allowed) => {
|
|
|
80
61
|
* // Disable span; override 'a' to CustomA component
|
|
81
62
|
* const html = excludeHtmlOnly(['span'], [['a', CustomA]])
|
|
82
63
|
*/
|
|
83
|
-
export const excludeHtmlOnly =
|
|
84
|
-
const result = { ...Html };
|
|
85
|
-
for (const tag of excluded) {
|
|
86
|
-
if (tag in Html)
|
|
87
|
-
result[tag] = UnsupportedHTML;
|
|
88
|
-
}
|
|
89
|
-
if (overrides) {
|
|
90
|
-
for (const [tag, component] of overrides) {
|
|
91
|
-
// Exclusions take precedence; do not override excluded tags
|
|
92
|
-
if (excluded.includes(tag))
|
|
93
|
-
continue;
|
|
94
|
-
if (tag in Html)
|
|
95
|
-
result[tag] = component;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return result;
|
|
99
|
-
};
|
|
64
|
+
export const excludeHtmlOnly = filterUtils.excludeOnly;
|
|
@@ -5,7 +5,7 @@ import { type RendererKey } from './rendererKeys.js';
|
|
|
5
5
|
* is set to the `Unsupported` component.
|
|
6
6
|
*
|
|
7
7
|
* @function buildUnsupportedRenderers
|
|
8
|
-
* @returns {
|
|
8
|
+
* @returns {Omit<Renderers, 'html'>} A map with all non‑HTML renderers set to `Unsupported`.
|
|
9
9
|
* @example
|
|
10
10
|
* import { buildUnsupportedRenderers } from '@humanspeak/svelte-markdown'
|
|
11
11
|
* const renderers = {
|
|
@@ -13,17 +13,17 @@ import { type RendererKey } from './rendererKeys.js';
|
|
|
13
13
|
* html: {} // customize HTML separately
|
|
14
14
|
* }
|
|
15
15
|
*/
|
|
16
|
-
export declare const buildUnsupportedRenderers: () =>
|
|
16
|
+
export declare const buildUnsupportedRenderers: () => Omit<Renderers, "html">;
|
|
17
17
|
/**
|
|
18
18
|
* Produces a renderer map that allows only the specified markdown renderers (excluding `html`).
|
|
19
19
|
* All non‑listed renderer keys are set to `Unsupported`.
|
|
20
|
-
* Each entry can be either a renderer key (to use the library
|
|
20
|
+
* Each entry can be either a renderer key (to use the library's default component),
|
|
21
21
|
* or a tuple `[key, component]` to specify a custom component for that key.
|
|
22
22
|
*
|
|
23
23
|
* @function allowRenderersOnly
|
|
24
24
|
* @param {Array<RendererKey | [RendererKey, RendererComponent]>} allowed
|
|
25
25
|
* Renderer keys to allow, or tuples for custom component overrides.
|
|
26
|
-
* @returns {
|
|
26
|
+
* @returns {Omit<Renderers, 'html'>} A renderer map with only the provided keys enabled.
|
|
27
27
|
* @example
|
|
28
28
|
* // Allow only paragraph and link with defaults
|
|
29
29
|
* const renderers = allowRenderersOnly(['paragraph', 'link'])
|
|
@@ -32,10 +32,10 @@ export declare const buildUnsupportedRenderers: () => Partial<Renderers>;
|
|
|
32
32
|
* // Allow paragraph with a custom component
|
|
33
33
|
* const renderers = allowRenderersOnly([['paragraph', MyParagraph]])
|
|
34
34
|
*/
|
|
35
|
-
export declare const allowRenderersOnly: (
|
|
35
|
+
export declare const allowRenderersOnly: (_allowed: Array<RendererKey | [RendererKey, RendererComponent]>) => Omit<Renderers, "html">;
|
|
36
36
|
/**
|
|
37
37
|
* Produces a renderer map that excludes only the specified markdown renderer keys (excluding `html`).
|
|
38
|
-
* Excluded keys are mapped to `Unsupported`, while all other keys use the library
|
|
38
|
+
* Excluded keys are mapped to `Unsupported`, while all other keys use the library's default components.
|
|
39
39
|
* Optionally override specific non‑excluded keys with custom components via `[key, component]` tuples.
|
|
40
40
|
*
|
|
41
41
|
* Exclusions take precedence over overrides.
|
|
@@ -45,7 +45,7 @@ export declare const allowRenderersOnly: (allowed: Array<RendererKey | [Renderer
|
|
|
45
45
|
* Renderer keys to exclude (set to `Unsupported`).
|
|
46
46
|
* @param {Array<[RendererKey, RendererComponent]>} [overrides]
|
|
47
47
|
* Optional tuples mapping non‑excluded keys to custom components.
|
|
48
|
-
* @returns {
|
|
48
|
+
* @returns {Omit<Renderers, 'html'>} A renderer map with only the provided keys excluded.
|
|
49
49
|
* @example
|
|
50
50
|
* // Disable just paragraph and link, keep others as defaults
|
|
51
51
|
* const renderers = excludeRenderersOnly(['paragraph', 'link'])
|
|
@@ -54,4 +54,4 @@ export declare const allowRenderersOnly: (allowed: Array<RendererKey | [Renderer
|
|
|
54
54
|
* // Disable link; override paragraph to a custom component
|
|
55
55
|
* const renderers = excludeRenderersOnly(['link'], [['paragraph', MyParagraph]])
|
|
56
56
|
*/
|
|
57
|
-
export declare const excludeRenderersOnly: (
|
|
57
|
+
export declare const excludeRenderersOnly: (_excluded: RendererKey[], _overrides?: Array<[RendererKey, RendererComponent]>) => Omit<Renderers, "html">;
|