shareable-twoslash-comments 0.0.9 → 0.0.11

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 (3) hide show
  1. package/README.md +15 -0
  2. package/dist/index.js +151 -68
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  A TypeScript Playground plugin that injects twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.
4
4
 
5
+ This plugin also supports twoslash arrow queries (`//=>`).
6
+
7
+ If placed at the end of a line, it finds the first position on that line with type information and inserts it.
8
+
9
+ ```ts
10
+ let foo = 1; //=> number
11
+ ```
12
+
13
+ If placed on its own line, it looks at the previous line, finds the first position with type information, and inserts it.
14
+
15
+ ```ts
16
+ let foo = 1;
17
+ //=> number
18
+ ```
19
+
5
20
  https://github.com/user-attachments/assets/5e42a08e-7570-4d04-9434-6a93cd898e7f
6
21
 
7
22
  ## Running this plugin
package/dist/index.js CHANGED
@@ -59,85 +59,147 @@ define(function () { 'use strict';
59
59
  };
60
60
 
61
61
  var twoSlashQueryRegex = /(^[ \t]*)(\/\/\s*\^\?)/gm;
62
- function fillTwoSlashQueries(sandbox) {
63
- return __awaiter(this, void 0, void 0, function () {
64
- var multilineEnabled, truncationDisabled, model, worker, diagnostics, text, editOperations, _i, _a, match, commentPrefix, caretOffset, caretPos, quickInfoPos, quickInfoOffset, quickInfo, quickInfoString, quickInfoComment, prevQuickInfoComment, prevQuickInfoLines, prevQuickInfoEndLine;
65
- var _b, _c;
66
- return __generator(this, function (_d) {
67
- switch (_d.label) {
62
+ var twoSlashArrowQueryRegex = /(^.*)\/\/=>/gm;
63
+ function fillTwoSlashQueries(sandbox_1) {
64
+ return __awaiter(this, arguments, void 0, function (sandbox, isUndoRedoChange) {
65
+ function getLeftMostQuickInfo(_a) {
66
+ return __awaiter(this, arguments, void 0, function (_b) {
67
+ var col, quickInfoPos, quickInfoOffset, quickInfo;
68
+ var line = _b.line, column = _b.column;
69
+ return __generator(this, function (_c) {
70
+ switch (_c.label) {
71
+ case 0:
72
+ col = column;
73
+ _c.label = 1;
74
+ case 1:
75
+ if (!(col <= model.getLineContent(line).length)) return [3 /*break*/, 4];
76
+ quickInfoPos = new sandbox.monaco.Position(line, col);
77
+ quickInfoOffset = model.getOffsetAt(quickInfoPos);
78
+ return [4 /*yield*/, worker.getQuickInfoAtPosition("file://" + model.uri.path, quickInfoOffset)];
79
+ case 2:
80
+ quickInfo = _c.sent();
81
+ if (quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.displayParts) {
82
+ return [2 /*return*/, quickInfo.displayParts.map(function (d) { return d.text; }).join("")];
83
+ }
84
+ _c.label = 3;
85
+ case 3:
86
+ col++;
87
+ return [3 /*break*/, 1];
88
+ case 4: return [2 /*return*/, ""];
89
+ }
90
+ });
91
+ });
92
+ }
93
+ function getPreviousQuickInfoComment(_a) {
94
+ var lineNumber = _a.lineNumber, commentPrefix = _a.commentPrefix;
95
+ var prevQuickInfoLines = [model.getLineContent(lineNumber)];
96
+ for (var currLineNumber = lineNumber + 1; currLineNumber <= model.getLineCount(); currLineNumber++) {
97
+ var lineContent = model.getLineContent(currLineNumber);
98
+ if (!lineContent.startsWith(commentPrefix)) {
99
+ break;
100
+ }
101
+ prevQuickInfoLines.push(lineContent);
102
+ }
103
+ return prevQuickInfoLines.join(model.getEOL());
104
+ }
105
+ var multilineEnabled, truncationDisabled, pauseOnError, model, worker, diagnostics, text, editOperations, matches, _i, matches_1, _a, match, queryType, textBeforeQuery, commentPrefix, isInlineArrowQuery, lineNumber, column, caretOffset, caretPos, quickInfoLine, quickInfoString, quickInfoComment, prevQuickInfoComment, prevQuickInfoLines, prevQuickInfoEndLine;
106
+ if (isUndoRedoChange === void 0) { isUndoRedoChange = false; }
107
+ return __generator(this, function (_b) {
108
+ switch (_b.label) {
68
109
  case 0:
69
110
  multilineEnabled = localStorage.getItem("shareable-twoslash-comments/enable-multiline-comments") === "true";
70
111
  truncationDisabled = localStorage.getItem("shareable-twoslash-comments/disable-truncation") === "true";
112
+ pauseOnError = localStorage.getItem("shareable-twoslash-comments/pause-on-error") === "true";
71
113
  model = sandbox.getModel();
72
114
  return [4 /*yield*/, sandbox.getWorkerProcess()];
73
115
  case 1:
74
- worker = _d.sent();
116
+ worker = _b.sent();
117
+ if (!pauseOnError) return [3 /*break*/, 3];
75
118
  return [4 /*yield*/, Promise.all([
76
119
  worker.getSyntacticDiagnostics("file://" + model.uri.path),
77
120
  worker.getSemanticDiagnostics("file://" + model.uri.path),
78
121
  ])];
79
122
  case 2:
80
- diagnostics = _d.sent();
123
+ diagnostics = _b.sent();
81
124
  if (diagnostics.flat().length > 0) {
82
125
  return [2 /*return*/];
83
126
  }
127
+ _b.label = 3;
128
+ case 3:
84
129
  text = model.getValue();
85
130
  editOperations = [];
86
- _i = 0, _a = Array.from(text.matchAll(twoSlashQueryRegex));
87
- _d.label = 3;
88
- case 3:
89
- if (!(_i < _a.length)) return [3 /*break*/, 6];
90
- match = _a[_i];
91
- commentPrefix = "".concat(match[1], "//").padEnd(match[0].length + 1);
92
- caretOffset = match.index + match[0].length - 2;
93
- caretPos = model.getPositionAt(caretOffset);
94
- quickInfoPos = new sandbox.monaco.Position(caretPos.lineNumber - 1, caretPos.column);
95
- quickInfoOffset = model.getOffsetAt(quickInfoPos);
96
- return [4 /*yield*/, worker.getQuickInfoAtPosition("file://" + model.uri.path, quickInfoOffset)];
131
+ matches = Array.from(text.matchAll(twoSlashQueryRegex))
132
+ .map(function (match) { return ({
133
+ match: match,
134
+ queryType: "twoSlashQuery",
135
+ }); })
136
+ .concat(Array.from(text.matchAll(twoSlashArrowQueryRegex)).map(function (match) { return ({
137
+ match: match,
138
+ queryType: "twoSlashArrowQuery",
139
+ }); }));
140
+ _i = 0, matches_1 = matches;
141
+ _b.label = 4;
97
142
  case 4:
98
- quickInfo = _d.sent();
99
- quickInfoString = (_c = (_b = quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.displayParts) === null || _b === void 0 ? void 0 : _b.map(function (d) { return d.text; }).join("")) !== null && _c !== void 0 ? _c : "";
143
+ if (!(_i < matches_1.length)) return [3 /*break*/, 7];
144
+ _a = matches_1[_i], match = _a.match, queryType = _a.queryType;
145
+ textBeforeQuery = match[1];
146
+ commentPrefix = "".concat(" ".repeat(textBeforeQuery.length), "//").padEnd(match[0].length + 1);
147
+ isInlineArrowQuery = queryType === "twoSlashArrowQuery" && textBeforeQuery.trim().length > 0;
148
+ lineNumber = model.getPositionAt(match.index).lineNumber;
149
+ column = model.getLineMinColumn(lineNumber);
150
+ if (queryType === "twoSlashQuery") {
151
+ caretOffset = match.index + match[0].length - 2;
152
+ caretPos = model.getPositionAt(caretOffset);
153
+ lineNumber = caretPos.lineNumber;
154
+ column = caretPos.column;
155
+ }
156
+ quickInfoLine = lineNumber - (isInlineArrowQuery ? 0 : 1);
157
+ if (quickInfoLine < 1) {
158
+ return [3 /*break*/, 6];
159
+ }
160
+ return [4 /*yield*/, getLeftMostQuickInfo({ line: quickInfoLine, column: column })];
161
+ case 5:
162
+ quickInfoString = _b.sent();
100
163
  quickInfoComment = "".concat(match[0]).concat(quickInfoString.length > 0 ? " " : "").concat(multilineEnabled
101
164
  ? quickInfoString.replace(/\r?\n/g, model.getEOL() + commentPrefix)
102
165
  : truncate(quickInfoString.replace(/\r?\n\s*/g, " "), truncationDisabled ? Number.POSITIVE_INFINITY : 100));
103
- prevQuickInfoComment = getPreviousQuickInfoComment({
104
- model: model,
105
- lineNumber: caretPos.lineNumber,
106
- commentPrefix: commentPrefix,
107
- });
166
+ prevQuickInfoComment = getPreviousQuickInfoComment({ lineNumber: lineNumber, commentPrefix: commentPrefix });
108
167
  prevQuickInfoLines = prevQuickInfoComment.split("\n").length;
109
- prevQuickInfoEndLine = caretPos.lineNumber + prevQuickInfoLines - 1;
168
+ prevQuickInfoEndLine = lineNumber + prevQuickInfoLines - 1;
110
169
  if (prevQuickInfoComment !== quickInfoComment) {
111
170
  editOperations.push({
112
- range: new sandbox.monaco.Range(caretPos.lineNumber, 0, prevQuickInfoEndLine, model.getLineContent(prevQuickInfoEndLine).length + 1),
171
+ range: new sandbox.monaco.Range(lineNumber, 0, prevQuickInfoEndLine, model.getLineContent(prevQuickInfoEndLine).length + 1),
113
172
  text: quickInfoComment,
114
173
  });
115
174
  }
116
- _d.label = 5;
117
- case 5:
118
- _i++;
119
- return [3 /*break*/, 3];
175
+ _b.label = 6;
120
176
  case 6:
177
+ _i++;
178
+ return [3 /*break*/, 4];
179
+ case 7:
121
180
  if (editOperations.length > 0) {
122
- model.applyEdits(editOperations);
181
+ if (!isUndoRedoChange) {
182
+ model.popStackElement();
183
+ }
184
+ try {
185
+ if (isUndoRedoChange) {
186
+ model.applyEdits(editOperations);
187
+ }
188
+ else {
189
+ sandbox.editor.executeEdits("shareable-twoslash-comments", editOperations);
190
+ }
191
+ }
192
+ finally {
193
+ if (!isUndoRedoChange) {
194
+ model.pushStackElement();
195
+ }
196
+ }
123
197
  }
124
198
  return [2 /*return*/];
125
199
  }
126
200
  });
127
201
  });
128
202
  }
129
- function getPreviousQuickInfoComment(_a) {
130
- var model = _a.model, lineNumber = _a.lineNumber, commentPrefix = _a.commentPrefix;
131
- var prevQuickInfoLines = [model.getLineContent(lineNumber)];
132
- for (var currLineNumber = lineNumber + 1; currLineNumber <= model.getLineCount(); currLineNumber++) {
133
- var lineContent = model.getLineContent(currLineNumber);
134
- if (!lineContent.startsWith(commentPrefix)) {
135
- break;
136
- }
137
- prevQuickInfoLines.push(lineContent);
138
- }
139
- return prevQuickInfoLines.join(model.getEOL());
140
- }
141
203
  function debounce(callback, delay) {
142
204
  if (delay === void 0) { delay = 1000; }
143
205
  var timeoutId;
@@ -168,11 +230,21 @@ define(function () { 'use strict';
168
230
  data: { firstMount: true },
169
231
  shouldBeSelected: function () { return true; },
170
232
  didMount: function (sandbox, container) {
233
+ container.style.paddingRight = "8px";
171
234
  // Create a design system object to handle
172
235
  // making DOM elements which fit the playground (and handle mobile/light/dark etc)
173
236
  var ds = utils.createDesignSystem(container);
174
237
  ds.p("This plugin embeds twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.");
175
- ds.showOptionList([
238
+ var optionsContainer = document.createElement("div");
239
+ Object.assign(optionsContainer.style, {
240
+ backgroundColor: "var(--raised-background, rgba(0,0,0,0.05))",
241
+ padding: "0 12px",
242
+ margin: "8px 0",
243
+ border: "1px solid var(--border-color, rgba(0,0,0,0.1))",
244
+ });
245
+ container.appendChild(optionsContainer);
246
+ var optionsDs = utils.createDesignSystem(optionsContainer);
247
+ optionsDs.showOptionList([
176
248
  {
177
249
  blurb: "Preserve multiline types instead of collapsing them to a single line.",
178
250
  flag: "shareable-twoslash-comments/enable-multiline-comments",
@@ -185,14 +257,45 @@ define(function () { 'use strict';
185
257
  display: "Disable truncation",
186
258
  onchange: function () { return fillTwoSlashQueries(sandbox); },
187
259
  },
260
+ {
261
+ blurb: "Pause comment generation if there are any errors in the code.",
262
+ flag: "shareable-twoslash-comments/pause-on-error",
263
+ display: "Pause on error",
264
+ onchange: function () { return fillTwoSlashQueries(sandbox); },
265
+ },
188
266
  ], {
189
267
  style: "separated",
190
268
  });
269
+ ds.p("This plugin also supports twoslash arrow queries (//=>).");
270
+ ds.p("If placed at the end of a line, it finds the first position on that line with type information and inserts it.");
271
+ var code1 = "let foo = 1; //=> number";
272
+ var code1El = ds.code(code1);
273
+ if (code1El.parentElement) {
274
+ code1El.parentElement.style.width = "auto";
275
+ }
276
+ sandbox.monaco.editor.colorize(code1, "typescript", {}).then(function (html) {
277
+ code1El.innerHTML = html;
278
+ });
279
+ ds.p("If placed on its own line, it looks at the previous line, finds the first position with type information, and inserts it.");
280
+ var code2 = "let foo = 1;\n//=> number";
281
+ var code2El = ds.code(code2);
282
+ if (code2El.parentElement) {
283
+ code2El.parentElement.style.width = "auto";
284
+ code2El.parentElement.style.marginBottom = "8px";
285
+ }
286
+ sandbox.monaco.editor.colorize(code2, "typescript", {}).then(function (html) {
287
+ code2El.innerHTML = html;
288
+ });
191
289
  var model = sandbox.getModel();
192
290
  if (customPlugin.data.firstMount) {
193
291
  debouncedFillTwoSlashQueries(sandbox);
194
- model.onDidChangeContent(function () {
195
- debouncedFillTwoSlashQueries(sandbox);
292
+ model.onDidChangeContent(function (e) {
293
+ if (e.isRedoing || e.isUndoing) {
294
+ fillTwoSlashQueries(sandbox, true);
295
+ }
296
+ else {
297
+ debouncedFillTwoSlashQueries(sandbox);
298
+ }
196
299
  });
197
300
  customPlugin.data.firstMount = false;
198
301
  }
@@ -214,26 +317,6 @@ define(function () { 'use strict';
214
317
  };
215
318
  return customPlugin;
216
319
  };
217
- // type GetLeftMostQuickInfo = (args: {
218
- // sandbox: Sandbox;
219
- // model: import("monaco-editor").editor.ITextModel;
220
- // lineNumber: number;
221
- // }) => Promise<number | undefined>;
222
- // const getLeftMostQuickInfo: GetLeftMostQuickInfo = async ({ sandbox, model, lineNumber }) => {
223
- // const worker = await sandbox.getWorkerProcess();
224
- // const lineLength = model.getLineContent(lineNumber).length;
225
- // for (let column = 0; column <= lineLength; column++) {
226
- // const quickInfoPos = new sandbox.monaco.Position(lineNumber, column);
227
- // const quickInfoOffset = model.getOffsetAt(quickInfoPos);
228
- // const quickInfo = await worker.getQuickInfoAtPosition(
229
- // "file://" + model.uri.path,
230
- // quickInfoOffset,
231
- // );
232
- // if (quickInfo) {
233
- // return column;
234
- // }
235
- // }
236
- // };
237
320
  //# sourceMappingURL=index.js.map
238
321
 
239
322
  return makePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shareable-twoslash-comments",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "main": "dist/index.js",
5
5
  "description": "A TypeScript Playground plugin that embeds twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.",
6
6
  "license": "MIT",