@changerawr/markdown 1.1.4 → 1.1.6
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 +94 -9
- package/dist/css/index.css +3 -123
- package/dist/index.d.mts +130 -3
- package/dist/index.d.ts +130 -3
- package/dist/index.js +321 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +318 -31
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +56 -2
- package/dist/react/index.d.ts +56 -2
- package/dist/react/index.js +297 -30
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +297 -30
- package/dist/react/index.mjs.map +1 -1
- package/dist/standalone.browser.js +323 -33
- package/dist/standalone.d.mts +56 -2
- package/dist/standalone.d.ts +56 -2
- package/dist/standalone.js +297 -30
- package/dist/standalone.js.map +1 -1
- package/dist/standalone.mjs +297 -30
- package/dist/standalone.mjs.map +1 -1
- package/dist/tailwind/index.d.mts +4 -35
- package/dist/tailwind/index.d.ts +4 -35
- package/dist/tailwind/index.js +120 -185
- package/dist/tailwind/index.js.map +1 -1
- package/dist/tailwind/index.mjs +119 -183
- package/dist/tailwind/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
ImageExtension: () => ImageExtension,
|
|
44
44
|
InlineCodeExtension: () => InlineCodeExtension,
|
|
45
45
|
ItalicExtension: () => ItalicExtension,
|
|
46
|
+
LRUCache: () => LRUCache,
|
|
46
47
|
LineBreakExtension: () => LineBreakExtension,
|
|
47
48
|
LinkExtension: () => LinkExtension,
|
|
48
49
|
ListExtension: () => ListExtension,
|
|
@@ -75,10 +76,12 @@ __export(index_exports, {
|
|
|
75
76
|
generateId: () => generateId,
|
|
76
77
|
getASTStats: () => getASTStats,
|
|
77
78
|
getTokenStats: () => getTokenStats,
|
|
79
|
+
hashContent: () => hashContent,
|
|
78
80
|
isBrowser: () => isBrowser,
|
|
79
81
|
isNode: () => isNode,
|
|
80
82
|
isValidUrl: () => isValidUrl,
|
|
81
83
|
markdown: () => markdown2,
|
|
84
|
+
memoize: () => memoize,
|
|
82
85
|
minimalClasses: () => minimalClasses,
|
|
83
86
|
parseASTFromJSON: () => parseASTFromJSON,
|
|
84
87
|
parseCum: () => parseCum,
|
|
@@ -108,9 +111,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
108
111
|
|
|
109
112
|
// src/parser.ts
|
|
110
113
|
var MarkdownParser = class {
|
|
114
|
+
// Cache compiled regexes
|
|
111
115
|
constructor(config) {
|
|
112
116
|
this.rules = [];
|
|
113
117
|
this.warnings = [];
|
|
118
|
+
this.compiledPatterns = /* @__PURE__ */ new Map();
|
|
114
119
|
this.config = {
|
|
115
120
|
debugMode: false,
|
|
116
121
|
maxIterations: 1e4,
|
|
@@ -120,6 +125,10 @@ var MarkdownParser = class {
|
|
|
120
125
|
}
|
|
121
126
|
addRule(rule) {
|
|
122
127
|
this.rules.push(rule);
|
|
128
|
+
this.compiledPatterns.set(
|
|
129
|
+
rule,
|
|
130
|
+
new RegExp(rule.pattern.source, rule.pattern.flags.replace("g", ""))
|
|
131
|
+
);
|
|
123
132
|
this.rules.sort((a, b) => {
|
|
124
133
|
const aFeatureExtension = ["alert", "button", "embed"].includes(a.name);
|
|
125
134
|
const bFeatureExtension = ["alert", "button", "embed"].includes(b.name);
|
|
@@ -165,12 +174,20 @@ var MarkdownParser = class {
|
|
|
165
174
|
iterationCount++;
|
|
166
175
|
let matched = false;
|
|
167
176
|
let bestMatch = null;
|
|
177
|
+
let nextBestMatchIndex = null;
|
|
168
178
|
for (const rule of this.rules) {
|
|
169
179
|
try {
|
|
170
|
-
const pattern =
|
|
180
|
+
const pattern = this.compiledPatterns.get(rule);
|
|
171
181
|
const match = remaining.match(pattern);
|
|
172
182
|
if (match && match.index !== void 0) {
|
|
173
|
-
|
|
183
|
+
if (match.index === 0) {
|
|
184
|
+
bestMatch = { rule, match, priority: 1e3 };
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (nextBestMatchIndex === null || match.index < nextBestMatchIndex) {
|
|
188
|
+
nextBestMatchIndex = match.index;
|
|
189
|
+
}
|
|
190
|
+
const priority = 1e3 - match.index;
|
|
174
191
|
if (!bestMatch || priority > bestMatch.priority || priority === bestMatch.priority && match.index < (bestMatch.match.index || 0)) {
|
|
175
192
|
bestMatch = { rule, match, priority };
|
|
176
193
|
}
|
|
@@ -217,15 +234,14 @@ var MarkdownParser = class {
|
|
|
217
234
|
}
|
|
218
235
|
}
|
|
219
236
|
if (!matched) {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
237
|
+
const chunkSize = nextBestMatchIndex !== null ? nextBestMatchIndex : Math.min(remaining.length, 1e3);
|
|
238
|
+
const textChunk = remaining.slice(0, chunkSize);
|
|
239
|
+
tokens.push({
|
|
240
|
+
type: "text",
|
|
241
|
+
content: textChunk,
|
|
242
|
+
raw: textChunk
|
|
243
|
+
});
|
|
244
|
+
remaining = remaining.slice(chunkSize);
|
|
229
245
|
}
|
|
230
246
|
}
|
|
231
247
|
if (iterationCount >= maxIterations) {
|
|
@@ -305,7 +321,7 @@ var MarkdownParser = class {
|
|
|
305
321
|
return processed;
|
|
306
322
|
}
|
|
307
323
|
recursivelyParseBlockContent(token) {
|
|
308
|
-
const blockTypes = ["alert", "blockquote"];
|
|
324
|
+
const blockTypes = ["alert", "blockquote", "list-item", "task-item"];
|
|
309
325
|
if (blockTypes.includes(token.type) && token.content && token.content.trim()) {
|
|
310
326
|
const children = this.parse(token.content);
|
|
311
327
|
return {
|
|
@@ -723,6 +739,171 @@ var MarkdownRenderer = class {
|
|
|
723
739
|
}
|
|
724
740
|
};
|
|
725
741
|
|
|
742
|
+
// src/cache.ts
|
|
743
|
+
var LRUCache = class {
|
|
744
|
+
constructor(capacity = 100) {
|
|
745
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
746
|
+
this.hits = 0;
|
|
747
|
+
this.misses = 0;
|
|
748
|
+
this.evictions = 0;
|
|
749
|
+
if (capacity <= 0) {
|
|
750
|
+
throw new Error("Cache capacity must be greater than 0");
|
|
751
|
+
}
|
|
752
|
+
this.capacity = capacity;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Get a value from the cache
|
|
756
|
+
*/
|
|
757
|
+
get(key) {
|
|
758
|
+
const entry = this.cache.get(key);
|
|
759
|
+
if (entry) {
|
|
760
|
+
entry.timestamp = Date.now();
|
|
761
|
+
entry.accessCount++;
|
|
762
|
+
this.hits++;
|
|
763
|
+
this.cache.delete(key);
|
|
764
|
+
this.cache.set(key, entry);
|
|
765
|
+
return entry.value;
|
|
766
|
+
}
|
|
767
|
+
this.misses++;
|
|
768
|
+
return void 0;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Set a value in the cache
|
|
772
|
+
*/
|
|
773
|
+
set(key, value) {
|
|
774
|
+
if (this.cache.has(key)) {
|
|
775
|
+
this.cache.delete(key);
|
|
776
|
+
} else if (this.cache.size >= this.capacity) {
|
|
777
|
+
this.evictLRU();
|
|
778
|
+
}
|
|
779
|
+
this.cache.set(key, {
|
|
780
|
+
value,
|
|
781
|
+
timestamp: Date.now(),
|
|
782
|
+
accessCount: 0
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Check if a key exists in the cache
|
|
787
|
+
*/
|
|
788
|
+
has(key) {
|
|
789
|
+
return this.cache.has(key);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Delete a specific key from the cache
|
|
793
|
+
*/
|
|
794
|
+
delete(key) {
|
|
795
|
+
return this.cache.delete(key);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Clear all entries from the cache
|
|
799
|
+
*/
|
|
800
|
+
clear() {
|
|
801
|
+
this.cache.clear();
|
|
802
|
+
this.hits = 0;
|
|
803
|
+
this.misses = 0;
|
|
804
|
+
this.evictions = 0;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Get the current size of the cache
|
|
808
|
+
*/
|
|
809
|
+
get size() {
|
|
810
|
+
return this.cache.size;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Get cache statistics
|
|
814
|
+
*/
|
|
815
|
+
getStats() {
|
|
816
|
+
const totalRequests = this.hits + this.misses;
|
|
817
|
+
return {
|
|
818
|
+
size: this.cache.size,
|
|
819
|
+
capacity: this.capacity,
|
|
820
|
+
hits: this.hits,
|
|
821
|
+
misses: this.misses,
|
|
822
|
+
hitRate: totalRequests > 0 ? this.hits / totalRequests : 0,
|
|
823
|
+
evictions: this.evictions
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Reset cache statistics
|
|
828
|
+
*/
|
|
829
|
+
resetStats() {
|
|
830
|
+
this.hits = 0;
|
|
831
|
+
this.misses = 0;
|
|
832
|
+
this.evictions = 0;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Get all keys in the cache
|
|
836
|
+
*/
|
|
837
|
+
keys() {
|
|
838
|
+
return Array.from(this.cache.keys());
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Get all values in the cache
|
|
842
|
+
*/
|
|
843
|
+
values() {
|
|
844
|
+
return Array.from(this.cache.values()).map((entry) => entry.value);
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Update cache capacity and evict if necessary
|
|
848
|
+
*/
|
|
849
|
+
setCapacity(newCapacity) {
|
|
850
|
+
if (newCapacity <= 0) {
|
|
851
|
+
throw new Error("Cache capacity must be greater than 0");
|
|
852
|
+
}
|
|
853
|
+
this.capacity = newCapacity;
|
|
854
|
+
while (this.cache.size > this.capacity) {
|
|
855
|
+
this.evictLRU();
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Evict the least recently used entry
|
|
860
|
+
*/
|
|
861
|
+
evictLRU() {
|
|
862
|
+
const firstKey = this.cache.keys().next().value;
|
|
863
|
+
if (firstKey !== void 0) {
|
|
864
|
+
this.cache.delete(firstKey);
|
|
865
|
+
this.evictions++;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
function hashContent(content) {
|
|
870
|
+
if (content.length > 1e4) {
|
|
871
|
+
const start = content.slice(0, 1e3);
|
|
872
|
+
const middle = content.slice(Math.floor(content.length / 2) - 500, Math.floor(content.length / 2) + 500);
|
|
873
|
+
const end = content.slice(-1e3);
|
|
874
|
+
const sample = content.length + "|" + start + middle + end;
|
|
875
|
+
let hash2 = 2166136261;
|
|
876
|
+
for (let i = 0; i < sample.length; i++) {
|
|
877
|
+
hash2 ^= sample.charCodeAt(i);
|
|
878
|
+
hash2 += (hash2 << 1) + (hash2 << 4) + (hash2 << 7) + (hash2 << 8) + (hash2 << 24);
|
|
879
|
+
}
|
|
880
|
+
return (hash2 >>> 0).toString(36);
|
|
881
|
+
}
|
|
882
|
+
let hash = 2166136261;
|
|
883
|
+
for (let i = 0; i < content.length; i++) {
|
|
884
|
+
hash ^= content.charCodeAt(i);
|
|
885
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
886
|
+
}
|
|
887
|
+
return (hash >>> 0).toString(36);
|
|
888
|
+
}
|
|
889
|
+
function memoize(fn, options = {}) {
|
|
890
|
+
const cache = options.cache || new LRUCache(options.maxSize || 100);
|
|
891
|
+
const keyGenerator = options.keyGenerator || ((...args) => JSON.stringify(args));
|
|
892
|
+
const memoized = function(...args) {
|
|
893
|
+
const key = keyGenerator(...args);
|
|
894
|
+
const cached = cache.get(key);
|
|
895
|
+
if (cached !== void 0) {
|
|
896
|
+
return cached;
|
|
897
|
+
}
|
|
898
|
+
const result = fn.apply(this, args);
|
|
899
|
+
cache.set(key, result);
|
|
900
|
+
return result;
|
|
901
|
+
};
|
|
902
|
+
memoized.cache = cache;
|
|
903
|
+
memoized.clearCache = () => cache.clear();
|
|
904
|
+
return memoized;
|
|
905
|
+
}
|
|
906
|
+
|
|
726
907
|
// src/extensions/core/blockquote.ts
|
|
727
908
|
var BlockquoteExtension = {
|
|
728
909
|
name: "blockquote",
|
|
@@ -1096,7 +1277,14 @@ var ListExtension = {
|
|
|
1096
1277
|
renderRules: [
|
|
1097
1278
|
{
|
|
1098
1279
|
type: "list-item",
|
|
1099
|
-
render: (token) =>
|
|
1280
|
+
render: (token) => {
|
|
1281
|
+
const format = token.attributes?.format || "tailwind";
|
|
1282
|
+
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1283
|
+
if (format === "html") {
|
|
1284
|
+
return `<li>${content}</li>`;
|
|
1285
|
+
}
|
|
1286
|
+
return `<li>${content}</li>`;
|
|
1287
|
+
}
|
|
1100
1288
|
}
|
|
1101
1289
|
]
|
|
1102
1290
|
};
|
|
@@ -1121,18 +1309,18 @@ var TaskListExtension = {
|
|
|
1121
1309
|
type: "task-item",
|
|
1122
1310
|
render: (token) => {
|
|
1123
1311
|
const isChecked = token.attributes?.checked === "true";
|
|
1124
|
-
const
|
|
1312
|
+
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1125
1313
|
const format = token.attributes?.format || "html";
|
|
1126
1314
|
if (format === "html") {
|
|
1127
1315
|
return `<div style="display: flex; align-items: center; gap: 8px; margin: 8px 0;">
|
|
1128
1316
|
<input type="checkbox" ${isChecked ? "checked" : ""} disabled style="margin: 0;" />
|
|
1129
|
-
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${
|
|
1317
|
+
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${content}</span>
|
|
1130
1318
|
</div>`;
|
|
1131
1319
|
}
|
|
1132
1320
|
return `<div class="flex items-center gap-2 my-2 task-list-item">
|
|
1133
|
-
<input type="checkbox" ${isChecked ? "checked" : ""} disabled
|
|
1321
|
+
<input type="checkbox" ${isChecked ? "checked" : ""} disabled
|
|
1134
1322
|
class="form-checkbox h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" />
|
|
1135
|
-
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${
|
|
1323
|
+
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${content}</span>
|
|
1136
1324
|
</div>`;
|
|
1137
1325
|
}
|
|
1138
1326
|
}
|
|
@@ -1200,7 +1388,7 @@ var AlertExtension = {
|
|
|
1200
1388
|
parseRules: [
|
|
1201
1389
|
{
|
|
1202
1390
|
name: "alert",
|
|
1203
|
-
pattern: /:::(\w+)(
|
|
1391
|
+
pattern: /:::(\w+)(?: ([^\n]+))?\n([\s\S]*?)\n:::/,
|
|
1204
1392
|
render: (match) => {
|
|
1205
1393
|
return {
|
|
1206
1394
|
type: "alert",
|
|
@@ -1208,7 +1396,7 @@ var AlertExtension = {
|
|
|
1208
1396
|
raw: match[0] || "",
|
|
1209
1397
|
attributes: {
|
|
1210
1398
|
type: match[1] || "info",
|
|
1211
|
-
title: match[2] || ""
|
|
1399
|
+
title: match[2]?.trim() || ""
|
|
1212
1400
|
}
|
|
1213
1401
|
};
|
|
1214
1402
|
}
|
|
@@ -1688,8 +1876,13 @@ function extractVimeoId(url) {
|
|
|
1688
1876
|
var ChangerawrMarkdown = class {
|
|
1689
1877
|
constructor(config) {
|
|
1690
1878
|
this.extensions = /* @__PURE__ */ new Map();
|
|
1879
|
+
this.parseTime = 0;
|
|
1880
|
+
this.renderTime = 0;
|
|
1881
|
+
this.lastTokenCount = 0;
|
|
1691
1882
|
this.parser = new MarkdownParser(config?.parser);
|
|
1692
1883
|
this.renderer = new MarkdownRenderer(config?.renderer);
|
|
1884
|
+
this.parseCache = new LRUCache(100);
|
|
1885
|
+
this.renderCache = new LRUCache(100);
|
|
1693
1886
|
this.registerCoreExtensions();
|
|
1694
1887
|
this.registerFeatureExtensions();
|
|
1695
1888
|
if (config?.extensions) {
|
|
@@ -1772,14 +1965,83 @@ var ChangerawrMarkdown = class {
|
|
|
1772
1965
|
}
|
|
1773
1966
|
}
|
|
1774
1967
|
parse(markdown3) {
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1968
|
+
const cacheKey = hashContent(markdown3);
|
|
1969
|
+
const cached = this.parseCache.get(cacheKey);
|
|
1970
|
+
if (cached) {
|
|
1971
|
+
this.lastTokenCount = cached.length;
|
|
1972
|
+
return cached;
|
|
1973
|
+
}
|
|
1974
|
+
const startTime = performance.now();
|
|
1975
|
+
const tokens = this.parser.parse(markdown3);
|
|
1976
|
+
this.parseTime = performance.now() - startTime;
|
|
1977
|
+
this.lastTokenCount = tokens.length;
|
|
1978
|
+
this.parseCache.set(cacheKey, tokens);
|
|
1979
|
+
return tokens;
|
|
1980
|
+
}
|
|
1981
|
+
render(tokens, cacheKey) {
|
|
1982
|
+
if (cacheKey) {
|
|
1983
|
+
const cached = this.renderCache.get(cacheKey);
|
|
1984
|
+
if (cached) {
|
|
1985
|
+
return cached;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
const startTime = performance.now();
|
|
1989
|
+
const html = this.renderer.render(tokens);
|
|
1990
|
+
this.renderTime = performance.now() - startTime;
|
|
1991
|
+
if (cacheKey) {
|
|
1992
|
+
this.renderCache.set(cacheKey, html);
|
|
1993
|
+
}
|
|
1994
|
+
return html;
|
|
1779
1995
|
}
|
|
1780
1996
|
toHtml(markdown3) {
|
|
1997
|
+
const cacheKey = hashContent(markdown3);
|
|
1998
|
+
const cachedHtml = this.renderCache.get(cacheKey);
|
|
1999
|
+
if (cachedHtml) {
|
|
2000
|
+
return cachedHtml;
|
|
2001
|
+
}
|
|
1781
2002
|
const tokens = this.parse(markdown3);
|
|
1782
|
-
return this.render(tokens);
|
|
2003
|
+
return this.render(tokens, cacheKey);
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* Render markdown with performance metrics
|
|
2007
|
+
*/
|
|
2008
|
+
toHtmlWithMetrics(markdown3) {
|
|
2009
|
+
const startTotal = performance.now();
|
|
2010
|
+
const parseCacheKey = hashContent(markdown3);
|
|
2011
|
+
const parseCacheHit = this.parseCache.has(parseCacheKey);
|
|
2012
|
+
const html = this.toHtml(markdown3);
|
|
2013
|
+
const totalTime = performance.now() - startTotal;
|
|
2014
|
+
const metrics = {
|
|
2015
|
+
inputSize: markdown3.length,
|
|
2016
|
+
parseTime: this.parseTime,
|
|
2017
|
+
renderTime: this.renderTime,
|
|
2018
|
+
totalTime,
|
|
2019
|
+
tokenCount: this.lastTokenCount,
|
|
2020
|
+
cacheHit: parseCacheHit
|
|
2021
|
+
};
|
|
2022
|
+
return { html, metrics };
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Stream-render large documents in chunks for better performance
|
|
2026
|
+
*/
|
|
2027
|
+
async toHtmlStreamed(markdown3, options = {}) {
|
|
2028
|
+
const chunkSize = options.chunkSize || 50;
|
|
2029
|
+
const tokens = this.parse(markdown3);
|
|
2030
|
+
const totalTokens = tokens.length;
|
|
2031
|
+
const chunks = [];
|
|
2032
|
+
for (let i = 0; i < tokens.length; i += chunkSize) {
|
|
2033
|
+
const chunkTokens = tokens.slice(i, Math.min(i + chunkSize, tokens.length));
|
|
2034
|
+
const chunkHtml = this.render(chunkTokens);
|
|
2035
|
+
chunks.push(chunkHtml);
|
|
2036
|
+
if (options.onChunk) {
|
|
2037
|
+
options.onChunk({
|
|
2038
|
+
html: chunkHtml,
|
|
2039
|
+
progress: Math.min(i + chunkSize, tokens.length) / totalTokens
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
2042
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
2043
|
+
}
|
|
2044
|
+
return chunks.join("");
|
|
1783
2045
|
}
|
|
1784
2046
|
getExtensions() {
|
|
1785
2047
|
return Array.from(this.extensions.keys());
|
|
@@ -1793,25 +2055,50 @@ var ChangerawrMarkdown = class {
|
|
|
1793
2055
|
getDebugInfo() {
|
|
1794
2056
|
return {
|
|
1795
2057
|
warnings: this.getWarnings(),
|
|
1796
|
-
parseTime:
|
|
1797
|
-
renderTime:
|
|
1798
|
-
tokenCount:
|
|
2058
|
+
parseTime: this.parseTime,
|
|
2059
|
+
renderTime: this.renderTime,
|
|
2060
|
+
tokenCount: this.lastTokenCount,
|
|
1799
2061
|
iterationCount: 0
|
|
1800
2062
|
};
|
|
1801
2063
|
}
|
|
1802
2064
|
getPerformanceMetrics() {
|
|
1803
2065
|
return {
|
|
1804
|
-
parseTime:
|
|
1805
|
-
renderTime:
|
|
1806
|
-
totalTime:
|
|
1807
|
-
tokenCount:
|
|
2066
|
+
parseTime: this.parseTime,
|
|
2067
|
+
renderTime: this.renderTime,
|
|
2068
|
+
totalTime: this.parseTime + this.renderTime,
|
|
2069
|
+
tokenCount: this.lastTokenCount
|
|
1808
2070
|
};
|
|
1809
2071
|
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Get cache statistics
|
|
2074
|
+
*/
|
|
2075
|
+
getCacheStats() {
|
|
2076
|
+
return {
|
|
2077
|
+
parse: this.parseCache.getStats(),
|
|
2078
|
+
render: this.renderCache.getStats()
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* Clear all caches
|
|
2083
|
+
*/
|
|
2084
|
+
clearCaches() {
|
|
2085
|
+
this.parseCache.clear();
|
|
2086
|
+
this.renderCache.clear();
|
|
2087
|
+
}
|
|
2088
|
+
/**
|
|
2089
|
+
* Update cache capacity
|
|
2090
|
+
*/
|
|
2091
|
+
setCacheSize(size) {
|
|
2092
|
+
this.parseCache.setCapacity(size);
|
|
2093
|
+
this.renderCache.setCapacity(size);
|
|
2094
|
+
}
|
|
1810
2095
|
rebuildParserAndRenderer() {
|
|
1811
2096
|
const parserConfig = this.parser.getConfig();
|
|
1812
2097
|
const rendererConfig = this.renderer.getConfig();
|
|
1813
2098
|
this.parser = new MarkdownParser(parserConfig);
|
|
1814
2099
|
this.renderer = new MarkdownRenderer(rendererConfig);
|
|
2100
|
+
this.parseCache.clear();
|
|
2101
|
+
this.renderCache.clear();
|
|
1815
2102
|
const extensionsToRegister = Array.from(this.extensions.values());
|
|
1816
2103
|
const featureExtensions = extensionsToRegister.filter(
|
|
1817
2104
|
(ext) => ["alert", "button", "embed"].includes(ext.name)
|
|
@@ -2457,6 +2744,7 @@ function createEngineWithPreset(presetName, additionalConfig) {
|
|
|
2457
2744
|
ImageExtension,
|
|
2458
2745
|
InlineCodeExtension,
|
|
2459
2746
|
ItalicExtension,
|
|
2747
|
+
LRUCache,
|
|
2460
2748
|
LineBreakExtension,
|
|
2461
2749
|
LinkExtension,
|
|
2462
2750
|
ListExtension,
|
|
@@ -2488,10 +2776,12 @@ function createEngineWithPreset(presetName, additionalConfig) {
|
|
|
2488
2776
|
generateId,
|
|
2489
2777
|
getASTStats,
|
|
2490
2778
|
getTokenStats,
|
|
2779
|
+
hashContent,
|
|
2491
2780
|
isBrowser,
|
|
2492
2781
|
isNode,
|
|
2493
2782
|
isValidUrl,
|
|
2494
2783
|
markdown,
|
|
2784
|
+
memoize,
|
|
2495
2785
|
minimalClasses,
|
|
2496
2786
|
parseASTFromJSON,
|
|
2497
2787
|
parseCum,
|