shareable-twoslash-comments 0.0.10 → 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 +138 -65
  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,12 +59,53 @@ 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, pauseOnError, 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";
@@ -72,76 +113,93 @@ define(function () { 'use strict';
72
113
  model = sandbox.getModel();
73
114
  return [4 /*yield*/, sandbox.getWorkerProcess()];
74
115
  case 1:
75
- worker = _d.sent();
116
+ worker = _b.sent();
76
117
  if (!pauseOnError) return [3 /*break*/, 3];
77
118
  return [4 /*yield*/, Promise.all([
78
119
  worker.getSyntacticDiagnostics("file://" + model.uri.path),
79
120
  worker.getSemanticDiagnostics("file://" + model.uri.path),
80
121
  ])];
81
122
  case 2:
82
- diagnostics = _d.sent();
123
+ diagnostics = _b.sent();
83
124
  if (diagnostics.flat().length > 0) {
84
125
  return [2 /*return*/];
85
126
  }
86
- _d.label = 3;
127
+ _b.label = 3;
87
128
  case 3:
88
129
  text = model.getValue();
89
130
  editOperations = [];
90
- _i = 0, _a = Array.from(text.matchAll(twoSlashQueryRegex));
91
- _d.label = 4;
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;
92
142
  case 4:
93
- if (!(_i < _a.length)) return [3 /*break*/, 7];
94
- match = _a[_i];
95
- commentPrefix = "".concat(match[1], "//").padEnd(match[0].length + 1);
96
- caretOffset = match.index + match[0].length - 2;
97
- caretPos = model.getPositionAt(caretOffset);
98
- quickInfoPos = new sandbox.monaco.Position(caretPos.lineNumber - 1, caretPos.column);
99
- quickInfoOffset = model.getOffsetAt(quickInfoPos);
100
- return [4 /*yield*/, worker.getQuickInfoAtPosition("file://" + model.uri.path, quickInfoOffset)];
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 })];
101
161
  case 5:
102
- quickInfo = _d.sent();
103
- 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 : "";
162
+ quickInfoString = _b.sent();
104
163
  quickInfoComment = "".concat(match[0]).concat(quickInfoString.length > 0 ? " " : "").concat(multilineEnabled
105
164
  ? quickInfoString.replace(/\r?\n/g, model.getEOL() + commentPrefix)
106
165
  : truncate(quickInfoString.replace(/\r?\n\s*/g, " "), truncationDisabled ? Number.POSITIVE_INFINITY : 100));
107
- prevQuickInfoComment = getPreviousQuickInfoComment({
108
- model: model,
109
- lineNumber: caretPos.lineNumber,
110
- commentPrefix: commentPrefix,
111
- });
166
+ prevQuickInfoComment = getPreviousQuickInfoComment({ lineNumber: lineNumber, commentPrefix: commentPrefix });
112
167
  prevQuickInfoLines = prevQuickInfoComment.split("\n").length;
113
- prevQuickInfoEndLine = caretPos.lineNumber + prevQuickInfoLines - 1;
168
+ prevQuickInfoEndLine = lineNumber + prevQuickInfoLines - 1;
114
169
  if (prevQuickInfoComment !== quickInfoComment) {
115
170
  editOperations.push({
116
- 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),
117
172
  text: quickInfoComment,
118
173
  });
119
174
  }
120
- _d.label = 6;
175
+ _b.label = 6;
121
176
  case 6:
122
177
  _i++;
123
178
  return [3 /*break*/, 4];
124
179
  case 7:
125
180
  if (editOperations.length > 0) {
126
- 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
+ }
127
197
  }
128
198
  return [2 /*return*/];
129
199
  }
130
200
  });
131
201
  });
132
202
  }
133
- function getPreviousQuickInfoComment(_a) {
134
- var model = _a.model, lineNumber = _a.lineNumber, commentPrefix = _a.commentPrefix;
135
- var prevQuickInfoLines = [model.getLineContent(lineNumber)];
136
- for (var currLineNumber = lineNumber + 1; currLineNumber <= model.getLineCount(); currLineNumber++) {
137
- var lineContent = model.getLineContent(currLineNumber);
138
- if (!lineContent.startsWith(commentPrefix)) {
139
- break;
140
- }
141
- prevQuickInfoLines.push(lineContent);
142
- }
143
- return prevQuickInfoLines.join(model.getEOL());
144
- }
145
203
  function debounce(callback, delay) {
146
204
  if (delay === void 0) { delay = 1000; }
147
205
  var timeoutId;
@@ -172,11 +230,21 @@ define(function () { 'use strict';
172
230
  data: { firstMount: true },
173
231
  shouldBeSelected: function () { return true; },
174
232
  didMount: function (sandbox, container) {
233
+ container.style.paddingRight = "8px";
175
234
  // Create a design system object to handle
176
235
  // making DOM elements which fit the playground (and handle mobile/light/dark etc)
177
236
  var ds = utils.createDesignSystem(container);
178
237
  ds.p("This plugin embeds twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.");
179
- 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([
180
248
  {
181
249
  blurb: "Preserve multiline types instead of collapsing them to a single line.",
182
250
  flag: "shareable-twoslash-comments/enable-multiline-comments",
@@ -198,11 +266,36 @@ define(function () { 'use strict';
198
266
  ], {
199
267
  style: "separated",
200
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
+ });
201
289
  var model = sandbox.getModel();
202
290
  if (customPlugin.data.firstMount) {
203
291
  debouncedFillTwoSlashQueries(sandbox);
204
- model.onDidChangeContent(function () {
205
- debouncedFillTwoSlashQueries(sandbox);
292
+ model.onDidChangeContent(function (e) {
293
+ if (e.isRedoing || e.isUndoing) {
294
+ fillTwoSlashQueries(sandbox, true);
295
+ }
296
+ else {
297
+ debouncedFillTwoSlashQueries(sandbox);
298
+ }
206
299
  });
207
300
  customPlugin.data.firstMount = false;
208
301
  }
@@ -224,26 +317,6 @@ define(function () { 'use strict';
224
317
  };
225
318
  return customPlugin;
226
319
  };
227
- // type GetLeftMostQuickInfo = (args: {
228
- // sandbox: Sandbox;
229
- // model: import("monaco-editor").editor.ITextModel;
230
- // lineNumber: number;
231
- // }) => Promise<number | undefined>;
232
- // const getLeftMostQuickInfo: GetLeftMostQuickInfo = async ({ sandbox, model, lineNumber }) => {
233
- // const worker = await sandbox.getWorkerProcess();
234
- // const lineLength = model.getLineContent(lineNumber).length;
235
- // for (let column = 0; column <= lineLength; column++) {
236
- // const quickInfoPos = new sandbox.monaco.Position(lineNumber, column);
237
- // const quickInfoOffset = model.getOffsetAt(quickInfoPos);
238
- // const quickInfo = await worker.getQuickInfoAtPosition(
239
- // "file://" + model.uri.path,
240
- // quickInfoOffset,
241
- // );
242
- // if (quickInfo) {
243
- // return column;
244
- // }
245
- // }
246
- // };
247
320
  //# sourceMappingURL=index.js.map
248
321
 
249
322
  return makePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shareable-twoslash-comments",
3
- "version": "0.0.10",
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",