shareable-twoslash-comments 0.0.1

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.
package/.prettierrc ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "printWidth": 100
3
+ }
@@ -0,0 +1,66 @@
1
+ ## Contributing to a TypeScript Playground Plugin
2
+
3
+ ## Contributing
4
+
5
+ You can use `pnpm start` to set up both a copy of Rollup to generate the JS, and Serve to host it.
6
+
7
+ ```sh
8
+ pnpm start
9
+ ```
10
+
11
+ Then set up the TypeScript playground to connect to a dev plugin at `http://localhost:5000/`.
12
+
13
+ #### Plugin API
14
+
15
+ The plugin API is documented in the [interface PlaygroundPlugin in `./src/index.ts`](src/index.ts).
16
+
17
+ Roughly:
18
+
19
+ - There are a set of mounting and un-mounting functions which you can use to handle your UI in the sidebar
20
+ - There are `modelChanged` methods, which are shortcuts to knowing when the code in monaco editor has changed
21
+
22
+ ### Sandbox
23
+
24
+ The plugins are passed copies of the TypeScript sandbox, which is a high level API wrapper to the [`monaco-editor`](https://microsoft.github.io/monaco-editor/). You can learn more about the sandbox on [the TypeScript website](http://www.typescriptlang.org/v2/dev/sandbox/).
25
+
26
+ #### Rollup
27
+
28
+ [Rollup](https://rollupjs.org) is a JavaScript bundler, that will take all of the TypeScript + JavaScript code you reference and then create an AMD bundle for it all. AMD bundles are used in Monaco, TypeScript Sandbox and the Playground - so, this is used for consistency with the rest of the ecosystem.
29
+
30
+ ## Adding a dependency
31
+
32
+ Because most node_modules expect to be running in node, you might have to do some work to get the dependency working on the web.
33
+
34
+ The route to handle this is via rollup:
35
+
36
+ - add a new dependency via `pnpm add xyz`
37
+ - import it into your `index.ts`
38
+ - run `pnpm build` - did it provide some error messages?
39
+ - If it did, you may need to edit your `rollup.config.js`.
40
+ - You could probably start by taking the [rollup config from `playground-plugin-tsquery`](https://github.com/orta/playground-plugin-tsquery/blob/master/rollup.config.js) and by adding any extra externals and globals.
41
+
42
+ #### Serve
43
+
44
+ [Serve](https://github.com/zeit/serve) is used to make a web-server for the dist folder.
45
+
46
+ ## Deployment
47
+
48
+ This module should be deployed to npm when you would like the world to see it, this may mean making your code handle a staging vs production environment (because the URLs will be different.)
49
+
50
+ For example, this is how you can handle getting the URL for a CSS file which is included in your `dist` folder:
51
+
52
+ ```ts
53
+ const isDev = document.location.host.includes("localhost")
54
+ const unpkgURL = "https://unpkg.com/typescript-playground-presentation-mode@latest/dist/slideshow.css"
55
+ const cssHref = isDev ? "http://localhost:5000/slideshow.css" : unpkgURL
56
+ ```
57
+
58
+ ### Post-Deploy
59
+
60
+ Once this is deployed, you can test it on the TypeScript playground by passing in the name of your plugin on npm to the custom plugin box. This is effectively your staging environment.
61
+
62
+ Once you're happy and it's polished, you can apply to have it in the default plugin list.
63
+
64
+ ## Support
65
+
66
+ Ask questions either on the [TypeScript Website issues](https://github.com/microsoft/TypeScript-Website/issues), or in the [TypeScript Community Discord](https://discord.gg/typescript) - in the TypeScript Website channel.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License Copyright (c) 2025 Som Shekhar Mukherjee
2
+
3
+ Permission is hereby
4
+ granted, free of charge, to any person obtaining a copy of this software and
5
+ associated documentation files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice
12
+ (including the next paragraph) shall be included in all copies or substantial
13
+ portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
18
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ ## Shareable Twoslash Comments
2
+
3
+ A TypeScript Playground plugin that embeds twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.
4
+
5
+ ## Running this plugin
6
+
7
+ - [Click this link](https://www.typescriptlang.org/play?install-plugin=shareable-twoslash-comments) to install
8
+
9
+ or
10
+
11
+ - Open up the TypeScript Playground
12
+ - Go the "Plugins" in the sidebar
13
+ - Look for "Plugins from npm"
14
+ - Add "shareable-twoslash-comments"
15
+ - Reload the browser
16
+
17
+ Then it will show up as a tab in the sidebar.
18
+
19
+ ## Contributing
20
+
21
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full details, however, TLDR:
22
+
23
+ ```sh
24
+ git clone ...
25
+ yarn install
26
+ yarn start
27
+ ```
28
+
29
+ Then tick the box for starting plugin development inside the TypeScript Playground.
package/dist/index.js ADDED
@@ -0,0 +1,175 @@
1
+ define(function () { 'use strict';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+
18
+ function __awaiter(thisArg, _arguments, P, generator) {
19
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
+ return new (P || (P = Promise))(function (resolve, reject) {
21
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
25
+ });
26
+ }
27
+
28
+ function __generator(thisArg, body) {
29
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
30
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
31
+ function verb(n) { return function (v) { return step([n, v]); }; }
32
+ function step(op) {
33
+ if (f) throw new TypeError("Generator is already executing.");
34
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
35
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
36
+ if (y = 0, t) op = [op[0] & 2, t.value];
37
+ switch (op[0]) {
38
+ case 0: case 1: t = op; break;
39
+ case 4: _.label++; return { value: op[1], done: false };
40
+ case 5: _.label++; y = op[1]; op = [0]; continue;
41
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
42
+ default:
43
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
44
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
45
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
46
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
47
+ if (t[2]) _.ops.pop();
48
+ _.trys.pop(); continue;
49
+ }
50
+ op = body.call(thisArg, _);
51
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
52
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
53
+ }
54
+ }
55
+
56
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
57
+ var e = new Error(message);
58
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
59
+ };
60
+
61
+ var twoSlashQueryRegex = /(^\s*)(\/\/\s*\^\?)/gm;
62
+ var fillTwoSlashQueries = function (sandbox) { return __awaiter(void 0, void 0, void 0, function () {
63
+ var multilineEnabled, model, worker, text, editOperations, _i, _a, match, commentPrefix, caretOffset, caretPos, quickInfoPos, quickInfoOffset, quickInfo, quickInfoString, quickInfoComment, prevQuickInfoComment, prevQuickInfoLines, prevQuickInfoEndLine;
64
+ return __generator(this, function (_b) {
65
+ switch (_b.label) {
66
+ case 0:
67
+ multilineEnabled = localStorage.getItem("shareable-twoslash-comments/enable-multiline-comments") === "true";
68
+ model = sandbox.getModel();
69
+ return [4 /*yield*/, sandbox.getWorkerProcess()];
70
+ case 1:
71
+ worker = _b.sent();
72
+ text = model.getValue();
73
+ editOperations = [];
74
+ _i = 0, _a = Array.from(text.matchAll(twoSlashQueryRegex));
75
+ _b.label = 2;
76
+ case 2:
77
+ if (!(_i < _a.length)) return [3 /*break*/, 5];
78
+ match = _a[_i];
79
+ commentPrefix = "".concat(match[1], "//").padEnd(match[0].length + 1);
80
+ caretOffset = match.index + match[0].length - 1;
81
+ caretPos = model.getPositionAt(caretOffset);
82
+ quickInfoPos = new sandbox.monaco.Position(caretPos.lineNumber - 1, caretPos.column);
83
+ quickInfoOffset = model.getOffsetAt(quickInfoPos);
84
+ return [4 /*yield*/, worker.getQuickInfoAtPosition("file://" + model.uri.path, quickInfoOffset)];
85
+ case 3:
86
+ quickInfo = _b.sent();
87
+ if (!(quickInfo === null || quickInfo === void 0 ? void 0 : quickInfo.displayParts)) {
88
+ return [3 /*break*/, 4];
89
+ }
90
+ quickInfoString = quickInfo.displayParts.map(function (d) { return d.text; }).join("");
91
+ quickInfoComment = "".concat(match[0], " ").concat(multilineEnabled
92
+ ? quickInfoString.replace(new RegExp(model.getEOL(), "g"), "".concat(model.getEOL()).concat(commentPrefix))
93
+ : quickInfoString.replace(/\r?\n\s*/g, " "));
94
+ prevQuickInfoComment = getPreviousQuickInfoComment({
95
+ model: model,
96
+ lineNumber: caretPos.lineNumber,
97
+ commentPrefix: commentPrefix,
98
+ });
99
+ prevQuickInfoLines = prevQuickInfoComment.split("\n").length;
100
+ prevQuickInfoEndLine = caretPos.lineNumber + prevQuickInfoLines - 1;
101
+ if (prevQuickInfoComment !== quickInfoComment) {
102
+ editOperations.push({
103
+ range: new sandbox.monaco.Range(caretPos.lineNumber, 0, prevQuickInfoEndLine, model.getLineContent(prevQuickInfoEndLine).length + 1),
104
+ text: quickInfoComment,
105
+ });
106
+ }
107
+ _b.label = 4;
108
+ case 4:
109
+ _i++;
110
+ return [3 /*break*/, 2];
111
+ case 5:
112
+ if (editOperations.length > 0) {
113
+ model.pushEditOperations([], editOperations, function () { return null; });
114
+ }
115
+ return [2 /*return*/];
116
+ }
117
+ });
118
+ }); };
119
+ var getPreviousQuickInfoComment = function (_a) {
120
+ var model = _a.model, lineNumber = _a.lineNumber, commentPrefix = _a.commentPrefix;
121
+ var prevQuickInfoLines = [];
122
+ for (var currLineNumber = lineNumber; currLineNumber <= model.getLineCount(); currLineNumber++) {
123
+ var lineContent = model.getLineContent(currLineNumber);
124
+ if (!(lineContent.startsWith(commentPrefix) || lineContent.search(twoSlashQueryRegex) !== -1)) {
125
+ break;
126
+ }
127
+ prevQuickInfoLines.push(lineContent);
128
+ }
129
+ return prevQuickInfoLines.join("\n");
130
+ };
131
+ //# sourceMappingURL=utils.js.map
132
+
133
+ var makePlugin = function (utils) {
134
+ var customPlugin = {
135
+ id: "shareable-twoslash-comments",
136
+ displayName: "Shareable Twoslash Comments",
137
+ didMount: function (sandbox, container) {
138
+ // Create a design system object to handle
139
+ // making DOM elements which fit the playground (and handle mobile/light/dark etc)
140
+ var ds = utils.createDesignSystem(container);
141
+ ds.p("This plugin embeds twoslash (// ^?) type hints as literal comments in your code, making them easy to copy and share.");
142
+ ds.showOptionList([
143
+ {
144
+ blurb: "Preserve multiline types instead of collapsing them to a single line.",
145
+ flag: "shareable-twoslash-comments/enable-multiline-comments",
146
+ display: "Enable multiline comments",
147
+ onchange: function () { return fillTwoSlashQueries(sandbox); },
148
+ },
149
+ ], {
150
+ style: "separated",
151
+ });
152
+ },
153
+ // This is called occasionally as text changes in monaco,
154
+ // it does not directly map 1 keyup to once run of the function
155
+ // because it is intentionally called at most once every 0.3 seconds
156
+ // and then will always run at the end.
157
+ modelChangedDebounce: function (sandbox, model) { return __awaiter(void 0, void 0, void 0, function () {
158
+ return __generator(this, function (_a) {
159
+ fillTwoSlashQueries(sandbox);
160
+ return [2 /*return*/];
161
+ });
162
+ }); },
163
+ // Gives you a chance to remove anything set up,
164
+ // the container itself if wiped of children after this.
165
+ didUnmount: function () {
166
+ console.log("De-focusing plugin");
167
+ },
168
+ };
169
+ return customPlugin;
170
+ };
171
+ //# sourceMappingURL=index.js.map
172
+
173
+ return makePlugin;
174
+
175
+ });
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "shareable-twoslash-comments",
3
+ "version": "0.0.1",
4
+ "main": "dist/index.js",
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
+ "license": "MIT",
7
+ "keywords": [
8
+ "playground-plugin"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/som-sm/shareable-twoslash-comments"
13
+ },
14
+ "scripts": {
15
+ "build": "rollup -c rollup.config.js",
16
+ "compile": "tsc",
17
+ "bootstrap": "node scripts/getDTS.js",
18
+ "start": "concurrently -p \"[{name}]\" -n \"ROLLUP,SITE\" -c \"bgBlue.bold,bgMagenta.bold\" \"yarn rollup -c rollup.config.js --watch\" \"yarn serve dist\"",
19
+ "prepublish": "yarn build",
20
+ "postinstall": "yarn bootstrap && yarn build"
21
+ },
22
+ "devDependencies": {
23
+ "@rollup/plugin-commonjs": "^11.0.2",
24
+ "@rollup/plugin-json": "^4.0.2",
25
+ "@rollup/plugin-node-resolve": "^7.1.0",
26
+ "@rollup/plugin-typescript": "^3.0.0",
27
+ "@types/react": "^16.9.23",
28
+ "concurrently": "^8.2.2",
29
+ "monaco-editor": "^0.32.1",
30
+ "node-fetch": "^2.6.0",
31
+ "prettier": "^3.4.2",
32
+ "rollup": "^1.31.0",
33
+ "serve": "^11.3.0",
34
+ "typescript": "latest",
35
+ "lz-string": "^1.5.0"
36
+ },
37
+ "dependencies": {
38
+ "tslib": "^2.5.0"
39
+ }
40
+ }