mark-deco 0.16.0 → 0.18.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 (113) hide show
  1. package/dist/browser.cjs +212 -0
  2. package/dist/browser.cjs.map +1 -0
  3. package/dist/browser.d.ts +35 -0
  4. package/dist/browser.mjs +212 -0
  5. package/dist/browser.mjs.map +1 -0
  6. package/dist/html-generator-BwpF_EzG.cjs +1544 -0
  7. package/dist/html-generator-BwpF_EzG.cjs.map +1 -0
  8. package/dist/html-generator-C6jDxBHL.js +1528 -0
  9. package/dist/html-generator-C6jDxBHL.js.map +1 -0
  10. package/dist/index.cjs +1205 -23
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +599 -17
  13. package/dist/index.mjs +1070 -1116
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/internal.cjs +27 -5
  16. package/dist/internal.cjs.map +1 -1
  17. package/dist/internal.d.ts +347 -12
  18. package/dist/internal.mjs +22 -22
  19. package/dist/misc.cjs +219 -0
  20. package/dist/misc.cjs.map +1 -0
  21. package/dist/{plugins/card/types.d.ts → misc.d.ts} +92 -102
  22. package/dist/misc.mjs +219 -0
  23. package/dist/misc.mjs.map +1 -0
  24. package/dist/node.cjs +188 -0
  25. package/dist/node.cjs.map +1 -0
  26. package/dist/node.d.ts +36 -0
  27. package/dist/node.mjs +188 -0
  28. package/dist/node.mjs.map +1 -0
  29. package/dist/utils-BUH90g-e.js +106 -0
  30. package/dist/utils-BUH90g-e.js.map +1 -0
  31. package/dist/utils-uvxmZF0P.cjs +105 -0
  32. package/dist/utils-uvxmZF0P.cjs.map +1 -0
  33. package/package.json +23 -8
  34. package/dist/apply-title-from-h1.d.ts +0 -29
  35. package/dist/apply-title-from-h1.d.ts.map +0 -1
  36. package/dist/cache/filesystem.d.ts +0 -20
  37. package/dist/cache/filesystem.d.ts.map +0 -1
  38. package/dist/cache/index.d.ts +0 -48
  39. package/dist/cache/index.d.ts.map +0 -1
  40. package/dist/cache/localstorage.d.ts +0 -19
  41. package/dist/cache/localstorage.d.ts.map +0 -1
  42. package/dist/cache/memory.d.ts +0 -18
  43. package/dist/cache/memory.d.ts.map +0 -1
  44. package/dist/fetcher.d.ts +0 -42
  45. package/dist/fetcher.d.ts.map +0 -1
  46. package/dist/frontmatter.d.ts +0 -32
  47. package/dist/frontmatter.d.ts.map +0 -1
  48. package/dist/index.d.ts.map +0 -1
  49. package/dist/internal-C5sOXLgo.js +0 -11180
  50. package/dist/internal-C5sOXLgo.js.map +0 -1
  51. package/dist/internal-vytMjdyC.cjs +0 -114
  52. package/dist/internal-vytMjdyC.cjs.map +0 -1
  53. package/dist/internal.d.ts.map +0 -1
  54. package/dist/logger.d.ts +0 -22
  55. package/dist/logger.d.ts.map +0 -1
  56. package/dist/plugins/card/amazon-rules.d.ts +0 -16
  57. package/dist/plugins/card/amazon-rules.d.ts.map +0 -1
  58. package/dist/plugins/card/fetcher.d.ts +0 -17
  59. package/dist/plugins/card/fetcher.d.ts.map +0 -1
  60. package/dist/plugins/card/html-generator.d.ts +0 -20
  61. package/dist/plugins/card/html-generator.d.ts.map +0 -1
  62. package/dist/plugins/card/index.d.ts +0 -20
  63. package/dist/plugins/card/index.d.ts.map +0 -1
  64. package/dist/plugins/card/ogp-rules.d.ts +0 -35
  65. package/dist/plugins/card/ogp-rules.d.ts.map +0 -1
  66. package/dist/plugins/card/rule-engine.d.ts +0 -22
  67. package/dist/plugins/card/rule-engine.d.ts.map +0 -1
  68. package/dist/plugins/card/types.d.ts.map +0 -1
  69. package/dist/plugins/card/utils.d.ts +0 -42
  70. package/dist/plugins/card/utils.d.ts.map +0 -1
  71. package/dist/plugins/card-plugin.d.ts +0 -12
  72. package/dist/plugins/card-plugin.d.ts.map +0 -1
  73. package/dist/plugins/mermaid/index.d.ts +0 -19
  74. package/dist/plugins/mermaid/index.d.ts.map +0 -1
  75. package/dist/plugins/mermaid/types.d.ts +0 -20
  76. package/dist/plugins/mermaid/types.d.ts.map +0 -1
  77. package/dist/plugins/mermaid-plugin.d.ts +0 -12
  78. package/dist/plugins/mermaid-plugin.d.ts.map +0 -1
  79. package/dist/plugins/oembed/fetcher.d.ts +0 -23
  80. package/dist/plugins/oembed/fetcher.d.ts.map +0 -1
  81. package/dist/plugins/oembed/html-generator.d.ts +0 -20
  82. package/dist/plugins/oembed/html-generator.d.ts.map +0 -1
  83. package/dist/plugins/oembed/index.d.ts +0 -20
  84. package/dist/plugins/oembed/index.d.ts.map +0 -1
  85. package/dist/plugins/oembed/providers.d.ts +0 -36
  86. package/dist/plugins/oembed/providers.d.ts.map +0 -1
  87. package/dist/plugins/oembed/providers.json.d.ts +0 -4451
  88. package/dist/plugins/oembed/redirect-resolver.d.ts +0 -16
  89. package/dist/plugins/oembed/redirect-resolver.d.ts.map +0 -1
  90. package/dist/plugins/oembed/types.d.ts +0 -97
  91. package/dist/plugins/oembed/types.d.ts.map +0 -1
  92. package/dist/plugins/oembed/utils.d.ts +0 -27
  93. package/dist/plugins/oembed/utils.d.ts.map +0 -1
  94. package/dist/plugins/oembed-plugin.d.ts +0 -12
  95. package/dist/plugins/oembed-plugin.d.ts.map +0 -1
  96. package/dist/plugins/remark-apply-title-from-h1.d.ts +0 -47
  97. package/dist/plugins/remark-apply-title-from-h1.d.ts.map +0 -1
  98. package/dist/plugins/remark-attr.d.ts +0 -18
  99. package/dist/plugins/remark-attr.d.ts.map +0 -1
  100. package/dist/plugins/responsive-images.d.ts +0 -17
  101. package/dist/plugins/responsive-images.d.ts.map +0 -1
  102. package/dist/plugins/shared/error-formatter.d.ts +0 -16
  103. package/dist/plugins/shared/error-formatter.d.ts.map +0 -1
  104. package/dist/processor.d.ts +0 -24
  105. package/dist/processor.d.ts.map +0 -1
  106. package/dist/types.d.ts +0 -236
  107. package/dist/types.d.ts.map +0 -1
  108. package/dist/utils/heading.d.ts +0 -24
  109. package/dist/utils/heading.d.ts.map +0 -1
  110. package/dist/utils/responsive-image.d.ts +0 -40
  111. package/dist/utils/responsive-image.d.ts.map +0 -1
  112. package/dist/utils.d.ts +0 -106
  113. package/dist/utils.d.ts.map +0 -1
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /*!
3
+ * name: mark-deco
4
+ * version: 0.18.0
5
+ * description: Flexible Markdown to HTML conversion library
6
+ * author: Kouji Matsui (@kekyo@mi.kekyo.net)
7
+ * license: MIT
8
+ * repository.url: https://github.com/kekyo/mark-deco
9
+ * git.commit.hash: 08bdfee4eccfb64e9ebacc5883c19a5cd40ce900
10
+ */
11
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
12
+ const asyncPrimitives = require("async-primitives");
13
+ const createLocalCacheStorage = (keyPrefix = "cache:") => {
14
+ const mutex = asyncPrimitives.createMutex();
15
+ const isLocalStorageAvailable = () => {
16
+ try {
17
+ const storage = typeof localStorage !== "undefined" ? localStorage : typeof window !== "undefined" ? window.localStorage : void 0;
18
+ return storage !== void 0 && storage !== null;
19
+ } catch (e) {
20
+ return false;
21
+ }
22
+ };
23
+ const cleanupExpiredInternal = async () => {
24
+ if (!isLocalStorageAvailable()) {
25
+ return;
26
+ }
27
+ const now = Date.now();
28
+ const expiredKeys = [];
29
+ for (let i = 0; i < localStorage.length; i++) {
30
+ const key = localStorage.key(i);
31
+ if (!key || !key.startsWith(keyPrefix)) {
32
+ continue;
33
+ }
34
+ const stored = localStorage.getItem(key);
35
+ if (!stored) {
36
+ continue;
37
+ }
38
+ try {
39
+ const entry = JSON.parse(stored);
40
+ if (entry.ttl !== void 0) {
41
+ const isExpired = entry.ttl === 0 || now > entry.timestamp + entry.ttl;
42
+ if (isExpired) {
43
+ expiredKeys.push(key);
44
+ }
45
+ }
46
+ } catch (e) {
47
+ expiredKeys.push(key);
48
+ }
49
+ }
50
+ for (const key of expiredKeys) {
51
+ localStorage.removeItem(key);
52
+ }
53
+ };
54
+ const get = async (key) => {
55
+ if (!isLocalStorageAvailable()) {
56
+ throw new Error("localStorage is not available in this environment");
57
+ }
58
+ const fullKey = keyPrefix + key;
59
+ const stored = localStorage.getItem(fullKey);
60
+ if (!stored) {
61
+ return null;
62
+ }
63
+ let entry;
64
+ try {
65
+ entry = JSON.parse(stored);
66
+ } catch (e) {
67
+ const lockHandle = await mutex.lock();
68
+ try {
69
+ localStorage.removeItem(fullKey);
70
+ return null;
71
+ } finally {
72
+ lockHandle.release();
73
+ }
74
+ }
75
+ if (entry.ttl !== void 0) {
76
+ const isExpired = entry.ttl === 0 || Date.now() > entry.timestamp + entry.ttl;
77
+ if (isExpired) {
78
+ const lockHandle = await mutex.lock();
79
+ try {
80
+ const currentTime = Date.now();
81
+ const stillExpired = entry.ttl === 0 || currentTime > entry.timestamp + entry.ttl;
82
+ if (stillExpired) {
83
+ localStorage.removeItem(fullKey);
84
+ }
85
+ return null;
86
+ } finally {
87
+ lockHandle.release();
88
+ }
89
+ }
90
+ }
91
+ return entry.data;
92
+ };
93
+ const set = async (key, value, ttl) => {
94
+ if (!isLocalStorageAvailable()) {
95
+ throw new Error("localStorage is not available in this environment");
96
+ }
97
+ const fullKey = keyPrefix + key;
98
+ const entry = {
99
+ data: value,
100
+ timestamp: Date.now()
101
+ };
102
+ if (ttl !== void 0) {
103
+ entry.ttl = ttl;
104
+ }
105
+ const serialized = JSON.stringify(entry);
106
+ const lockHandle = await mutex.lock();
107
+ try {
108
+ try {
109
+ localStorage.setItem(fullKey, serialized);
110
+ } catch (error) {
111
+ if (error instanceof Error && error.name === "QuotaExceededError") {
112
+ await cleanupExpiredInternal();
113
+ try {
114
+ localStorage.setItem(fullKey, serialized);
115
+ } catch (retryError) {
116
+ throw new Error(`Failed to store cache entry: ${retryError}`);
117
+ }
118
+ } else {
119
+ throw new Error(`Failed to store cache entry: ${error}`);
120
+ }
121
+ }
122
+ } finally {
123
+ lockHandle.release();
124
+ }
125
+ };
126
+ const deleteEntry = async (key) => {
127
+ if (!isLocalStorageAvailable()) {
128
+ throw new Error("localStorage is not available in this environment");
129
+ }
130
+ const fullKey = keyPrefix + key;
131
+ const lockHandle = await mutex.lock();
132
+ try {
133
+ localStorage.removeItem(fullKey);
134
+ } finally {
135
+ lockHandle.release();
136
+ }
137
+ };
138
+ const clear = async () => {
139
+ if (!isLocalStorageAvailable()) {
140
+ throw new Error("localStorage is not available in this environment");
141
+ }
142
+ const keysToRemove = [];
143
+ for (let i = 0; i < localStorage.length; i++) {
144
+ const key = localStorage.key(i);
145
+ if (key && key.startsWith(keyPrefix)) {
146
+ keysToRemove.push(key);
147
+ }
148
+ }
149
+ if (keysToRemove.length === 0) {
150
+ return;
151
+ }
152
+ const lockHandle = await mutex.lock();
153
+ try {
154
+ for (const key of keysToRemove) {
155
+ localStorage.removeItem(key);
156
+ }
157
+ } finally {
158
+ lockHandle.release();
159
+ }
160
+ };
161
+ const size = async () => {
162
+ if (!isLocalStorageAvailable()) {
163
+ throw new Error("localStorage is not available in this environment");
164
+ }
165
+ const keysToCheck = [];
166
+ for (let i = 0; i < localStorage.length; i++) {
167
+ const key = localStorage.key(i);
168
+ if (key && key.startsWith(keyPrefix)) {
169
+ keysToCheck.push(key);
170
+ }
171
+ }
172
+ if (keysToCheck.length === 0) {
173
+ return 0;
174
+ }
175
+ const lockHandle = await mutex.lock();
176
+ try {
177
+ const now = Date.now();
178
+ let validCount = 0;
179
+ for (const key of keysToCheck) {
180
+ const stored = localStorage.getItem(key);
181
+ if (!stored) {
182
+ continue;
183
+ }
184
+ try {
185
+ const entry = JSON.parse(stored);
186
+ if (entry.ttl !== void 0) {
187
+ const isExpired = entry.ttl === 0 || now > entry.timestamp + entry.ttl;
188
+ if (isExpired) {
189
+ localStorage.removeItem(key);
190
+ continue;
191
+ }
192
+ }
193
+ validCount++;
194
+ } catch (e) {
195
+ localStorage.removeItem(key);
196
+ }
197
+ }
198
+ return validCount;
199
+ } finally {
200
+ lockHandle.release();
201
+ }
202
+ };
203
+ return {
204
+ get,
205
+ set,
206
+ delete: deleteEntry,
207
+ clear,
208
+ size
209
+ };
210
+ };
211
+ exports.createLocalCacheStorage = createLocalCacheStorage;
212
+ //# sourceMappingURL=browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.cjs","sources":["../src/cache/localstorage.ts"],"sourcesContent":["// mark-deco - Flexible Markdown to HTML conversion library\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/mark-deco\n\nimport { createMutex } from 'async-primitives';\nimport type { CacheStorage, CacheEntry } from './index';\n\n/**\n * Create localStorage-based cache storage instance\n * @param keyPrefix - Prefix for localStorage keys (defaults to 'cache:')\n * @returns LocalCache instance that uses localStorage\n * @throws Error if localStorage is not available\n */\nexport const createLocalCacheStorage = (\n keyPrefix: string = 'cache:'\n): CacheStorage => {\n const mutex = createMutex();\n\n /**\n * Check if localStorage is available\n */\n const isLocalStorageAvailable = (): boolean => {\n try {\n const storage =\n typeof localStorage !== 'undefined'\n ? localStorage\n : typeof window !== 'undefined'\n ? window.localStorage\n : undefined;\n return storage !== undefined && storage !== null;\n } catch {\n return false;\n }\n };\n\n /**\n * Clean up expired entries (internal method, assumes lock is already held)\n */\n const cleanupExpiredInternal = async (): Promise<void> => {\n if (!isLocalStorageAvailable()) {\n return;\n }\n\n const now = Date.now();\n const expiredKeys: string[] = [];\n\n // Scan all localStorage keys with our prefix\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (!key || !key.startsWith(keyPrefix)) {\n continue;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n continue;\n }\n\n try {\n const entry: CacheEntry = JSON.parse(stored);\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || now > entry.timestamp + entry.ttl;\n if (isExpired) {\n expiredKeys.push(key);\n }\n }\n } catch {\n // Invalid JSON, mark for removal\n expiredKeys.push(key);\n }\n }\n\n // Remove expired entries\n for (const key of expiredKeys) {\n localStorage.removeItem(key);\n }\n };\n\n const get = async (key: string): Promise<string | null> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute full key outside of lock\n const fullKey = keyPrefix + key;\n const stored = localStorage.getItem(fullKey);\n\n if (!stored) {\n return null;\n }\n\n let entry: CacheEntry;\n try {\n entry = JSON.parse(stored);\n } catch {\n // Invalid JSON, need to remove the corrupted entry under lock\n const lockHandle = await mutex.lock();\n try {\n localStorage.removeItem(fullKey);\n return null;\n } finally {\n lockHandle.release();\n }\n }\n\n // Check TTL expiration - only lock if we need to delete expired entry\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || Date.now() > entry.timestamp + entry.ttl;\n if (isExpired) {\n // Lock only for the deletion operation\n const lockHandle = await mutex.lock();\n try {\n // Double-check expiration under lock to avoid race conditions\n const currentTime = Date.now();\n const stillExpired =\n entry.ttl === 0 || currentTime > entry.timestamp + entry.ttl;\n if (stillExpired) {\n localStorage.removeItem(fullKey);\n }\n return null;\n } finally {\n lockHandle.release();\n }\n }\n }\n\n return entry.data;\n };\n\n const set = async (\n key: string,\n value: string,\n ttl?: number\n ): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute everything possible outside of lock\n const fullKey = keyPrefix + key;\n const entry: CacheEntry = {\n data: value,\n timestamp: Date.now(),\n };\n\n if (ttl !== undefined) {\n entry.ttl = ttl;\n }\n\n const serialized = JSON.stringify(entry);\n\n const lockHandle = await mutex.lock();\n try {\n try {\n // For cache systems, last-write-wins is often acceptable\n // We minimize lock time by only protecting the actual storage operation\n localStorage.setItem(fullKey, serialized);\n } catch (error) {\n // Handle localStorage quota exceeded or other errors\n if (error instanceof Error && error.name === 'QuotaExceededError') {\n // Try to cleanup expired entries and retry\n await cleanupExpiredInternal();\n try {\n localStorage.setItem(fullKey, serialized);\n } catch (retryError) {\n throw new Error(`Failed to store cache entry: ${retryError}`);\n }\n } else {\n throw new Error(`Failed to store cache entry: ${error}`);\n }\n }\n } finally {\n lockHandle.release();\n }\n };\n\n const deleteEntry = async (key: string): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute full key outside of lock\n const fullKey = keyPrefix + key;\n\n const lockHandle = await mutex.lock();\n try {\n localStorage.removeItem(fullKey);\n } finally {\n lockHandle.release();\n }\n };\n\n const clear = async (): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-scan keys to remove outside of lock\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(keyPrefix)) {\n keysToRemove.push(key);\n }\n }\n\n if (keysToRemove.length === 0) {\n return;\n }\n\n const lockHandle = await mutex.lock();\n try {\n // Remove all identified keys\n for (const key of keysToRemove) {\n localStorage.removeItem(key);\n }\n } finally {\n lockHandle.release();\n }\n };\n\n const size = async (): Promise<number> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-scan all keys with our prefix without lock\n const keysToCheck: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(keyPrefix)) {\n keysToCheck.push(key);\n }\n }\n\n if (keysToCheck.length === 0) {\n return 0;\n }\n\n // Clean up expired entries and count valid ones with lock\n const lockHandle = await mutex.lock();\n try {\n const now = Date.now();\n let validCount = 0;\n\n for (const key of keysToCheck) {\n const stored = localStorage.getItem(key);\n if (!stored) {\n continue; // Key was deleted by another process\n }\n\n try {\n const entry: CacheEntry = JSON.parse(stored);\n\n // Check if entry is expired\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || now > entry.timestamp + entry.ttl;\n if (isExpired) {\n localStorage.removeItem(key);\n continue; // Don't count this entry\n }\n }\n validCount++;\n } catch {\n // Invalid JSON, remove it\n localStorage.removeItem(key);\n }\n }\n\n return validCount;\n } finally {\n lockHandle.release();\n }\n };\n\n return {\n get,\n set,\n delete: deleteEntry,\n clear,\n size,\n };\n};\n"],"names":["createMutex"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /*!
2
+ * name: mark-deco
3
+ * version: 0.18.0
4
+ * description: Flexible Markdown to HTML conversion library
5
+ * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
+ * license: MIT
7
+ * repository.url: https://github.com/kekyo/mark-deco
8
+ * git.commit.hash: 08bdfee4eccfb64e9ebacc5883c19a5cd40ce900
9
+ */
10
+
11
+ /**
12
+ * Cache storage interface
13
+ */
14
+ declare interface CacheStorage_2 {
15
+ /** Retrieve cached data by key */
16
+ get(key: string): Promise<string | null>;
17
+ /** Store data in cache with optional TTL */
18
+ set(key: string, value: string, ttl?: number): Promise<void>;
19
+ /** Delete cached data by key */
20
+ delete(key: string): Promise<void>;
21
+ /** Clear all cached data */
22
+ clear(): Promise<void>;
23
+ /** Get the number of cached entries */
24
+ size(): Promise<number>;
25
+ }
26
+
27
+ /**
28
+ * Create localStorage-based cache storage instance
29
+ * @param keyPrefix - Prefix for localStorage keys (defaults to 'cache:')
30
+ * @returns LocalCache instance that uses localStorage
31
+ * @throws Error if localStorage is not available
32
+ */
33
+ export declare const createLocalCacheStorage: (keyPrefix?: string) => CacheStorage_2;
34
+
35
+ export { }
@@ -0,0 +1,212 @@
1
+ /*!
2
+ * name: mark-deco
3
+ * version: 0.18.0
4
+ * description: Flexible Markdown to HTML conversion library
5
+ * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
+ * license: MIT
7
+ * repository.url: https://github.com/kekyo/mark-deco
8
+ * git.commit.hash: 08bdfee4eccfb64e9ebacc5883c19a5cd40ce900
9
+ */
10
+ import { createMutex } from "async-primitives";
11
+ const createLocalCacheStorage = (keyPrefix = "cache:") => {
12
+ const mutex = createMutex();
13
+ const isLocalStorageAvailable = () => {
14
+ try {
15
+ const storage = typeof localStorage !== "undefined" ? localStorage : typeof window !== "undefined" ? window.localStorage : void 0;
16
+ return storage !== void 0 && storage !== null;
17
+ } catch (e) {
18
+ return false;
19
+ }
20
+ };
21
+ const cleanupExpiredInternal = async () => {
22
+ if (!isLocalStorageAvailable()) {
23
+ return;
24
+ }
25
+ const now = Date.now();
26
+ const expiredKeys = [];
27
+ for (let i = 0; i < localStorage.length; i++) {
28
+ const key = localStorage.key(i);
29
+ if (!key || !key.startsWith(keyPrefix)) {
30
+ continue;
31
+ }
32
+ const stored = localStorage.getItem(key);
33
+ if (!stored) {
34
+ continue;
35
+ }
36
+ try {
37
+ const entry = JSON.parse(stored);
38
+ if (entry.ttl !== void 0) {
39
+ const isExpired = entry.ttl === 0 || now > entry.timestamp + entry.ttl;
40
+ if (isExpired) {
41
+ expiredKeys.push(key);
42
+ }
43
+ }
44
+ } catch (e) {
45
+ expiredKeys.push(key);
46
+ }
47
+ }
48
+ for (const key of expiredKeys) {
49
+ localStorage.removeItem(key);
50
+ }
51
+ };
52
+ const get = async (key) => {
53
+ if (!isLocalStorageAvailable()) {
54
+ throw new Error("localStorage is not available in this environment");
55
+ }
56
+ const fullKey = keyPrefix + key;
57
+ const stored = localStorage.getItem(fullKey);
58
+ if (!stored) {
59
+ return null;
60
+ }
61
+ let entry;
62
+ try {
63
+ entry = JSON.parse(stored);
64
+ } catch (e) {
65
+ const lockHandle = await mutex.lock();
66
+ try {
67
+ localStorage.removeItem(fullKey);
68
+ return null;
69
+ } finally {
70
+ lockHandle.release();
71
+ }
72
+ }
73
+ if (entry.ttl !== void 0) {
74
+ const isExpired = entry.ttl === 0 || Date.now() > entry.timestamp + entry.ttl;
75
+ if (isExpired) {
76
+ const lockHandle = await mutex.lock();
77
+ try {
78
+ const currentTime = Date.now();
79
+ const stillExpired = entry.ttl === 0 || currentTime > entry.timestamp + entry.ttl;
80
+ if (stillExpired) {
81
+ localStorage.removeItem(fullKey);
82
+ }
83
+ return null;
84
+ } finally {
85
+ lockHandle.release();
86
+ }
87
+ }
88
+ }
89
+ return entry.data;
90
+ };
91
+ const set = async (key, value, ttl) => {
92
+ if (!isLocalStorageAvailable()) {
93
+ throw new Error("localStorage is not available in this environment");
94
+ }
95
+ const fullKey = keyPrefix + key;
96
+ const entry = {
97
+ data: value,
98
+ timestamp: Date.now()
99
+ };
100
+ if (ttl !== void 0) {
101
+ entry.ttl = ttl;
102
+ }
103
+ const serialized = JSON.stringify(entry);
104
+ const lockHandle = await mutex.lock();
105
+ try {
106
+ try {
107
+ localStorage.setItem(fullKey, serialized);
108
+ } catch (error) {
109
+ if (error instanceof Error && error.name === "QuotaExceededError") {
110
+ await cleanupExpiredInternal();
111
+ try {
112
+ localStorage.setItem(fullKey, serialized);
113
+ } catch (retryError) {
114
+ throw new Error(`Failed to store cache entry: ${retryError}`);
115
+ }
116
+ } else {
117
+ throw new Error(`Failed to store cache entry: ${error}`);
118
+ }
119
+ }
120
+ } finally {
121
+ lockHandle.release();
122
+ }
123
+ };
124
+ const deleteEntry = async (key) => {
125
+ if (!isLocalStorageAvailable()) {
126
+ throw new Error("localStorage is not available in this environment");
127
+ }
128
+ const fullKey = keyPrefix + key;
129
+ const lockHandle = await mutex.lock();
130
+ try {
131
+ localStorage.removeItem(fullKey);
132
+ } finally {
133
+ lockHandle.release();
134
+ }
135
+ };
136
+ const clear = async () => {
137
+ if (!isLocalStorageAvailable()) {
138
+ throw new Error("localStorage is not available in this environment");
139
+ }
140
+ const keysToRemove = [];
141
+ for (let i = 0; i < localStorage.length; i++) {
142
+ const key = localStorage.key(i);
143
+ if (key && key.startsWith(keyPrefix)) {
144
+ keysToRemove.push(key);
145
+ }
146
+ }
147
+ if (keysToRemove.length === 0) {
148
+ return;
149
+ }
150
+ const lockHandle = await mutex.lock();
151
+ try {
152
+ for (const key of keysToRemove) {
153
+ localStorage.removeItem(key);
154
+ }
155
+ } finally {
156
+ lockHandle.release();
157
+ }
158
+ };
159
+ const size = async () => {
160
+ if (!isLocalStorageAvailable()) {
161
+ throw new Error("localStorage is not available in this environment");
162
+ }
163
+ const keysToCheck = [];
164
+ for (let i = 0; i < localStorage.length; i++) {
165
+ const key = localStorage.key(i);
166
+ if (key && key.startsWith(keyPrefix)) {
167
+ keysToCheck.push(key);
168
+ }
169
+ }
170
+ if (keysToCheck.length === 0) {
171
+ return 0;
172
+ }
173
+ const lockHandle = await mutex.lock();
174
+ try {
175
+ const now = Date.now();
176
+ let validCount = 0;
177
+ for (const key of keysToCheck) {
178
+ const stored = localStorage.getItem(key);
179
+ if (!stored) {
180
+ continue;
181
+ }
182
+ try {
183
+ const entry = JSON.parse(stored);
184
+ if (entry.ttl !== void 0) {
185
+ const isExpired = entry.ttl === 0 || now > entry.timestamp + entry.ttl;
186
+ if (isExpired) {
187
+ localStorage.removeItem(key);
188
+ continue;
189
+ }
190
+ }
191
+ validCount++;
192
+ } catch (e) {
193
+ localStorage.removeItem(key);
194
+ }
195
+ }
196
+ return validCount;
197
+ } finally {
198
+ lockHandle.release();
199
+ }
200
+ };
201
+ return {
202
+ get,
203
+ set,
204
+ delete: deleteEntry,
205
+ clear,
206
+ size
207
+ };
208
+ };
209
+ export {
210
+ createLocalCacheStorage
211
+ };
212
+ //# sourceMappingURL=browser.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.mjs","sources":["../src/cache/localstorage.ts"],"sourcesContent":["// mark-deco - Flexible Markdown to HTML conversion library\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/mark-deco\n\nimport { createMutex } from 'async-primitives';\nimport type { CacheStorage, CacheEntry } from './index';\n\n/**\n * Create localStorage-based cache storage instance\n * @param keyPrefix - Prefix for localStorage keys (defaults to 'cache:')\n * @returns LocalCache instance that uses localStorage\n * @throws Error if localStorage is not available\n */\nexport const createLocalCacheStorage = (\n keyPrefix: string = 'cache:'\n): CacheStorage => {\n const mutex = createMutex();\n\n /**\n * Check if localStorage is available\n */\n const isLocalStorageAvailable = (): boolean => {\n try {\n const storage =\n typeof localStorage !== 'undefined'\n ? localStorage\n : typeof window !== 'undefined'\n ? window.localStorage\n : undefined;\n return storage !== undefined && storage !== null;\n } catch {\n return false;\n }\n };\n\n /**\n * Clean up expired entries (internal method, assumes lock is already held)\n */\n const cleanupExpiredInternal = async (): Promise<void> => {\n if (!isLocalStorageAvailable()) {\n return;\n }\n\n const now = Date.now();\n const expiredKeys: string[] = [];\n\n // Scan all localStorage keys with our prefix\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (!key || !key.startsWith(keyPrefix)) {\n continue;\n }\n\n const stored = localStorage.getItem(key);\n if (!stored) {\n continue;\n }\n\n try {\n const entry: CacheEntry = JSON.parse(stored);\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || now > entry.timestamp + entry.ttl;\n if (isExpired) {\n expiredKeys.push(key);\n }\n }\n } catch {\n // Invalid JSON, mark for removal\n expiredKeys.push(key);\n }\n }\n\n // Remove expired entries\n for (const key of expiredKeys) {\n localStorage.removeItem(key);\n }\n };\n\n const get = async (key: string): Promise<string | null> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute full key outside of lock\n const fullKey = keyPrefix + key;\n const stored = localStorage.getItem(fullKey);\n\n if (!stored) {\n return null;\n }\n\n let entry: CacheEntry;\n try {\n entry = JSON.parse(stored);\n } catch {\n // Invalid JSON, need to remove the corrupted entry under lock\n const lockHandle = await mutex.lock();\n try {\n localStorage.removeItem(fullKey);\n return null;\n } finally {\n lockHandle.release();\n }\n }\n\n // Check TTL expiration - only lock if we need to delete expired entry\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || Date.now() > entry.timestamp + entry.ttl;\n if (isExpired) {\n // Lock only for the deletion operation\n const lockHandle = await mutex.lock();\n try {\n // Double-check expiration under lock to avoid race conditions\n const currentTime = Date.now();\n const stillExpired =\n entry.ttl === 0 || currentTime > entry.timestamp + entry.ttl;\n if (stillExpired) {\n localStorage.removeItem(fullKey);\n }\n return null;\n } finally {\n lockHandle.release();\n }\n }\n }\n\n return entry.data;\n };\n\n const set = async (\n key: string,\n value: string,\n ttl?: number\n ): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute everything possible outside of lock\n const fullKey = keyPrefix + key;\n const entry: CacheEntry = {\n data: value,\n timestamp: Date.now(),\n };\n\n if (ttl !== undefined) {\n entry.ttl = ttl;\n }\n\n const serialized = JSON.stringify(entry);\n\n const lockHandle = await mutex.lock();\n try {\n try {\n // For cache systems, last-write-wins is often acceptable\n // We minimize lock time by only protecting the actual storage operation\n localStorage.setItem(fullKey, serialized);\n } catch (error) {\n // Handle localStorage quota exceeded or other errors\n if (error instanceof Error && error.name === 'QuotaExceededError') {\n // Try to cleanup expired entries and retry\n await cleanupExpiredInternal();\n try {\n localStorage.setItem(fullKey, serialized);\n } catch (retryError) {\n throw new Error(`Failed to store cache entry: ${retryError}`);\n }\n } else {\n throw new Error(`Failed to store cache entry: ${error}`);\n }\n }\n } finally {\n lockHandle.release();\n }\n };\n\n const deleteEntry = async (key: string): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-compute full key outside of lock\n const fullKey = keyPrefix + key;\n\n const lockHandle = await mutex.lock();\n try {\n localStorage.removeItem(fullKey);\n } finally {\n lockHandle.release();\n }\n };\n\n const clear = async (): Promise<void> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-scan keys to remove outside of lock\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(keyPrefix)) {\n keysToRemove.push(key);\n }\n }\n\n if (keysToRemove.length === 0) {\n return;\n }\n\n const lockHandle = await mutex.lock();\n try {\n // Remove all identified keys\n for (const key of keysToRemove) {\n localStorage.removeItem(key);\n }\n } finally {\n lockHandle.release();\n }\n };\n\n const size = async (): Promise<number> => {\n // Check if localStorage is available first (no lock needed for this check)\n if (!isLocalStorageAvailable()) {\n throw new Error('localStorage is not available in this environment');\n }\n\n // Pre-scan all keys with our prefix without lock\n const keysToCheck: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(keyPrefix)) {\n keysToCheck.push(key);\n }\n }\n\n if (keysToCheck.length === 0) {\n return 0;\n }\n\n // Clean up expired entries and count valid ones with lock\n const lockHandle = await mutex.lock();\n try {\n const now = Date.now();\n let validCount = 0;\n\n for (const key of keysToCheck) {\n const stored = localStorage.getItem(key);\n if (!stored) {\n continue; // Key was deleted by another process\n }\n\n try {\n const entry: CacheEntry = JSON.parse(stored);\n\n // Check if entry is expired\n if (entry.ttl !== undefined) {\n const isExpired =\n entry.ttl === 0 || now > entry.timestamp + entry.ttl;\n if (isExpired) {\n localStorage.removeItem(key);\n continue; // Don't count this entry\n }\n }\n validCount++;\n } catch {\n // Invalid JSON, remove it\n localStorage.removeItem(key);\n }\n }\n\n return validCount;\n } finally {\n lockHandle.release();\n }\n };\n\n return {\n get,\n set,\n delete: deleteEntry,\n clear,\n size,\n };\n};\n"],"names":[],"mappings":"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"}