diff --git a/autotests/folding/test.ts.fold b/autotests/folding/test.ts.fold
index 39667b1..418ec2f 100644
--- a/autotests/folding/test.ts.fold
+++ b/autotests/folding/test.ts.fold
@@ -1,189 +1,207 @@
///
// TypeScript Test
class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}}
interface Person {
firstName: string;
lastName: string;
}
function greeter(person : Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
JSON.stringify()
console.log("Hello world");
import http = require("http");
import path = require("path");
import URL = url.URL;
import { Readable, Writable } from "stream";
import { isBuffer, isString, isObject } from "util";
const port = 8__88___8;
const baseUrl = new URL(`http://localhost:${port}/`);
const rootDir = path.dirname(__dirname);
const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome";
let browser: "edge" | "chrome" | "none" = defaultBrowser;
let grep: string | undefined;
interface FileBasedTestConfiguration {[setting: string]: string;
}
function swapCase(s: string): string {
return s.replace(/\w/g, (ch) => {
const up = ch.toUpperCase();
return ch === up ? ch.toLowerCase() : up;
});
}
for (var i in pieces) {
switch (true) {
case /^\"?Accession\"?/.test(pieces[i]):
numeration[0] = i;
break;
}}
const enum ResponseCode {
Success = 200,
BadRequest = 400
}
// Substitutions
export function isInOpenInterval(start: number, end: number) {
return tersible(a => a > start && a < end, () => `(${start}...${end})`)
}
-const bar = `${x} ${y}`;
+const bar = `${x} ${y}`;
// readonly
function f1(mt: [number, number], rt: readonly [number, number]) {}
function f2(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {}
type ReadWrite = { -readonly [P in keyof T] : T[P]};
// const assertion
let obj = { x: 10, y: [20, 30], z: { a: { b: 42 }}} as const;
let r2 = { x: 20, y: 10 } as const;
let r2 = {...p} as const;
let p1 = { x: 10, y: 20 as const };
let p2 = { 10 as const, 'foo' as const };
// Definite assignment operator
class Cl {
one?: string;
two!: string;
}
-let x! = 1;
+let x! = 1;
// Function with multiple arguments
const children = [].map>>(element => {
if (!this.identityProvider) {
return element;
}
return element;
-});
+});
// Numerics
var a = 0xA;
var b = 0b1;
var c = 0o7;
var d = 1.1E+3;
var e = 1.E+3;
var f = .1E+3;
var g = 1E+3;
var h = 1.1;
var i = 1.;
var j = .1;
var k = 1;
var l = 1__.e+3_22 | .2____e2 | 0o1_23 | 11__. ;
// Bigint
const binBig = 0b101n;
const octBig = 0o567n;
const hexBig = 0xC0Bn;
const decBig = 123n;
// Types
let a: null = null;
let b: number = 123;
let c: number = 123.456;
let d: string = `Geeks`;
let e: undefined = undefined;
let f: boolean = true;
let g: number = 0b111001; // Binary
let h: number = 0o436; // Octal
-let i: number = 0xadf0d; // Hexa-Decimal
+let i: number = 0xadf0d; // Hexa-Decimal
const query = query<[number], number>(`
SELECT *
FROM statistics
WHERE unit_id = $1`)
function runQuery() {
const query = createQuery<[number[]], Table>(`
some SQL here
`)
return database.execute(query)
}
-aa: string ? string
+aa: string ? string
string // Don't highlight
aa: string assa |
- string
+ string
string ;
string
aa: { string
string } // Don't highlight
-
+
aa: [ string
string ]
-aa: ( string
+aa: ( string
string ) // Don't highlight
aa: string
interface a {
aa: /* comment
*/ string,
bb: /* comment */
number,
cc: // comment
void,
dd:
any,
}
null, <{[key]: () => any}> null
null, <{[key]: () =>{a: number}}> null
// Correctly highlighting regular expressions
dt = ((dt[0] * 1e9 + dt[1]) / 1e6).toFixed(3).replace(/\.?0+$/, '') + 'ms';
(a[0] / 2) / (2)
// Type guards
function isNumber(x: any): x is number {
return typeof x === "number";
}
// Conditional expressions (highlight keywords before ":")
class C {
w = () =>
this.a() ? true : this.b() ? false : true;
z = () =>
- this.b() ? hello : k;
+ this.b() ? hello : k;
+}
+
+function foo(arg: T): T extends B ? number : string {
+ if (arg === "A") return 111;
+ return "returning a string";
+}
+
+// Types and logical `&&` and `||` operators after `as` expression
+Date as any || null;
+
+//Assertions
+const assert: (value: unknown) => asserts value = value => {}
+declare function assertIsString(value: unknown): asserts value is string;
+declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
+declare function assertDefined(value: T): asserts value is NonNullable;
+namespace Debug {
+ export declare function assert(value: unknown, message?: string): asserts value;
+ export declare function assertDefined(value: T): asserts value is NonNullable;
}
diff --git a/autotests/folding/test.tsx.fold b/autotests/folding/test.tsx.fold
index e642959..0441ad1 100644
--- a/autotests/folding/test.tsx.fold
+++ b/autotests/folding/test.tsx.fold
@@ -1,136 +1,146 @@
// TypeScript React
/** @author Willy
* @url https://reactjs.org/ **/
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
function Story(props) {
const SpecificStory = components[props.storyType];
return story={ props.story } attr2="&ref;" attr3="Hello\n" />;
-}
+}
-function
+function
attr1={/> function return class var 0x123 {} &noRef; hello() React.Component() } attr2="&ref;">
/* no comment*/ function /> return class var 0x123 &ref; hello() React.Component()
./> anyWord />
- { function return class var 0x123 hello() React.Component() }
+ { function return class var 0x123 hello() React.Component() }>
> >
> >
> >
/*comment*/attr1/*comment*/= /*comment*/"value"/*comment*/attr2 /*comment*/attr3='a' key/*comment*/key2 />
// Detect Valid tags
/* comment */>>
-{ /* comment
- *//>
+{ /* comment
+ *//>
word . }
return /* comment
multiline *//>/* comment *//>
&& /*comment*//>
& /*comment*//>{ >Hello> }
?/>;
[ /> ( />
,/> =/>
&&/> ||/>
return /> ;
default/> ;
> > />> return >
anyWord
anyWord/*comment*/
.
& |
% /* comment*/
// TODO: Fix this (comment before the tag name):
var x = </**/div>;
// Tag after ":"
annotation: />
annotation: text [/>]
console.log("hello")
// Type assertion in tag
/>> >
/>
// Non-ASCII tag name & attribute
<日本語>日本語>;
本本:本-本 aa本:本 aa:aa /><aaaa:ñ />/>;
{ ... x } y
={2 } z />;
let k1 =
a={10} b="hi" {...o} >
hi hi hi!
>;
let k2 =
a={10} b="hi">
> My Div
>
{(name: string) =>
> My name {name}
>}>;
let k3 = initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })}/>; // No Error
// OK
let k1 = a={10} b="hi"><>>>;
let k2 = a={10} b="hi"><>>;
let k3 = a={10} b="hi"><>>;
let k4 = a={10} b="hi"><>>;
// OK
let k1 =
>
> Hello
>
> world
>
>;
let k2 =
>
> Hello
> {(user: any) =>
>{user.name}
>}
>;
let k3 =
> {1}{"That is a number"}
>;
let k4 = >;
// Empty tags
hello<>
hello<>>; // no whitespace
< > >; // lots of whitespace
< /*starting wrap*/ > /*ending wrap*/>; // comments in the tags
<>hi>; // text inside
<>>hi>
>bye
>>; // children
<>>1><>>2.1>>2.2>>>3>>; // nested fragments
<>#>; // # would cause scanning error if not in jsxtext
// Tags after substitutions in templates
`aaa${>>//comment
/*comment*//>}`
// Don't highlight tags within type declaration
type T12 = ReturnType<(() => T)>;
type T13 = ReturnType<([]>() => T)>;
type T14 = ReturnType;
type T15 = ReturnType<(s: string) => void>;
// Don't highlight tags within variable declaration
let myIdentity: (arg: T) => T = />;
var myIdentity: (arg: U) => U = identity;
const myIdentity: {(arg: T): T} = identity;
// Don't highlight tags within interfaces and classes
interface GenericIdentityFn {(arg: T): T;
}
class Handler {
info: (arg: T): T ;
> >
}
+
+// Highlight "(
+ arg: T
+) => {
+ const a = arg
+ return a
+}
+> text extends I/>> // Here "" is a tag
diff --git a/autotests/html/test.ts.html b/autotests/html/test.ts.html
index 3744d98..47e63d9 100644
--- a/autotests/html/test.ts.html
+++ b/autotests/html/test.ts.html
@@ -1,196 +1,214 @@
test.ts
/// <reference types="node"/>// TypeScript Testclass Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
interface Person {
firstName: string;
lastName: string;
}
functiongreeter(person : Person) {
return"Hello, " + person.firstName + " " + person.lastName;
}
let user = newStudent("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
JSON.stringify()
console.log("Hello world");
import http = require("http");
import path = require("path");
import URL = url.URL;
import { Readable, Writable } from"stream";
import { isBuffer, isString, isObject } from"util";
const port = 8__88___8;
const baseUrl = newURL(`http://localhost:${port}/`);
const rootDir = path.dirname(__dirname);
const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome";
let browser: "edge" | "chrome" | "none" = defaultBrowser;
let grep: string | undefined;
interface FileBasedTestConfiguration {
[setting: string]: string;
}
functionswapCase(s: string): string {
returns.replace(/\w/g, (ch) => {
const up = ch.toUpperCase();
return ch === up ? ch.toLowerCase() : up;
});
}
for (var i in pieces) {
switch (true) {
case/^\"?Accession\"?/.test(pieces[i]):
numeration[0] = i;
break;
}
}
constenum ResponseCode {
Success = 200,
BadRequest = 400
}
// SubstitutionsexportfunctionisInOpenInterval(start: number, end: number) {
returntersible(a => a > start && a < end, () =>`(${start}...${end})`)
}
-const bar = `${x}${y}`;
+const bar = `${x}${y}`;
// readonlyfunctionf1(mt: [number, number], rt: readonly [number, number]) {
}
functionf2(ma: string[], ra: readonlystring[], mt: [string, string], rt: readonly [string, string]) {
}
type ReadWrite<T> = { -readonly [P inkeyof T] : T[P] };
// const assertionlet obj = { x: 10, y: [20, 30], z: { a: { b: 42 } } } asconst;
let r2 = { x: 20, y: 10 } asconst;
let r2 = {...p} asconst;
let p1 = { x: 10, y: 20asconst };
let p2 = { 10asconst, 'foo'asconst };
// Definite assignment operatorclass Cl {
one?: string;
two!: string;
}
-let x! = 1;
+let x! = 1;
// Function with multiple argumentsconst children = [].map<Set<Map<number, string>>>(element => {
if (!this.identityProvider) {
return element;
}
return element;
-});
+});
// Numericsvar a = 0xA;
var b = 0b1;
var c = 0o7;
var d = 1.1E+3;
var e = 1.E+3;
var f = .1E+3;
var g = 1E+3;
var h = 1.1;
var i = 1.;
var j = .1;
var k = 1;
var l = 1__.e+3_22 | .2____e2 | 0o1_23 | 11__. ;
// Bigintconst binBig = 0b101n;
const octBig = 0o567n;
const hexBig = 0xC0Bn;
const decBig = 123n;
// Typeslet a: null = null;
let b: number = 123;
let c: number = 123.456;
let d: string = `Geeks`;
let e: undefined = undefined;
let f: boolean = true;
let g: number = 0b111001; // Binarylet h: number = 0o436; // Octal
-let i: number = 0xadf0d; // Hexa-Decimal
+let i: number = 0xadf0d; // Hexa-Decimalconst query = query<[number], number>(` SELECT * FROM statistics WHERE unit_id = $1`)
functionrunQuery() {
const query = createQuery<[number[]], Table<Columns>>(` some SQL here `)
returndatabase.execute(query)
}
-aa: <sdf/> string ?<ssd/> string
+aa: <sdf/> string ?<ssd/> string
string // Don't highlight
aa: string assa |
- string
+ string
string ;
string
aa: { string
string } // Don't highlight
-
+
aa: [ stringstring ]
-aa: ( string
+aa: ( string
string ) // Don't highlight
aa: string <string>
interface a {
aa: /* comment */string,
bb: /* comment */number,
cc: // commentvoid,
dd:
any,
}
null, <{[key]: () =>any}> nullnull, <{[key]: () =>{a: number}}> null// Correctly highlighting regular expressions
dt = ((dt[0] * 1e9 + dt[1]) / 1e6).toFixed(3).replace(/\.?0+$/, '') + 'ms';
(a[0] / 2) / (2)
// Type guardsfunctionisNumber(x: any): x isnumber {
returntypeof x === "number";
}
// Conditional expressions (highlight keywords before ":")class C {
w = () =>this.a() ? true : this.b() ? false : true;
z = () =>
- this.b() ? hello : k;
+ this.b() ? hello : k;
+}
+
+functionfoo<T extends X>(arg: T): T extends B ? number : string {
+ if (arg === "A") return <T extends B ? number : never>111;
+ return <T extends B ? never : string>"returning a string";
+}
+
+// Types and logical `&&` and `||` operators after `as` expression
+Dateasany || null;
+
+//Assertions
+const assert: (value: unknown) =>asserts value = value => {}
+declarefunctionassertIsString(value: unknown): asserts value isstring;
+declarefunctionassertIsArrayOfStrings(value: unknown): asserts value isstring[];
+declarefunctionassertDefined<T>(value: T): asserts value isNonNullable<T>;
+namespaceDebug {
+ exportdeclarefunctionassert(value: unknown, message?: string): asserts value;
+ exportdeclarefunctionassertDefined<T>(value: T): asserts value isNonNullable<T>;
}