web-remarq 0.5.0 → 0.6.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.
@@ -50,6 +50,7 @@ var WebRemarq = (() => {
50
50
  // src/index.ts
51
51
  var src_exports = {};
52
52
  __export(src_exports, {
53
+ LocalStorageAdapter: () => LocalStorageAdapter,
53
54
  WebRemarq: () => WebRemarq
54
55
  });
55
56
 
@@ -88,79 +89,133 @@ var WebRemarq = (() => {
88
89
  }
89
90
 
90
91
  // src/core/storage.ts
91
- var STORAGE_KEY = "remarq:annotations";
92
92
  var AnnotationStorage = class {
93
- constructor() {
94
- this.annotations = [];
95
- this.extraFields = {};
96
- this.isMemoryOnly = false;
97
- this.load();
93
+ constructor(adapter) {
94
+ this.adapter = adapter;
95
+ this.cache = [];
96
+ this.ready = this.init();
97
+ }
98
+ get isMemoryOnly() {
99
+ var _a3;
100
+ return (_a3 = this.adapter.isMemoryOnly) != null ? _a3 : false;
98
101
  }
99
102
  getAll() {
100
- return [...this.annotations];
103
+ return [...this.cache];
101
104
  }
102
105
  getByRoute(route) {
103
- return this.annotations.filter((a) => a.route === route);
106
+ return this.cache.filter((a) => a.route === route);
104
107
  }
105
- add(annotation) {
106
- this.annotations.push(annotation);
107
- this.save();
108
+ async add(annotation) {
109
+ this.cache.push(annotation);
110
+ await this.adapter.save(annotation);
108
111
  }
109
- remove(id) {
110
- this.annotations = this.annotations.filter((a) => a.id !== id);
111
- this.save();
112
+ async remove(id) {
113
+ this.cache = this.cache.filter((a) => a.id !== id);
114
+ await this.adapter.remove(id);
112
115
  }
113
- update(id, changes) {
114
- const idx = this.annotations.findIndex((a) => a.id === id);
115
- if (idx !== -1) {
116
- this.annotations[idx] = __spreadValues(__spreadValues({}, this.annotations[idx]), changes);
117
- this.save();
118
- }
116
+ async update(id, changes) {
117
+ const idx = this.cache.findIndex((a) => a.id === id);
118
+ if (idx === -1) return;
119
+ const updated = __spreadValues(__spreadValues({}, this.cache[idx]), changes);
120
+ this.cache[idx] = updated;
121
+ await this.adapter.save(updated);
119
122
  }
120
- clearAll() {
121
- this.annotations = [];
122
- this.save();
123
+ async clearAll() {
124
+ this.cache = [];
125
+ await this.adapter.clear();
123
126
  }
124
127
  exportJSON() {
125
128
  return {
126
129
  version: 1,
127
- annotations: [...this.annotations]
130
+ annotations: [...this.cache]
128
131
  };
129
132
  }
130
- importJSON(data) {
131
- this.annotations = [...data.annotations];
133
+ async importJSON(data) {
134
+ this.cache = [...data.annotations];
132
135
  this.migrateViewportBuckets();
133
- this.save();
136
+ await this.adapter.clear();
137
+ for (const ann of this.cache) {
138
+ await this.adapter.save(ann);
139
+ }
140
+ }
141
+ async init() {
142
+ const data = await this.adapter.load();
143
+ if (data) {
144
+ this.cache = data.annotations;
145
+ this.migrateViewportBuckets();
146
+ }
134
147
  }
135
148
  migrateViewportBuckets() {
136
- for (const ann of this.annotations) {
149
+ for (const ann of this.cache) {
137
150
  if (ann.viewportBucket == null && ann.viewport) {
138
151
  const width = parseInt(ann.viewport.split("x")[0], 10);
139
152
  ann.viewportBucket = toBucket(width);
140
153
  }
141
154
  }
142
155
  }
143
- load() {
156
+ };
157
+
158
+ // src/core/local-storage-adapter.ts
159
+ var STORAGE_KEY = "remarq:annotations";
160
+ var LocalStorageAdapter = class {
161
+ constructor() {
162
+ this.isMemoryOnly = false;
163
+ this.extraFields = {};
164
+ this.memoryStore = null;
165
+ }
166
+ async load() {
167
+ if (this.isMemoryOnly) return this.memoryStore;
144
168
  try {
145
169
  const raw = localStorage.getItem(STORAGE_KEY);
146
- if (raw) {
147
- const parsed = JSON.parse(raw);
148
- const _a3 = parsed, { version, annotations } = _a3, rest = __objRest(_a3, ["version", "annotations"]);
149
- this.annotations = annotations != null ? annotations : [];
150
- this.extraFields = rest;
151
- this.migrateViewportBuckets();
152
- }
170
+ if (!raw) return null;
171
+ const parsed = JSON.parse(raw);
172
+ const _a3 = parsed, { version, annotations } = _a3, rest = __objRest(_a3, ["version", "annotations"]);
173
+ this.extraFields = rest;
174
+ const store = {
175
+ version: 1,
176
+ annotations: Array.isArray(annotations) ? annotations : []
177
+ };
178
+ this.memoryStore = store;
179
+ return store;
153
180
  } catch (e) {
154
181
  this.isMemoryOnly = true;
182
+ return this.memoryStore;
183
+ }
184
+ }
185
+ async save(annotation) {
186
+ const store = await this.ensureStore();
187
+ const idx = store.annotations.findIndex((a) => a.id === annotation.id);
188
+ if (idx === -1) {
189
+ store.annotations.push(annotation);
190
+ } else {
191
+ store.annotations[idx] = annotation;
155
192
  }
193
+ this.persist(store);
194
+ }
195
+ async remove(id) {
196
+ const store = await this.ensureStore();
197
+ store.annotations = store.annotations.filter((a) => a.id !== id);
198
+ this.persist(store);
199
+ }
200
+ async clear() {
201
+ const store = await this.ensureStore();
202
+ store.annotations = [];
203
+ this.persist(store);
156
204
  }
157
- save() {
205
+ async ensureStore() {
206
+ if (this.memoryStore) return this.memoryStore;
207
+ const loaded = await this.load();
208
+ if (loaded) return loaded;
209
+ this.memoryStore = { version: 1, annotations: [] };
210
+ return this.memoryStore;
211
+ }
212
+ persist(store) {
158
213
  if (this.isMemoryOnly) return;
159
214
  try {
160
215
  const data = __spreadProps(__spreadValues({
161
216
  version: 1
162
217
  }, this.extraFields), {
163
- annotations: this.annotations
218
+ annotations: store.annotations
164
219
  });
165
220
  localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
166
221
  } catch (e) {
@@ -2640,18 +2695,18 @@ var WebRemarq = (() => {
2640
2695
  }
2641
2696
  var WebRemarq = {
2642
2697
  init(opts) {
2643
- var _a3;
2698
+ var _a3, _b;
2644
2699
  if (initialized) return;
2645
2700
  options = opts != null ? opts : {};
2646
2701
  try {
2647
2702
  injectStyles();
2648
- storage = new AnnotationStorage();
2703
+ storage = new AnnotationStorage((_a3 = options.storage) != null ? _a3 : new LocalStorageAdapter());
2649
2704
  themeManager = new ThemeManager(document.body, options.theme);
2650
2705
  overlay = new Overlay(themeManager.container);
2651
2706
  spacingOverlay = new SpacingOverlay(themeManager.container);
2652
2707
  popup = new Popup(themeManager.container);
2653
2708
  markers = new MarkerManager(themeManager.container, handleMarkerClick);
2654
- const position = (_a3 = options.position) != null ? _a3 : "bottom-right";
2709
+ const position = (_b = options.position) != null ? _b : "bottom-right";
2655
2710
  detachedPanel = new DetachedPanel(themeManager.container, (id) => {
2656
2711
  elementCache.delete(id);
2657
2712
  storage.remove(id);
@@ -2684,9 +2739,6 @@ var WebRemarq = (() => {
2684
2739
  onThemeToggle: () => themeManager.toggle(),
2685
2740
  onHelp: () => showShortcutsModal(themeManager.container)
2686
2741
  }, position);
2687
- if (storage.isMemoryOnly) {
2688
- toolbar.setMemoryWarning(true);
2689
- }
2690
2742
  routeObserver = new RouteObserver();
2691
2743
  unsubRoute = routeObserver.onChange(() => refreshMarkers());
2692
2744
  document.addEventListener("click", handleInspectClick, true);
@@ -2694,8 +2746,13 @@ var WebRemarq = (() => {
2694
2746
  document.addEventListener("keydown", handleInspectKeydown);
2695
2747
  setupMutationObserver();
2696
2748
  initViewportListener(() => refreshMarkers());
2749
+ storage.ready.then(() => {
2750
+ if (storage.isMemoryOnly) {
2751
+ toolbar.setMemoryWarning(true);
2752
+ }
2753
+ refreshMarkers();
2754
+ });
2697
2755
  console.debug(`[web-remarq] Initialized on route: ${currentRoute()}`);
2698
- refreshMarkers();
2699
2756
  initialized = true;
2700
2757
  } catch (err) {
2701
2758
  console.error("[web-remarq] Init failed:", err);