@spyglassmc/core 0.4.17 → 0.4.18

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.
@@ -65,6 +65,10 @@ export declare namespace CompletionItem {
65
65
  * Escape `$`, `\`, and `}` in `textToInsert`
66
66
  */
67
67
  function escape(textToInsert: string): string;
68
+ /**
69
+ * Un-escape `$`, `\`, and `}` in `textToInsert`
70
+ */
71
+ function unescape(textToInsert: string): string;
68
72
  }
69
73
  export declare class InsertTextBuilder {
70
74
  #private;
@@ -35,6 +35,13 @@ export var CompletionItem;
35
35
  return textToInsert.replace(/([\\$}])/g, '\\$1');
36
36
  }
37
37
  CompletionItem.escape = escape;
38
+ /**
39
+ * Un-escape `$`, `\`, and `}` in `textToInsert`
40
+ */
41
+ function unescape(textToInsert) {
42
+ return textToInsert.replace(/\\([\\$}])/g, '$1');
43
+ }
44
+ CompletionItem.unescape = unescape;
38
45
  })(CompletionItem || (CompletionItem = {}));
39
46
  export class InsertTextBuilder {
40
47
  #ans = '';
@@ -199,7 +199,10 @@ export function escapeString(value, quote) {
199
199
  if (!quote) {
200
200
  return value;
201
201
  }
202
- return value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"');
202
+ // Un-escape and then re-escape completion
203
+ value = CompletionItem.unescape(value);
204
+ value = value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"');
205
+ return CompletionItem.escape(value);
203
206
  }
204
207
  export const symbol = (node, ctx) => {
205
208
  const path = node.options.parentPath ?? [];
@@ -53,7 +53,7 @@ export class Downloader {
53
53
  }
54
54
  const deserializer = cache.deserializer ?? ((b) => b);
55
55
  const ans = await transformer(deserializer(cachedBuffer));
56
- this.logger.info(`[Downloader] [${id}] Skipped downloading thanks to cache ${cacheChecksum}`);
56
+ this.logger.info(`[Downloader] [${id}] Skipped downloading thanks to cache ${cacheChecksum} (${cachedBuffer.length} bytes)`);
57
57
  return ans;
58
58
  }
59
59
  catch (e) {
@@ -103,7 +103,7 @@ export class Downloader {
103
103
  this.logger.error(`[Downloader] [${id}] Caching file ${cacheUri}`, e);
104
104
  }
105
105
  }
106
- this.logger.info(`[Downloader] [${id}] Downloaded from ${uri}`);
106
+ this.logger.info(`[Downloader] [${id}] Downloaded from ${uri} (${buffer.length} bytes)`);
107
107
  return await transformer(buffer);
108
108
  }
109
109
  catch (e) {
@@ -113,7 +113,7 @@ export class Downloader {
113
113
  const cachedBuffer = await fileUtil.readFile(this.externals, cacheUri);
114
114
  const deserializer = cache.deserializer ?? ((b) => b);
115
115
  const ans = await transformer(deserializer(cachedBuffer));
116
- this.logger.warn(`[Downloader] [${id}] Fell back to cached file ${cacheUri}`);
116
+ this.logger.warn(`[Downloader] [${id}] Fell back to cached file ${cacheUri} (${cachedBuffer.length} bytes)`);
117
117
  return ans;
118
118
  }
119
119
  catch (e) {
@@ -236,14 +236,26 @@ export class ArchiveUriSupporter {
236
236
  if (entries.has(archiveName)) {
237
237
  throw new Error(`A different URI with ${archiveName} already exists`);
238
238
  }
239
+ /// Debug message for #1609
240
+ logger.info(`[ArchiveUriSupporter#create] Extracting archive ${archiveName} from ${uri}`);
239
241
  const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), { stripLevel: typeof info?.startDepth === 'number' ? info.startDepth : 0 });
240
- entries.set(archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
242
+ const newEntries = new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f]));
243
+ /// Debug message for #1609
244
+ logger.info(`[ArchiveUriSupporter#create] Extracted ${files.length} files, adding ${newEntries.size} entries`);
245
+ for (const [path, entry] of [...newEntries.entries()].slice(0, 20)) {
246
+ logger.info(`[ArchiveUriSupporter#create] ${path} (${entry.data.length} bytes)`);
247
+ }
248
+ entries.set(archiveName, newEntries);
241
249
  }
242
250
  }
243
251
  catch (e) {
244
- logger.error(`[SpyglassUriSupporter#create] Bad dependency ${uri}`, e);
252
+ logger.error(`[ArchiveUriSupporter#create] Bad dependency ${uri}`, e);
245
253
  }
246
254
  }
255
+ /// Debug message for #1609
256
+ logger.info(`[ArchiveUriSupporter#create] Finalizing with ${entries.size} archives: ${[
257
+ ...entries.keys(),
258
+ ]}`);
247
259
  return new ArchiveUriSupporter(externals, entries);
248
260
  }
249
261
  }
@@ -37,6 +37,8 @@ export declare class ReadonlySource {
37
37
  * @param offset The index to offset from cursor. Defaults to 0
38
38
  */
39
39
  peek(length?: number, offset?: number): string;
40
+ canRead(length?: number): boolean;
41
+ canReadInLine(): boolean;
40
42
  /**
41
43
  * If the `expectedValue` is right after the cursor, returns `true`. Otherwise returns `false`.
42
44
  *
@@ -48,8 +50,8 @@ export declare class ReadonlySource {
48
50
  tryPeekAfterWhitespace(expectedValue: string): boolean;
49
51
  peekUntil(...terminators: string[]): string;
50
52
  peekLine(): string;
51
- peekRemaining(): string;
52
- matchPattern(regex: RegExp): boolean;
53
+ peekRemaining(offset?: number): string;
54
+ matchPattern(regex: RegExp, offset?: number): boolean;
53
55
  /**
54
56
  * If there is a non-space character between `cursor + offset` (inclusive) and the next newline, returns `true`. Otherwise returns `false`.
55
57
  *
@@ -67,8 +69,6 @@ export declare class Source extends ReadonlySource {
67
69
  get cursor(): number;
68
70
  set cursor(cursor: number);
69
71
  clone(): Source;
70
- canRead(length?: number): boolean;
71
- canReadInLine(): boolean;
72
72
  read(): string;
73
73
  /**
74
74
  * Skips the current character.
@@ -59,6 +59,14 @@ export class ReadonlySource {
59
59
  peek(length = 1, offset = 0) {
60
60
  return this.string.slice(this.innerCursor + offset, this.innerCursor + offset + length);
61
61
  }
62
+ canRead(length = 1) {
63
+ const needed = this.innerCursor + length;
64
+ const available = this.string.length;
65
+ return this.innerCursor + length <= this.string.length;
66
+ }
67
+ canReadInLine() {
68
+ return this.canRead() && this.peek() !== CR && this.peek() !== LF;
69
+ }
62
70
  /**
63
71
  * If the `expectedValue` is right after the cursor, returns `true`. Otherwise returns `false`.
64
72
  *
@@ -93,11 +101,11 @@ export class ReadonlySource {
93
101
  peekLine() {
94
102
  return this.peekUntil(CR, LF);
95
103
  }
96
- peekRemaining() {
97
- return this.string.slice(this.innerCursor);
104
+ peekRemaining(offset = 0) {
105
+ return this.string.slice(this.innerCursor + offset);
98
106
  }
99
- matchPattern(regex) {
100
- return regex.test(this.peekRemaining());
107
+ matchPattern(regex, offset = 0) {
108
+ return regex.test(this.peekRemaining(offset));
101
109
  }
102
110
  /**
103
111
  * If there is a non-space character between `cursor + offset` (inclusive) and the next newline, returns `true`. Otherwise returns `false`.
@@ -149,12 +157,6 @@ export class Source extends ReadonlySource {
149
157
  ans.innerCursor = this.innerCursor;
150
158
  return ans;
151
159
  }
152
- canRead(length = 1) {
153
- return this.innerCursor + length <= this.string.length;
154
- }
155
- canReadInLine() {
156
- return this.canRead() && this.peek() !== CR && this.peek() !== LF;
157
- }
158
160
  read() {
159
161
  return this.string.charAt(this.innerCursor++);
160
162
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spyglassmc/core",
3
- "version": "0.4.17",
3
+ "version": "0.4.18",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",