@typescript/twoslash
Advanced tools
Comparing version 0.3.1 to 0.4.0
@@ -0,1 +1,16 @@ | ||
## 0.4.0 | ||
- Lines with `// prettier-ignore` are stripped, if you want to show it in a code sample, use `/** prettier-ignore */` | ||
- You can request completions at a particular point in a file, note: the results come directly from TS and a | ||
useful but will definitely require some work to massage into being useful (they're un-ordered and un-prioritised.) | ||
To make your life easier it also includes a "completionsPrefix" which is the substring between the position indicated and the nearest dot or space, you can use that to filter the results. | ||
You can see some results in the main README now. | ||
```ts | ||
const myString = "" | ||
myString.s | ||
// ^? | ||
``` | ||
## 0.3.0 | ||
@@ -2,0 +17,0 @@ |
@@ -63,3 +63,3 @@ declare type LZ = typeof import("lz-string"); | ||
queries: { | ||
kind: "query"; | ||
kind: "query" | "completions"; | ||
/** What line is the highlighted identifier on? */ | ||
@@ -70,5 +70,5 @@ line: number; | ||
/** The text of the token which is highlighted */ | ||
text: string; | ||
text?: string; | ||
/** Any attached JSDocs */ | ||
docs: string | undefined; | ||
docs?: string | undefined; | ||
/** The token start which the query indicates */ | ||
@@ -78,2 +78,5 @@ start: number; | ||
length: number; | ||
/** Results for completions at a particular point */ | ||
completions?: import("typescript").CompletionEntry[]; | ||
completionsPrefix?: string; | ||
}[]; | ||
@@ -80,0 +83,0 @@ /** Diagnostic error messages which came up when creating the program */ |
@@ -29,14 +29,14 @@ 'use strict'; | ||
function escapeHtml(text) { | ||
return text.replace(/</g, '<'); | ||
return text.replace(/</g, "<"); | ||
} | ||
function parsePrimitive(value, type) { | ||
switch (type) { | ||
case 'number': | ||
case "number": | ||
return +value; | ||
case 'string': | ||
case "string": | ||
return value; | ||
case 'boolean': | ||
return value.toLowerCase() === 'true' || value.length === 0; | ||
case "boolean": | ||
return value.toLowerCase() === "true" || value.length === 0; | ||
} | ||
@@ -47,4 +47,4 @@ | ||
function cleanMarkdownEscaped(code) { | ||
code = code.replace(/¨D/g, '$'); | ||
code = code.replace(/¨T/g, '~'); | ||
code = code.replace(/¨D/g, "$"); | ||
code = code.replace(/¨T/g, "~"); | ||
return code; | ||
@@ -54,22 +54,22 @@ } | ||
switch (types) { | ||
case 'js': | ||
return 'js'; | ||
case "js": | ||
return "js"; | ||
case 'javascript': | ||
return 'js'; | ||
case "javascript": | ||
return "js"; | ||
case 'ts': | ||
return 'ts'; | ||
case "ts": | ||
return "ts"; | ||
case 'typescript': | ||
return 'ts'; | ||
case "typescript": | ||
return "ts"; | ||
case 'tsx': | ||
return 'tsx'; | ||
case "tsx": | ||
return "tsx"; | ||
case 'jsn': | ||
return 'json'; | ||
case "jsn": | ||
return "json"; | ||
} | ||
throw new Error('Cannot handle the file extension:' + types); | ||
throw new Error("Cannot handle the file extension:" + types); | ||
} | ||
@@ -96,6 +96,29 @@ function getIdentifierTextSpans(ts, sourceFile) { | ||
function stringAroundIndex(string, index) { | ||
var arr = [string[index - 3], string[index - 2], string[index - 1], '>', string[index], '<', string[index + 1], string[index + 2], string[index + 3]]; | ||
return arr.filter(Boolean).join(''); | ||
var arr = [string[index - 3], string[index - 2], string[index - 1], ">", string[index], "<", string[index + 1], string[index + 2], string[index + 3]]; | ||
return arr.filter(Boolean).join(""); | ||
} | ||
/** Came from https://ourcodeworld.com/articles/read/223/how-to-retrieve-the-closest-word-in-a-string-with-a-given-index-in-javascript */ | ||
function getClosestWord(str, pos) { | ||
// Make copies | ||
str = String(str); | ||
pos = Number(pos) >>> 0; // Search for the word's beginning and end. | ||
var left = str.slice(0, pos + 1).search(/\S+$/), | ||
right = str.slice(pos).search(/\s/); // The last word in the string is a special case. | ||
if (right < 0) { | ||
return { | ||
word: str.slice(left), | ||
startPos: left | ||
}; | ||
} // Return the word, using the located bounds to extract it from the string. | ||
return { | ||
word: str.slice(left, right + pos), | ||
startPos: left | ||
}; | ||
} | ||
/** To ensure that errors are matched up right */ | ||
@@ -146,41 +169,75 @@ function validateCodeForErrors(relevantErrors, handbookOptions, extension, originalCode) { | ||
for (var i = 0; i < codeLines.length; i++) { | ||
var line = codeLines[i]; | ||
var highlightMatch = /^\/\/\s*\^+( .+)?$/.exec(line); | ||
var queryMatch = /^\/\/\s*\^\?\s*$/.exec(line); | ||
var _loop = function _loop(_i) { | ||
var line = codeLines[_i]; | ||
if (queryMatch !== null) { | ||
var start = line.indexOf("^"); | ||
queries.push({ | ||
kind: "query", | ||
offset: start, | ||
text: undefined, | ||
docs: undefined, | ||
line: i + removedLines - 1 | ||
}); | ||
log("Removing line " + i + " for having a query"); | ||
var moveForward = function moveForward() { | ||
contentOffset = nextContentOffset; | ||
nextContentOffset += line.length + 1; | ||
}; | ||
var stripLine = function stripLine(logDesc) { | ||
log("Removing line " + _i + " for " + logDesc); | ||
removedLines++; | ||
codeLines.splice(i, 1); | ||
i--; | ||
} else if (highlightMatch !== null) { | ||
var _start = line.indexOf("^"); | ||
codeLines.splice(_i, 1); | ||
_i--; | ||
}; // We only need to run regexes over lines with comments | ||
var length = line.lastIndexOf("^") - _start + 1; | ||
var position = contentOffset + _start; | ||
var description = highlightMatch[1] ? highlightMatch[1].trim() : ""; | ||
highlights.push({ | ||
kind: "highlight", | ||
position: position, | ||
length: length, | ||
description: description, | ||
line: i | ||
}); | ||
log("Removing line " + i + " for having a highlight"); | ||
codeLines.splice(i, 1); | ||
removedLines++; | ||
i--; | ||
if (!line.includes("//")) { | ||
moveForward(); | ||
} else { | ||
contentOffset = nextContentOffset; | ||
nextContentOffset += line.length + 1; | ||
var highlightMatch = /^\/\/\s*\^+( .+)?$/.exec(line); | ||
var queryMatch = /^\/\/\s*\^\?\s*$/.exec(line); // https://regex101.com/r/2yDsRk/1 | ||
var removePrettierIgnoreMatch = /^\s*\/\/ prettier-ignore$/.exec(line); | ||
var completionsQuery = /^\/\/\s*\^\|$/.exec(line); | ||
if (queryMatch !== null) { | ||
var start = line.indexOf("^"); | ||
queries.push({ | ||
kind: "query", | ||
offset: start, | ||
text: undefined, | ||
docs: undefined, | ||
line: _i + removedLines - 1 | ||
}); | ||
stripLine("having a query"); | ||
} else if (highlightMatch !== null) { | ||
var _start = line.indexOf("^"); | ||
var length = line.lastIndexOf("^") - _start + 1; | ||
var position = contentOffset + _start; | ||
var description = highlightMatch[1] ? highlightMatch[1].trim() : ""; | ||
highlights.push({ | ||
kind: "highlight", | ||
position: position, | ||
length: length, | ||
description: description, | ||
line: _i | ||
}); | ||
stripLine("having a highlight"); | ||
} else if (removePrettierIgnoreMatch !== null) { | ||
stripLine("being a prettier ignore"); | ||
} else if (completionsQuery !== null) { | ||
var _start2 = line.indexOf("^"); // prettier-ignore | ||
queries.push({ | ||
kind: "completion", | ||
offset: _start2, | ||
text: undefined, | ||
docs: undefined, | ||
line: _i + removedLines - 1 | ||
}); | ||
stripLine("having a completion query"); | ||
} else { | ||
moveForward(); | ||
} | ||
} | ||
i = _i; | ||
}; | ||
for (var i = 0; i < codeLines.length; i++) { | ||
_loop(i); | ||
} | ||
@@ -197,10 +254,10 @@ | ||
var _loop2 = function _loop2() { | ||
var _loop3 = function _loop3() { | ||
if (_isArray) { | ||
if (_i >= _iterator.length) return "break"; | ||
_ref = _iterator[_i++]; | ||
if (_i2 >= _iterator.length) return "break"; | ||
_ref = _iterator[_i2++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) return "break"; | ||
_ref = _i.value; | ||
_i2 = _iterator.next(); | ||
if (_i2.done) return "break"; | ||
_ref = _i2.value; | ||
} | ||
@@ -242,10 +299,10 @@ | ||
_loop: for (var _iterator = ts.optionDeclarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
_loop2: for (var _iterator = ts.optionDeclarations, _isArray = Array.isArray(_iterator), _i2 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
var _ret = _loop2(); | ||
var _ret = _loop3(); | ||
switch (_ret) { | ||
case "break": | ||
break _loop; | ||
break _loop2; | ||
@@ -267,12 +324,12 @@ default: | ||
for (var i = 0; i < codeLines.length;) { | ||
for (var _i3 = 0; _i3 < codeLines.length;) { | ||
var match = void 0; | ||
if (match = booleanConfigRegexp.exec(codeLines[i])) { | ||
if (match = booleanConfigRegexp.exec(codeLines[_i3])) { | ||
options[match[1]] = true; | ||
setOption(match[1], "true", options, ts); | ||
} else if (match = valuedConfigRegexp.exec(codeLines[i])) { | ||
} else if (match = valuedConfigRegexp.exec(codeLines[_i3])) { | ||
// Skip a filename tag, which should propagate through this stage | ||
if (match[1] === "filename") { | ||
i++; | ||
_i3++; | ||
continue; | ||
@@ -283,7 +340,7 @@ } | ||
} else { | ||
i++; | ||
_i3++; | ||
continue; | ||
} | ||
codeLines.splice(i, 1); | ||
codeLines.splice(_i3, 1); | ||
} | ||
@@ -307,18 +364,18 @@ | ||
for (var i = 0; i < codeLines.length; i++) { | ||
for (var _i4 = 0; _i4 < codeLines.length; _i4++) { | ||
var match = void 0; | ||
if (match = booleanConfigRegexp.exec(codeLines[i])) { | ||
if (match = booleanConfigRegexp.exec(codeLines[_i4])) { | ||
if (match[1] in options) { | ||
options[match[1]] = true; | ||
log("Setting options." + match[1] + " to true"); | ||
codeLines.splice(i, 1); | ||
i--; | ||
codeLines.splice(_i4, 1); | ||
_i4--; | ||
} | ||
} else if (match = valuedConfigRegexp.exec(codeLines[i])) { | ||
} else if (match = valuedConfigRegexp.exec(codeLines[_i4])) { | ||
if (match[1] in options) { | ||
options[match[1]] = match[2]; | ||
log("Setting options." + match[1] + " to " + match[2]); | ||
codeLines.splice(i, 1); | ||
i--; | ||
codeLines.splice(_i4, 1); | ||
_i4--; | ||
} | ||
@@ -408,12 +465,12 @@ } | ||
var _loop3 = function _loop3() { | ||
var _loop4 = function _loop4() { | ||
var _highlights, _partialQueries; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) return "break"; | ||
_ref2 = _iterator2[_i2++]; | ||
if (_i5 >= _iterator2.length) return "break"; | ||
_ref2 = _iterator2[_i5++]; | ||
} else { | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) return "break"; | ||
_ref2 = _i2.value; | ||
_i5 = _iterator2.next(); | ||
if (_i5.done) return "break"; | ||
_ref2 = _i5.value; | ||
} | ||
@@ -435,26 +492,54 @@ | ||
var position = ts.getPositionOfLineAndCharacter(sourceFile, q.line, q.offset); | ||
var quickInfo = ls.getQuickInfoAtPosition(filename, position); | ||
var token = ls.getDefinitionAtPosition(filename, position); // prettier-ignore | ||
var text = "Could not get LSP result: " + stringAroundIndex(env.getSourceFile(filename).text, position); | ||
var docs = undefined; | ||
switch (q.kind) { | ||
case "query": | ||
{ | ||
var quickInfo = ls.getQuickInfoAtPosition(filename, position); | ||
var token = ls.getDefinitionAtPosition(filename, position); // prettier-ignore | ||
if (quickInfo && token && quickInfo.displayParts) { | ||
text = quickInfo.displayParts.map(function (dp) { | ||
return dp.text; | ||
}).join(""); | ||
docs = quickInfo.documentation ? quickInfo.documentation.map(function (d) { | ||
return d.text; | ||
}).join("<br/>") : undefined; | ||
var text = "Could not get LSP result: " + stringAroundIndex(env.getSourceFile(filename).text, position); | ||
var docs = undefined; | ||
if (quickInfo && token && quickInfo.displayParts) { | ||
text = quickInfo.displayParts.map(function (dp) { | ||
return dp.text; | ||
}).join(""); | ||
docs = quickInfo.documentation ? quickInfo.documentation.map(function (d) { | ||
return d.text; | ||
}).join("<br/>") : undefined; | ||
} | ||
var queryResult = { | ||
kind: "query", | ||
text: text, | ||
docs: docs, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return queryResult; | ||
} | ||
case "completion": | ||
{ | ||
var _quickInfo = ls.getCompletionsAtPosition(filename, position - 1, {}); | ||
if (!_quickInfo) { | ||
throw new Error("Twoslash: The ^| query at line " + q.line + " in " + filename + " did not return any completions"); | ||
} | ||
var word = getClosestWord(sourceFile.text, position - 1); | ||
var prefix = sourceFile.text.slice(word.startPos, position); | ||
var lastDot = prefix.split(".").pop() || ""; | ||
var _queryResult = { | ||
kind: "completions", | ||
completions: _quickInfo.entries, | ||
completionPrefix: lastDot, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return _queryResult; | ||
} | ||
} | ||
var queryResult = { | ||
kind: "query", | ||
text: text, | ||
docs: docs, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return queryResult; | ||
}); | ||
@@ -469,6 +554,6 @@ | ||
for (var _iterator2 = nameContent, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
for (var _iterator2 = nameContent, _isArray2 = Array.isArray(_iterator2), _i5 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref2; | ||
var _ret2 = _loop3(); | ||
var _ret2 = _loop4(); | ||
@@ -511,12 +596,12 @@ if (_ret2 === "break") break; | ||
for (var _iterator3 = identifiers, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
for (var _iterator3 = identifiers, _isArray3 = Array.isArray(_iterator3), _i6 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref3; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i3++]; | ||
if (_i6 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i6++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref3 = _i3.value; | ||
_i6 = _iterator3.next(); | ||
if (_i6.done) break; | ||
_ref3 = _i6.value; | ||
} | ||
@@ -557,3 +642,3 @@ | ||
// specific file, and not the global twoslash document. This has to be done here because | ||
// in the above loops, the code for queries/highlights hasn't been stripped yet. | ||
// in the above loops, the code for queries/highlights/etc hasn't been stripped yet. | ||
@@ -565,11 +650,31 @@ | ||
var pos = ts.getPositionOfLineAndCharacter(sourceFile, q.line, q.offset) + fileContentStartIndexInModifiedFile; | ||
queries.push({ | ||
docs: q.docs, | ||
kind: "query", | ||
start: pos, | ||
length: q.text.length, | ||
text: q.text, | ||
offset: q.offset, | ||
line: q.line + linesAbove | ||
}); | ||
switch (q.kind) { | ||
case "query": | ||
{ | ||
queries.push({ | ||
docs: q.docs, | ||
kind: "query", | ||
start: pos + fileContentStartIndexInModifiedFile, | ||
length: q.text.length, | ||
text: q.text, | ||
offset: q.offset, | ||
line: q.line + linesAbove + 1 | ||
}); | ||
break; | ||
} | ||
case "completions": | ||
{ | ||
queries.push({ | ||
completions: q.completions, | ||
kind: "completions", | ||
start: pos + fileContentStartIndexInModifiedFile, | ||
completionsPrefix: q.completionPrefix, | ||
length: 1, | ||
offset: q.offset, | ||
line: q.line + linesAbove + 1 | ||
}); | ||
} | ||
} | ||
}); | ||
@@ -588,12 +693,12 @@ } | ||
for (var _iterator4 = relevantErrors, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
for (var _iterator4 = relevantErrors, _isArray4 = Array.isArray(_iterator4), _i7 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref4; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref4 = _iterator4[_i4++]; | ||
if (_i7 >= _iterator4.length) break; | ||
_ref4 = _iterator4[_i7++]; | ||
} else { | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref4 = _i4.value; | ||
_i7 = _iterator4.next(); | ||
if (_i7.done) break; | ||
_ref4 = _i7.value; | ||
} | ||
@@ -600,0 +705,0 @@ |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=(e=require("debug"))&&"object"==typeof e&&"default"in e?e.default:e,r=require("@typescript/vfs");function n(){return(n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function i(e,t){switch(t){case"number":return+e;case"string":return e;case"boolean":return"true"===e.toLowerCase()||0===e.length}throw new Error("Unknown primitive type "+t+" with - "+e)}var o=t("twoslasher");function a(e){for(var t=[],r=[],n=0,i=0,a=0,s=0;s<e.length;s++){var l=e[s],c=/^\/\/\s*\^+( .+)?$/.exec(l);if(null!==/^\/\/\s*\^\?\s*$/.exec(l)){var u=l.indexOf("^");r.push({kind:"query",offset:u,text:void 0,docs:void 0,line:s+a-1}),o("Removing line "+s+" for having a query"),a++,e.splice(s,1),s--}else if(null!==c){var f=l.indexOf("^"),p=l.lastIndexOf("^")-f+1,g=i+f,h=c[1]?c[1].trim():"";t.push({kind:"highlight",position:g,length:p,description:h,line:s}),o("Removing line "+s+" for having a highlight"),e.splice(s,1),a++,s--}else i=n,n+=l.length+1}return{highlights:t,queries:r}}function s(e,t,r,n){o("Setting "+e+" to "+t);var a=function(){if(l){if(c>=s.length)return"break";u=s[c++]}else{if((c=s.next()).done)return"break";u=c.value}var n=u;if(n.name.toLowerCase()===e.toLowerCase()){switch(n.type){case"number":case"string":case"boolean":r[n.name]=i(t,n.type);break;case"list":r[n.name]=t.split(",").map((function(e){return i(e,n.element.type)}));break;default:if(r[n.name]=n.type.get(t.toLowerCase()),o("Set "+n.name+" to "+r[n.name]),void 0===r[n.name]){var a=Array.from(n.type.keys());throw new Error("Invalid value "+t+" for "+n.name+". Allowed values: "+a.join(","))}}return{v:void 0}}},s=n.optionDeclarations,l=Array.isArray(s),c=0;e:for(s=l?s:s[Symbol.iterator]();;){var u,f=a();switch(f){case"break":break e;default:if("object"==typeof f)return f.v}}throw new Error("No compiler setting named '"+e+"' exists!")}var l=/^\/\/\s?@(\w+)$/,c=/^\/\/\s?@(\w+):\s?(.+)$/,u={errors:[],noErrors:!1,showEmit:!1,showEmittedFile:"index.js",noStaticSemanticInfo:!1,emit:!1,noErrorValidation:!1};exports.twoslasher=function(e,t,i,f,p,g){var h=null!=f?f:require("typescript"),d=null!=p?p:require("lz-string"),v=e,m=function(e){switch(e){case"js":case"javascript":return"js";case"ts":case"typescript":return"ts";case"tsx":return"tsx";case"jsn":return"json"}throw new Error("Cannot handle the file extension:"+e)}(t),y="index."+m;o("\n\nLooking at code: \n```"+m+"\n"+e+"\n```\n");var x={strict:!0,target:h.ScriptTarget.ES2016,allowJs:!0};!function(e){if(e.includes("// @errors "))throw new Error("You have '@errors ' - you're missing the colon after errors");if(e.includes("// @filename "))throw new Error("You have '@filename ' - you're missing the colon after filename")}(e);var w=(e=function(e){return(e=e.replace(/¨D/g,"$")).replace(/¨T/g,"~")}(e)).split(/\r\n?|\n/g),E=n({},function(e){for(var t=n({},u),r=0;r<e.length;r++){var i=void 0;(i=l.exec(e[r]))?i[1]in t&&(t[i[1]]=!0,o("Setting options."+i[1]+" to true"),e.splice(r,1),r--):(i=c.exec(e[r]))&&i[1]in t&&(t[i[1]]=i[2],o("Setting options."+i[1]+" to "+i[2]),e.splice(r,1),r--)}return"errors"in t&&"string"==typeof t.errors&&(t.errors=t.errors.split(" ").map(Number),o("Setting options.error to ",t.errors)),t}(w),{},i),b=function(e,t,r){for(var i=n({},t),o=0;o<e.length;){var a=void 0;if(a=l.exec(e[o]))i[a[1]]=!0,s(a[1],"true",i,r);else{if(!(a=c.exec(e[o]))){o++;continue}if("filename"===a[1]){o++;continue}s(a[1],a[2],i,r)}e.splice(o,1)}return i}(w,x,h),S=null!=g?g:function(e){return r.createDefaultMapFromNodeModules(e)}(b),j=r.createSystem(S),k=r.createVirtualTypeScriptEnvironment(j,[],h,b),A=k.languageService;e=w.join("\n");var O=[],P=[],C=[],F=e.split("// @filename: "),T=1===F.length,q=[y,e.split(/\r\n?|\n/g)],L=(T?[q]:F.map((function(e){var t=e.split(/\r\n?|\n/g),r=t[0],n=t.slice(1);return[r,["// @filename: "+r].concat(n)]}))).filter((function(e){return e[0].length})),I=L.map((function(e){return e[0]})),D=function(){var e,t;if(M){if($>=N.length)return"break";R=N[$++]}else{if(($=N.next()).done)return"break";R=$.value}var r=R[0],n=R[1],i=n.join("\n");k.createFile(r,i);var o=a(n);(e=C).push.apply(e,o.highlights);var s=o.queries.map((function(e,t){var n,i,o=k.getSourceFile(r),a=h.getPositionOfLineAndCharacter(o,e.line,e.offset),s=A.getQuickInfoAtPosition(r,a),l=A.getDefinitionAtPosition(r,a),c="Could not get LSP result: "+[(n=k.getSourceFile(r).text)[(i=a)-3],n[i-2],n[i-1],">",n[i],"<",n[i+1],n[i+2],n[i+3]].filter(Boolean).join(""),u=void 0;return s&&l&&s.displayParts&&(c=s.displayParts.map((function(e){return e.text})).join(""),u=s.documentation?s.documentation.map((function(e){return e.text})).join("<br/>"):void 0),{kind:"query",text:c,docs:u,line:e.line-t,offset:e.offset,file:r}}));(t=O).push.apply(t,s);var l=n.join("\n");k.updateFile(r,l)},N=L,M=Array.isArray(N),$=0;for(N=M?N:N[Symbol.iterator]();;){var R;if("break"===D())break}var Q,U=e.split(/\r\n?|\n/g);a(U),e=U.join("\n"),E.emit&&(null===(Q=k.languageService.getProgram())||void 0===Q||Q.emit());var V=[],_=[];I.forEach((function(t){E.noErrors||(V.push.apply(V,A.getSemanticDiagnostics(t)),V.push.apply(V,A.getSyntacticDiagnostics(t)));var r=k.sys.readFile(t),n=k.getSourceFile(t);if(!n)throw new Error("No sourcefile found for "+t+" in twoslash");if(!E.noStaticSemanticInfo&&!E.showEmit){var i=-1==e.indexOf(r)?0:e.indexOf(r),o=e.slice(0,i).split("\n").length-1,a=function(e,t){var r=[];return function n(i){e.forEachChild(i,(function(i){if(e.isIdentifier(i)){var o=i.getStart(t,!1);r.push({span:e.createTextSpan(o,i.end-o),text:i.getText(t)})}n(i)}))}(t),r}(h,n),s=Array.isArray(a),l=0;for(a=s?a:a[Symbol.iterator]();;){var c;if(s){if(l>=a.length)break;c=a[l++]}else{if((l=a.next()).done)break;c=l.value}var u=c,f=u.span,p=A.getQuickInfoAtPosition(t,f.start);if(p&&p.displayParts){var g=p.displayParts.map((function(e){return e.text})).join(""),d=u.text,v=p.documentation?p.documentation.map((function(e){return e.text})).join("\n"):void 0,m=f.start+i,y=h.createSourceFile("_.ts",e,h.ScriptTarget.ES2015),x=h.getLineAndCharacterOfPosition(y,m);_.push({text:g,docs:v,start:m,length:f.length,line:x.line,character:x.character,targetString:d})}}O.filter((function(e){return e.file===t})).forEach((function(e){var t=h.getPositionOfLineAndCharacter(n,e.line,e.offset)+i;P.push({docs:e.docs,kind:"query",start:t,length:e.text.length,text:e.text,offset:e.offset,line:e.line+o})}))}}));var Y=V.filter((function(e){return e.file&&I.includes(e.file.fileName)}));!E.noErrorValidation&&Y.length&&function(e,t,r,n){var i=e.filter((function(e){return!t.errors.includes(e.code)})),o=i.map((function(e){return e.code})).join(" ");if(i.length){var a="// @errors: "+e.map((function(e){return e.code})).join(" "),s=t.errors.length?" - the annotation specified "+t.errors:"\n\nExpected:\n"+a,l=i.map((function(e){return"["+e.code+"] - "+("string"==typeof e.messageText?e.messageText:e.messageText.messageText)})).join("\n ");throw new Error("Errors were thrown in the sample, but not included in an errors tag: "+o+s+"\n\n "+l+"\n\n## Code\n\n'''"+r+"\n"+n+"\n'''")}}(Y,E,t,v);var z=[],B=Y,J=Array.isArray(B),G=0;for(B=J?B:B[Symbol.iterator]();;){var H;if(J){if(G>=B.length)break;H=B[G++]}else{if((G=B.next()).done)break;H=G.value}var K=H,W=k.sys.readFile(K.file.fileName),X=e.indexOf(W),Z=h.flattenDiagnosticMessageText(K.messageText,"\n").replace(/</g,"<"),ee="err-"+K.code+"-"+K.start+"-"+K.length,te=h.getLineAndCharacterOfPosition(K.file,K.start);z.push({category:K.category,code:K.code,length:K.length,start:K.start?K.start+X:void 0,line:te.line,character:te.character,renderedMessage:Z,id:ee})}if(E.showEmit){var re=A.getEmitOutput(y),ne=re.outputFiles.find((function(e){return e.name===E.showEmittedFile}));if(!ne){var ie=re.outputFiles.map((function(e){return e.name})).join(", ");throw new Error("Cannot find the file "+E.showEmittedFile+" - in "+ie)}e=ne.text,t=ne.name.split(".").pop(),C=[],O=[],_=[]}var oe="https://www.typescriptlang.org/play/#code/"+d.compressToEncodedURIComponent(v),ae="// ---cut---\n";if(e.includes(ae)){var se=e.indexOf(ae)+ae.length,le=e.substr(0,se).split("\n").length-1;e=e.split(ae).pop(),_.forEach((function(e){e.start-=se,e.line-=le})),_=_.filter((function(e){return e.start>-1})),z.forEach((function(e){e.start&&(e.start-=se),e.line&&(e.line-=le)})),z=z.filter((function(e){return e.start&&e.start>-1})),C.forEach((function(e){e.position-=se,e.line-=le})),C=C.filter((function(e){return e.position>-1})),P.forEach((function(e){return e.line-=le})),P=P.filter((function(e){return e.line>-1}))}return{code:e,extension:t,highlights:C,queries:P,staticQuickInfos:_,errors:z,playgroundURL:oe}}; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=(e=require("debug"))&&"object"==typeof e&&"default"in e?e.default:e,r=require("@typescript/vfs");function n(){return(n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function i(e,t){switch(t){case"number":return+e;case"string":return e;case"boolean":return"true"===e.toLowerCase()||0===e.length}throw new Error("Unknown primitive type "+t+" with - "+e)}var o=t("twoslasher");function a(e){for(var t=[],r=[],n=0,i=0,a=0,s=function(s){var c=e[s],u=function(){i=n,n+=c.length+1},f=function(t){o("Removing line "+s+" for "+t),a++,e.splice(s,1),s--};if(c.includes("//")){var p=/^\/\/\s*\^+( .+)?$/.exec(c),h=/^\/\/\s*\^\?\s*$/.exec(c),d=/^\s*\/\/ prettier-ignore$/.exec(c),g=/^\/\/\s*\^\|$/.exec(c);if(null!==h){var m=c.indexOf("^");r.push({kind:"query",offset:m,text:void 0,docs:void 0,line:s+a-1}),f("having a query")}else if(null!==p){var v=c.indexOf("^"),y=c.lastIndexOf("^")-v+1,x=i+v,w=p[1]?p[1].trim():"";t.push({kind:"highlight",position:x,length:y,description:w,line:s}),f("having a highlight")}else if(null!==d)f("being a prettier ignore");else if(null!==g){var b=c.indexOf("^");r.push({kind:"completion",offset:b,text:void 0,docs:void 0,line:s+a-1}),f("having a completion query")}else u()}else u();l=s},l=0;l<e.length;l++)s(l);return{highlights:t,queries:r}}function s(e,t,r,n){o("Setting "+e+" to "+t);var a=function(){if(l){if(c>=s.length)return"break";u=s[c++]}else{if((c=s.next()).done)return"break";u=c.value}var n=u;if(n.name.toLowerCase()===e.toLowerCase()){switch(n.type){case"number":case"string":case"boolean":r[n.name]=i(t,n.type);break;case"list":r[n.name]=t.split(",").map((function(e){return i(e,n.element.type)}));break;default:if(r[n.name]=n.type.get(t.toLowerCase()),o("Set "+n.name+" to "+r[n.name]),void 0===r[n.name]){var a=Array.from(n.type.keys());throw new Error("Invalid value "+t+" for "+n.name+". Allowed values: "+a.join(","))}}return{v:void 0}}},s=n.optionDeclarations,l=Array.isArray(s),c=0;e:for(s=l?s:s[Symbol.iterator]();;){var u,f=a();switch(f){case"break":break e;default:if("object"==typeof f)return f.v}}throw new Error("No compiler setting named '"+e+"' exists!")}var l=/^\/\/\s?@(\w+)$/,c=/^\/\/\s?@(\w+):\s?(.+)$/,u={errors:[],noErrors:!1,showEmit:!1,showEmittedFile:"index.js",noStaticSemanticInfo:!1,emit:!1,noErrorValidation:!1};exports.twoslasher=function(e,t,i,f,p,h){var d=null!=f?f:require("typescript"),g=null!=p?p:require("lz-string"),m=e,v=function(e){switch(e){case"js":case"javascript":return"js";case"ts":case"typescript":return"ts";case"tsx":return"tsx";case"jsn":return"json"}throw new Error("Cannot handle the file extension:"+e)}(t),y="index."+v;o("\n\nLooking at code: \n```"+v+"\n"+e+"\n```\n");var x={strict:!0,target:d.ScriptTarget.ES2016,allowJs:!0};!function(e){if(e.includes("// @errors "))throw new Error("You have '@errors ' - you're missing the colon after errors");if(e.includes("// @filename "))throw new Error("You have '@filename ' - you're missing the colon after filename")}(e);var w=(e=function(e){return(e=e.replace(/¨D/g,"$")).replace(/¨T/g,"~")}(e)).split(/\r\n?|\n/g),b=n({},function(e){for(var t=n({},u),r=0;r<e.length;r++){var i=void 0;(i=l.exec(e[r]))?i[1]in t&&(t[i[1]]=!0,o("Setting options."+i[1]+" to true"),e.splice(r,1),r--):(i=c.exec(e[r]))&&i[1]in t&&(t[i[1]]=i[2],o("Setting options."+i[1]+" to "+i[2]),e.splice(r,1),r--)}return"errors"in t&&"string"==typeof t.errors&&(t.errors=t.errors.split(" ").map(Number),o("Setting options.error to ",t.errors)),t}(w),{},i),E=function(e,t,r){for(var i=n({},t),o=0;o<e.length;){var a=void 0;if(a=l.exec(e[o]))i[a[1]]=!0,s(a[1],"true",i,r);else{if(!(a=c.exec(e[o]))){o++;continue}if("filename"===a[1]){o++;continue}s(a[1],a[2],i,r)}e.splice(o,1)}return i}(w,x,d),S=null!=h?h:function(e){return r.createDefaultMapFromNodeModules(e)}(E),k=r.createSystem(S),j=r.createVirtualTypeScriptEnvironment(k,[],d,E),P=j.languageService;e=w.join("\n");var A=[],O=[],q=[],C=e.split("// @filename: "),T=1===C.length,F=[y,e.split(/\r\n?|\n/g)],L=(T?[F]:C.map((function(e){var t=e.split(/\r\n?|\n/g),r=t[0],n=t.slice(1);return[r,["// @filename: "+r].concat(n)]}))).filter((function(e){return e[0].length})),I=L.map((function(e){return e[0]})),$=function(){var e,t;if(N){if(M>=D.length)return"break";Q=D[M++]}else{if((M=D.next()).done)return"break";Q=M.value}var r=Q[0],n=Q[1],i=n.join("\n");j.createFile(r,i);var o=a(n);(e=q).push.apply(e,o.highlights);var s=o.queries.map((function(e,t){var n,i,o=j.getSourceFile(r),a=d.getPositionOfLineAndCharacter(o,e.line,e.offset);switch(e.kind){case"query":var s=P.getQuickInfoAtPosition(r,a),l=P.getDefinitionAtPosition(r,a),c="Could not get LSP result: "+[(n=j.getSourceFile(r).text)[(i=a)-3],n[i-2],n[i-1],">",n[i],"<",n[i+1],n[i+2],n[i+3]].filter(Boolean).join(""),u=void 0;return s&&l&&s.displayParts&&(c=s.displayParts.map((function(e){return e.text})).join(""),u=s.documentation?s.documentation.map((function(e){return e.text})).join("<br/>"):void 0),{kind:"query",text:c,docs:u,line:e.line-t,offset:e.offset,file:r};case"completion":var f=P.getCompletionsAtPosition(r,a-1,{});if(!f)throw new Error("Twoslash: The ^| query at line "+e.line+" in "+r+" did not return any completions");var p=function(e,t){e=String(e),t=Number(t)>>>0;var r=e.slice(0,t+1).search(/\S+$/),n=e.slice(t).search(/\s/);return n<0?{word:e.slice(r),startPos:r}:{word:e.slice(r,n+t),startPos:r}}(o.text,a-1),h=o.text.slice(p.startPos,a).split(".").pop()||"";return{kind:"completions",completions:f.entries,completionPrefix:h,line:e.line-t,offset:e.offset,file:r}}}));(t=A).push.apply(t,s);var l=n.join("\n");j.updateFile(r,l)},D=L,N=Array.isArray(D),M=0;for(D=N?D:D[Symbol.iterator]();;){var Q;if("break"===$())break}var R,U=e.split(/\r\n?|\n/g);a(U),e=U.join("\n"),b.emit&&(null===(R=j.languageService.getProgram())||void 0===R||R.emit());var V=[],_=[];I.forEach((function(t){b.noErrors||(V.push.apply(V,P.getSemanticDiagnostics(t)),V.push.apply(V,P.getSyntacticDiagnostics(t)));var r=j.sys.readFile(t),n=j.getSourceFile(t);if(!n)throw new Error("No sourcefile found for "+t+" in twoslash");if(!b.noStaticSemanticInfo&&!b.showEmit){var i=-1==e.indexOf(r)?0:e.indexOf(r),o=e.slice(0,i).split("\n").length-1,a=function(e,t){var r=[];return function n(i){e.forEachChild(i,(function(i){if(e.isIdentifier(i)){var o=i.getStart(t,!1);r.push({span:e.createTextSpan(o,i.end-o),text:i.getText(t)})}n(i)}))}(t),r}(d,n),s=Array.isArray(a),l=0;for(a=s?a:a[Symbol.iterator]();;){var c;if(s){if(l>=a.length)break;c=a[l++]}else{if((l=a.next()).done)break;c=l.value}var u=c,f=u.span,p=P.getQuickInfoAtPosition(t,f.start);if(p&&p.displayParts){var h=p.displayParts.map((function(e){return e.text})).join(""),g=u.text,m=p.documentation?p.documentation.map((function(e){return e.text})).join("\n"):void 0,v=f.start+i,y=d.createSourceFile("_.ts",e,d.ScriptTarget.ES2015),x=d.getLineAndCharacterOfPosition(y,v);_.push({text:h,docs:m,start:v,length:f.length,line:x.line,character:x.character,targetString:g})}}A.filter((function(e){return e.file===t})).forEach((function(e){var t=d.getPositionOfLineAndCharacter(n,e.line,e.offset)+i;switch(e.kind){case"query":O.push({docs:e.docs,kind:"query",start:t+i,length:e.text.length,text:e.text,offset:e.offset,line:e.line+o+1});break;case"completions":O.push({completions:e.completions,kind:"completions",start:t+i,completionsPrefix:e.completionPrefix,length:1,offset:e.offset,line:e.line+o+1})}}))}}));var Y=V.filter((function(e){return e.file&&I.includes(e.file.fileName)}));!b.noErrorValidation&&Y.length&&function(e,t,r,n){var i=e.filter((function(e){return!t.errors.includes(e.code)})),o=i.map((function(e){return e.code})).join(" ");if(i.length){var a="// @errors: "+e.map((function(e){return e.code})).join(" "),s=t.errors.length?" - the annotation specified "+t.errors:"\n\nExpected:\n"+a,l=i.map((function(e){return"["+e.code+"] - "+("string"==typeof e.messageText?e.messageText:e.messageText.messageText)})).join("\n ");throw new Error("Errors were thrown in the sample, but not included in an errors tag: "+o+s+"\n\n "+l+"\n\n## Code\n\n'''"+r+"\n"+n+"\n'''")}}(Y,b,t,m);var z=[],B=Y,J=Array.isArray(B),G=0;for(B=J?B:B[Symbol.iterator]();;){var H;if(J){if(G>=B.length)break;H=B[G++]}else{if((G=B.next()).done)break;H=G.value}var K=H,W=j.sys.readFile(K.file.fileName),X=e.indexOf(W),Z=d.flattenDiagnosticMessageText(K.messageText,"\n").replace(/</g,"<"),ee="err-"+K.code+"-"+K.start+"-"+K.length,te=d.getLineAndCharacterOfPosition(K.file,K.start);z.push({category:K.category,code:K.code,length:K.length,start:K.start?K.start+X:void 0,line:te.line,character:te.character,renderedMessage:Z,id:ee})}if(b.showEmit){var re=P.getEmitOutput(y),ne=re.outputFiles.find((function(e){return e.name===b.showEmittedFile}));if(!ne){var ie=re.outputFiles.map((function(e){return e.name})).join(", ");throw new Error("Cannot find the file "+b.showEmittedFile+" - in "+ie)}e=ne.text,t=ne.name.split(".").pop(),q=[],A=[],_=[]}var oe="https://www.typescriptlang.org/play/#code/"+g.compressToEncodedURIComponent(m),ae="// ---cut---\n";if(e.includes(ae)){var se=e.indexOf(ae)+ae.length,le=e.substr(0,se).split("\n").length-1;e=e.split(ae).pop(),_.forEach((function(e){e.start-=se,e.line-=le})),_=_.filter((function(e){return e.start>-1})),z.forEach((function(e){e.start&&(e.start-=se),e.line&&(e.line-=le)})),z=z.filter((function(e){return e.start&&e.start>-1})),q.forEach((function(e){e.position-=se,e.line-=le})),q=q.filter((function(e){return e.position>-1})),O.forEach((function(e){return e.line-=le})),O=O.filter((function(e){return e.line>-1}))}return{code:e,extension:t,highlights:q,queries:O,staticQuickInfos:_,errors:z,playgroundURL:oe}}; | ||
//# sourceMappingURL=twoslash.cjs.production.min.js.map |
@@ -23,14 +23,14 @@ import debug from 'debug'; | ||
function escapeHtml(text) { | ||
return text.replace(/</g, '<'); | ||
return text.replace(/</g, "<"); | ||
} | ||
function parsePrimitive(value, type) { | ||
switch (type) { | ||
case 'number': | ||
case "number": | ||
return +value; | ||
case 'string': | ||
case "string": | ||
return value; | ||
case 'boolean': | ||
return value.toLowerCase() === 'true' || value.length === 0; | ||
case "boolean": | ||
return value.toLowerCase() === "true" || value.length === 0; | ||
} | ||
@@ -41,4 +41,4 @@ | ||
function cleanMarkdownEscaped(code) { | ||
code = code.replace(/¨D/g, '$'); | ||
code = code.replace(/¨T/g, '~'); | ||
code = code.replace(/¨D/g, "$"); | ||
code = code.replace(/¨T/g, "~"); | ||
return code; | ||
@@ -48,22 +48,22 @@ } | ||
switch (types) { | ||
case 'js': | ||
return 'js'; | ||
case "js": | ||
return "js"; | ||
case 'javascript': | ||
return 'js'; | ||
case "javascript": | ||
return "js"; | ||
case 'ts': | ||
return 'ts'; | ||
case "ts": | ||
return "ts"; | ||
case 'typescript': | ||
return 'ts'; | ||
case "typescript": | ||
return "ts"; | ||
case 'tsx': | ||
return 'tsx'; | ||
case "tsx": | ||
return "tsx"; | ||
case 'jsn': | ||
return 'json'; | ||
case "jsn": | ||
return "json"; | ||
} | ||
throw new Error('Cannot handle the file extension:' + types); | ||
throw new Error("Cannot handle the file extension:" + types); | ||
} | ||
@@ -90,6 +90,29 @@ function getIdentifierTextSpans(ts, sourceFile) { | ||
function stringAroundIndex(string, index) { | ||
var arr = [string[index - 3], string[index - 2], string[index - 1], '>', string[index], '<', string[index + 1], string[index + 2], string[index + 3]]; | ||
return arr.filter(Boolean).join(''); | ||
var arr = [string[index - 3], string[index - 2], string[index - 1], ">", string[index], "<", string[index + 1], string[index + 2], string[index + 3]]; | ||
return arr.filter(Boolean).join(""); | ||
} | ||
/** Came from https://ourcodeworld.com/articles/read/223/how-to-retrieve-the-closest-word-in-a-string-with-a-given-index-in-javascript */ | ||
function getClosestWord(str, pos) { | ||
// Make copies | ||
str = String(str); | ||
pos = Number(pos) >>> 0; // Search for the word's beginning and end. | ||
var left = str.slice(0, pos + 1).search(/\S+$/), | ||
right = str.slice(pos).search(/\s/); // The last word in the string is a special case. | ||
if (right < 0) { | ||
return { | ||
word: str.slice(left), | ||
startPos: left | ||
}; | ||
} // Return the word, using the located bounds to extract it from the string. | ||
return { | ||
word: str.slice(left, right + pos), | ||
startPos: left | ||
}; | ||
} | ||
/** To ensure that errors are matched up right */ | ||
@@ -140,41 +163,75 @@ function validateCodeForErrors(relevantErrors, handbookOptions, extension, originalCode) { | ||
for (var i = 0; i < codeLines.length; i++) { | ||
var line = codeLines[i]; | ||
var highlightMatch = /^\/\/\s*\^+( .+)?$/.exec(line); | ||
var queryMatch = /^\/\/\s*\^\?\s*$/.exec(line); | ||
var _loop = function _loop(_i) { | ||
var line = codeLines[_i]; | ||
if (queryMatch !== null) { | ||
var start = line.indexOf("^"); | ||
queries.push({ | ||
kind: "query", | ||
offset: start, | ||
text: undefined, | ||
docs: undefined, | ||
line: i + removedLines - 1 | ||
}); | ||
log("Removing line " + i + " for having a query"); | ||
var moveForward = function moveForward() { | ||
contentOffset = nextContentOffset; | ||
nextContentOffset += line.length + 1; | ||
}; | ||
var stripLine = function stripLine(logDesc) { | ||
log("Removing line " + _i + " for " + logDesc); | ||
removedLines++; | ||
codeLines.splice(i, 1); | ||
i--; | ||
} else if (highlightMatch !== null) { | ||
var _start = line.indexOf("^"); | ||
codeLines.splice(_i, 1); | ||
_i--; | ||
}; // We only need to run regexes over lines with comments | ||
var length = line.lastIndexOf("^") - _start + 1; | ||
var position = contentOffset + _start; | ||
var description = highlightMatch[1] ? highlightMatch[1].trim() : ""; | ||
highlights.push({ | ||
kind: "highlight", | ||
position: position, | ||
length: length, | ||
description: description, | ||
line: i | ||
}); | ||
log("Removing line " + i + " for having a highlight"); | ||
codeLines.splice(i, 1); | ||
removedLines++; | ||
i--; | ||
if (!line.includes("//")) { | ||
moveForward(); | ||
} else { | ||
contentOffset = nextContentOffset; | ||
nextContentOffset += line.length + 1; | ||
var highlightMatch = /^\/\/\s*\^+( .+)?$/.exec(line); | ||
var queryMatch = /^\/\/\s*\^\?\s*$/.exec(line); // https://regex101.com/r/2yDsRk/1 | ||
var removePrettierIgnoreMatch = /^\s*\/\/ prettier-ignore$/.exec(line); | ||
var completionsQuery = /^\/\/\s*\^\|$/.exec(line); | ||
if (queryMatch !== null) { | ||
var start = line.indexOf("^"); | ||
queries.push({ | ||
kind: "query", | ||
offset: start, | ||
text: undefined, | ||
docs: undefined, | ||
line: _i + removedLines - 1 | ||
}); | ||
stripLine("having a query"); | ||
} else if (highlightMatch !== null) { | ||
var _start = line.indexOf("^"); | ||
var length = line.lastIndexOf("^") - _start + 1; | ||
var position = contentOffset + _start; | ||
var description = highlightMatch[1] ? highlightMatch[1].trim() : ""; | ||
highlights.push({ | ||
kind: "highlight", | ||
position: position, | ||
length: length, | ||
description: description, | ||
line: _i | ||
}); | ||
stripLine("having a highlight"); | ||
} else if (removePrettierIgnoreMatch !== null) { | ||
stripLine("being a prettier ignore"); | ||
} else if (completionsQuery !== null) { | ||
var _start2 = line.indexOf("^"); // prettier-ignore | ||
queries.push({ | ||
kind: "completion", | ||
offset: _start2, | ||
text: undefined, | ||
docs: undefined, | ||
line: _i + removedLines - 1 | ||
}); | ||
stripLine("having a completion query"); | ||
} else { | ||
moveForward(); | ||
} | ||
} | ||
i = _i; | ||
}; | ||
for (var i = 0; i < codeLines.length; i++) { | ||
_loop(i); | ||
} | ||
@@ -191,10 +248,10 @@ | ||
var _loop2 = function _loop2() { | ||
var _loop3 = function _loop3() { | ||
if (_isArray) { | ||
if (_i >= _iterator.length) return "break"; | ||
_ref = _iterator[_i++]; | ||
if (_i2 >= _iterator.length) return "break"; | ||
_ref = _iterator[_i2++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) return "break"; | ||
_ref = _i.value; | ||
_i2 = _iterator.next(); | ||
if (_i2.done) return "break"; | ||
_ref = _i2.value; | ||
} | ||
@@ -236,10 +293,10 @@ | ||
_loop: for (var _iterator = ts.optionDeclarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
_loop2: for (var _iterator = ts.optionDeclarations, _isArray = Array.isArray(_iterator), _i2 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
var _ret = _loop2(); | ||
var _ret = _loop3(); | ||
switch (_ret) { | ||
case "break": | ||
break _loop; | ||
break _loop2; | ||
@@ -261,12 +318,12 @@ default: | ||
for (var i = 0; i < codeLines.length;) { | ||
for (var _i3 = 0; _i3 < codeLines.length;) { | ||
var match = void 0; | ||
if (match = booleanConfigRegexp.exec(codeLines[i])) { | ||
if (match = booleanConfigRegexp.exec(codeLines[_i3])) { | ||
options[match[1]] = true; | ||
setOption(match[1], "true", options, ts); | ||
} else if (match = valuedConfigRegexp.exec(codeLines[i])) { | ||
} else if (match = valuedConfigRegexp.exec(codeLines[_i3])) { | ||
// Skip a filename tag, which should propagate through this stage | ||
if (match[1] === "filename") { | ||
i++; | ||
_i3++; | ||
continue; | ||
@@ -277,7 +334,7 @@ } | ||
} else { | ||
i++; | ||
_i3++; | ||
continue; | ||
} | ||
codeLines.splice(i, 1); | ||
codeLines.splice(_i3, 1); | ||
} | ||
@@ -301,18 +358,18 @@ | ||
for (var i = 0; i < codeLines.length; i++) { | ||
for (var _i4 = 0; _i4 < codeLines.length; _i4++) { | ||
var match = void 0; | ||
if (match = booleanConfigRegexp.exec(codeLines[i])) { | ||
if (match = booleanConfigRegexp.exec(codeLines[_i4])) { | ||
if (match[1] in options) { | ||
options[match[1]] = true; | ||
log("Setting options." + match[1] + " to true"); | ||
codeLines.splice(i, 1); | ||
i--; | ||
codeLines.splice(_i4, 1); | ||
_i4--; | ||
} | ||
} else if (match = valuedConfigRegexp.exec(codeLines[i])) { | ||
} else if (match = valuedConfigRegexp.exec(codeLines[_i4])) { | ||
if (match[1] in options) { | ||
options[match[1]] = match[2]; | ||
log("Setting options." + match[1] + " to " + match[2]); | ||
codeLines.splice(i, 1); | ||
i--; | ||
codeLines.splice(_i4, 1); | ||
_i4--; | ||
} | ||
@@ -402,12 +459,12 @@ } | ||
var _loop3 = function _loop3() { | ||
var _loop4 = function _loop4() { | ||
var _highlights, _partialQueries; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) return "break"; | ||
_ref2 = _iterator2[_i2++]; | ||
if (_i5 >= _iterator2.length) return "break"; | ||
_ref2 = _iterator2[_i5++]; | ||
} else { | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) return "break"; | ||
_ref2 = _i2.value; | ||
_i5 = _iterator2.next(); | ||
if (_i5.done) return "break"; | ||
_ref2 = _i5.value; | ||
} | ||
@@ -429,26 +486,54 @@ | ||
var position = ts.getPositionOfLineAndCharacter(sourceFile, q.line, q.offset); | ||
var quickInfo = ls.getQuickInfoAtPosition(filename, position); | ||
var token = ls.getDefinitionAtPosition(filename, position); // prettier-ignore | ||
var text = "Could not get LSP result: " + stringAroundIndex(env.getSourceFile(filename).text, position); | ||
var docs = undefined; | ||
switch (q.kind) { | ||
case "query": | ||
{ | ||
var quickInfo = ls.getQuickInfoAtPosition(filename, position); | ||
var token = ls.getDefinitionAtPosition(filename, position); // prettier-ignore | ||
if (quickInfo && token && quickInfo.displayParts) { | ||
text = quickInfo.displayParts.map(function (dp) { | ||
return dp.text; | ||
}).join(""); | ||
docs = quickInfo.documentation ? quickInfo.documentation.map(function (d) { | ||
return d.text; | ||
}).join("<br/>") : undefined; | ||
var text = "Could not get LSP result: " + stringAroundIndex(env.getSourceFile(filename).text, position); | ||
var docs = undefined; | ||
if (quickInfo && token && quickInfo.displayParts) { | ||
text = quickInfo.displayParts.map(function (dp) { | ||
return dp.text; | ||
}).join(""); | ||
docs = quickInfo.documentation ? quickInfo.documentation.map(function (d) { | ||
return d.text; | ||
}).join("<br/>") : undefined; | ||
} | ||
var queryResult = { | ||
kind: "query", | ||
text: text, | ||
docs: docs, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return queryResult; | ||
} | ||
case "completion": | ||
{ | ||
var _quickInfo = ls.getCompletionsAtPosition(filename, position - 1, {}); | ||
if (!_quickInfo) { | ||
throw new Error("Twoslash: The ^| query at line " + q.line + " in " + filename + " did not return any completions"); | ||
} | ||
var word = getClosestWord(sourceFile.text, position - 1); | ||
var prefix = sourceFile.text.slice(word.startPos, position); | ||
var lastDot = prefix.split(".").pop() || ""; | ||
var _queryResult = { | ||
kind: "completions", | ||
completions: _quickInfo.entries, | ||
completionPrefix: lastDot, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return _queryResult; | ||
} | ||
} | ||
var queryResult = { | ||
kind: "query", | ||
text: text, | ||
docs: docs, | ||
line: q.line - i, | ||
offset: q.offset, | ||
file: filename | ||
}; | ||
return queryResult; | ||
}); | ||
@@ -463,6 +548,6 @@ | ||
for (var _iterator2 = nameContent, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
for (var _iterator2 = nameContent, _isArray2 = Array.isArray(_iterator2), _i5 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref2; | ||
var _ret2 = _loop3(); | ||
var _ret2 = _loop4(); | ||
@@ -505,12 +590,12 @@ if (_ret2 === "break") break; | ||
for (var _iterator3 = identifiers, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
for (var _iterator3 = identifiers, _isArray3 = Array.isArray(_iterator3), _i6 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref3; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i3++]; | ||
if (_i6 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i6++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref3 = _i3.value; | ||
_i6 = _iterator3.next(); | ||
if (_i6.done) break; | ||
_ref3 = _i6.value; | ||
} | ||
@@ -551,3 +636,3 @@ | ||
// specific file, and not the global twoslash document. This has to be done here because | ||
// in the above loops, the code for queries/highlights hasn't been stripped yet. | ||
// in the above loops, the code for queries/highlights/etc hasn't been stripped yet. | ||
@@ -559,11 +644,31 @@ | ||
var pos = ts.getPositionOfLineAndCharacter(sourceFile, q.line, q.offset) + fileContentStartIndexInModifiedFile; | ||
queries.push({ | ||
docs: q.docs, | ||
kind: "query", | ||
start: pos, | ||
length: q.text.length, | ||
text: q.text, | ||
offset: q.offset, | ||
line: q.line + linesAbove | ||
}); | ||
switch (q.kind) { | ||
case "query": | ||
{ | ||
queries.push({ | ||
docs: q.docs, | ||
kind: "query", | ||
start: pos + fileContentStartIndexInModifiedFile, | ||
length: q.text.length, | ||
text: q.text, | ||
offset: q.offset, | ||
line: q.line + linesAbove + 1 | ||
}); | ||
break; | ||
} | ||
case "completions": | ||
{ | ||
queries.push({ | ||
completions: q.completions, | ||
kind: "completions", | ||
start: pos + fileContentStartIndexInModifiedFile, | ||
completionsPrefix: q.completionPrefix, | ||
length: 1, | ||
offset: q.offset, | ||
line: q.line + linesAbove + 1 | ||
}); | ||
} | ||
} | ||
}); | ||
@@ -582,12 +687,12 @@ } | ||
for (var _iterator4 = relevantErrors, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
for (var _iterator4 = relevantErrors, _isArray4 = Array.isArray(_iterator4), _i7 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref4; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref4 = _iterator4[_i4++]; | ||
if (_i7 >= _iterator4.length) break; | ||
_ref4 = _iterator4[_i7++]; | ||
} else { | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref4 = _i4.value; | ||
_i7 = _iterator4.next(); | ||
if (_i7.done) break; | ||
_ref4 = _i7.value; | ||
} | ||
@@ -594,0 +699,0 @@ |
@@ -1,2 +0,1 @@ | ||
/// <reference types="" /> | ||
export declare function escapeHtml(text: string): string; | ||
@@ -9,3 +8,3 @@ export declare function strrep(text: string, count: number): string; | ||
export declare function typesToExtension(types: string): "js" | "ts" | "tsx" | "json"; | ||
export declare function getIdentifierTextSpans(ts: typeof import('typescript'), sourceFile: import('typescript').SourceFile): { | ||
export declare function getIdentifierTextSpans(ts: typeof import("typescript"), sourceFile: import("typescript").SourceFile): { | ||
span: import("typescript").TextSpan; | ||
@@ -15,1 +14,6 @@ text: string; | ||
export declare function stringAroundIndex(string: string, index: number): string; | ||
/** Came from https://ourcodeworld.com/articles/read/223/how-to-retrieve-the-closest-word-in-a-string-with-a-given-index-in-javascript */ | ||
export declare function getClosestWord(str: string, pos: number): { | ||
word: string; | ||
startPos: number; | ||
}; |
{ | ||
"name": "@typescript/twoslash", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"license": "MIT", | ||
@@ -15,3 +15,3 @@ "author": "TypeScript team", | ||
"build": "tsdx build && yarn readme", | ||
"bootstrap": "yarn workspace @typescript/vfs run build && yarn build", | ||
"bootstrap": "yarn build", | ||
"readme": "yarn md-magic README.md --config ./scripts/inline-results.js && yarn prettier README.md --write", | ||
@@ -30,3 +30,3 @@ "test": "tsdx test", | ||
"tslib": "^1.10.0", | ||
"typescript": "*" | ||
"typescript": "3.9.2" | ||
}, | ||
@@ -44,6 +44,6 @@ "jest": { | ||
"dependencies": { | ||
"@typescript/vfs": "1.0.0", | ||
"debug": "^4.1.1", | ||
"lz-string": "^1.4.4", | ||
"@typescript/vfs": "1.0.0" | ||
"lz-string": "^1.4.4" | ||
} | ||
} |
192
README.md
@@ -86,2 +86,6 @@ # TypeScript TwoSlash | ||
### Notes | ||
- Lines which have `// prettier-ignore` are stripped | ||
### API | ||
@@ -209,2 +213,172 @@ | ||
#### `completions.ts` | ||
```ts | ||
console.log | ||
// ^| | ||
``` | ||
Turns to: | ||
> ```ts | ||
> console.log | ||
> ``` | ||
> With: | ||
> ```json | ||
> { | ||
> "code": "See above", | ||
> "extension": "ts", | ||
> "highlights": [], | ||
> "queries": [ | ||
> { | ||
> "completions": [ | ||
> { | ||
> "name": "memory", | ||
> "kind": "property", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "assert", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "clear", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "count", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "countReset", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "debug", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "dir", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "dirxml", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "error", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "exception", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "group", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "groupCollapsed", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "groupEnd", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "info", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "log", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "table", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "time", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "timeEnd", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "timeLog", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "timeStamp", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "trace", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> }, | ||
> { | ||
> "name": "warn", | ||
> "kind": "method", | ||
> "kindModifiers": "declare", | ||
> "sortText": "0" | ||
> } | ||
> ], | ||
> "kind": "completions", | ||
> "start": 9, | ||
> "completionsPrefix": "l", | ||
> "length": 1, | ||
> "offset": 9, | ||
> "line": 1 | ||
> } | ||
> ], | ||
> "staticQuickInfos": "[ 2 items ]", | ||
> "errors": [], | ||
> "playgroundURL": "https://www.typescriptlang.org/play/#code/MYewdgziA2CmB00QHMBQB6dACHusD0AfVIA" | ||
> } | ||
> ``` | ||
#### `cuts_out_unneccessary_code.ts` | ||
@@ -266,3 +440,3 @@ | ||
> "offset": 4, | ||
> "line": 4 | ||
> "line": 5 | ||
> }, | ||
@@ -276,3 +450,3 @@ > { | ||
> "offset": 4, | ||
> "line": 6 | ||
> "line": 7 | ||
> }, | ||
@@ -286,3 +460,3 @@ > { | ||
> "offset": 4, | ||
> "line": 8 | ||
> "line": 9 | ||
> } | ||
@@ -443,3 +617,3 @@ > ], | ||
> "offset": 4, | ||
> "line": 0 | ||
> "line": 1 | ||
> } | ||
@@ -580,3 +754,3 @@ > ], | ||
queries: { | ||
kind: "query" | ||
kind: "query" | "completions" | ||
/** What line is the highlighted identifier on? */ | ||
@@ -587,5 +761,5 @@ line: number | ||
/** The text of the token which is highlighted */ | ||
text: string | ||
text?: string | ||
/** Any attached JSDocs */ | ||
docs: string | undefined | ||
docs?: string | undefined | ||
/** The token start which the query indicates */ | ||
@@ -595,2 +769,6 @@ start: number | ||
length: number | ||
/** Results for completions at a particular point */ | ||
completions?: import("typescript").CompletionEntry[] | ||
/* Completion prefix e.g. the letters before the cursor in the word so you can filter */ | ||
completionsPrefix?: string | ||
}[] | ||
@@ -597,0 +775,0 @@ /** Diagnostic error messages which came up when creating the program */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
234369
1471
799
0