1 Commits

Author SHA1 Message Date
Arnavion e9c3ee5edf tsnext 2016-09-16 09:45:16 -07:00
31 changed files with 681 additions and 728 deletions
+60 -68
View File
@@ -18,17 +18,14 @@
* limitations under the License.
*/
import * as fs from "fs";
import * as path from "path";
import { File, FileTransform } from "async-build";
import { FileTransform } from "async-build";
import * as AST from "./typescript/ast";
import { Compiler } from "./typescript/compiler";
import { walk } from "./typescript/walker";
function flatten<T>(arr: T[][]): T[] {
var result: T[] = [];
let result: T[] = [];
for (const a of arr) {
result = result.concat(a);
@@ -37,7 +34,7 @@ function flatten<T>(arr: T[][]): T[] {
return result;
}
var sorter = (() => {
const sorter = (() => {
function visibilitySorter(value1: { isPrivate?: boolean; isProtected?: boolean; }, value2: { isPrivate?: boolean; isProtected?: boolean; }) {
if (value1.isPrivate === value2.isPrivate && value1.isProtected === value2.isProtected) {
return 0;
@@ -62,10 +59,10 @@ var sorter = (() => {
return 0;
}
var types = [AST.Property, AST.Function, AST.Interface, AST.Class, AST.Enum];
const types = [AST.Property, AST.Function, AST.Interface, AST.Class, AST.Enum];
function typeSorter(value1: AST.ModuleMember | AST.NamespaceMember, value2: AST.ModuleMember | AST.NamespaceMember) {
var type1Index = -1;
var type2Index = -1;
let type1Index = -1;
let type2Index = -1;
types.every((type, index) => {
if (value1 instanceof type) {
@@ -84,11 +81,11 @@ var sorter = (() => {
return value1.name.localeCompare(value2.name);
}
var sorters: ((value1: AST.ModuleMember, value2: AST.ModuleMember) => number)[] = [visibilitySorter, typeSorter, nameSorter];
const sorters: ((value1: AST.ModuleMember, value2: AST.ModuleMember) => number)[] = [visibilitySorter, typeSorter, nameSorter];
return (value1: AST.ModuleMember, value2: AST.ModuleMember) => {
for (var i = 0; i < sorters.length; i++) {
var result = sorters[i](value1, value2);
for (const sorter of sorters) {
const result = sorter(value1, value2);
if (result !== 0) {
return result;
@@ -110,10 +107,10 @@ function sanitize(str: string) {
function toVariableName(item: { name: string }) {
// TODO: Handle non-letters (are both their toLowerCase() and toUpperCase())
var name = item.name;
var result = "";
const name = item.name;
let result = "";
for (var i = 0; i < name.length; i++) {
for (let i = 0; i < name.length; i++) {
if (name[i] === name[i].toLowerCase()) {
// This is lower case. Write it as lower case.
result += name[i];
@@ -168,15 +165,15 @@ function toUsageName(item: AST.Class | AST.Interface | AST.Function | AST.Proper
}
if (item.parent instanceof AST.Namespace) {
if ((<AST.Class | AST.Interface | AST.Function | AST.Enum>item).isPrivate) {
if ((item as AST.CanBePrivate).isPrivate) {
return item.name;
}
return item.fullName;
}
if ((<AST.Function>item).isStatic) {
return toUsageName(<AST.Class | AST.Interface>item.parent) + '.' + item.name;
if ((item as AST.CanBeStatic).isStatic) {
return toUsageName(item.parent as AST.Class | AST.Interface) + '.' + item.name;
}
return toVariableName(item.parent) + '.' + item.name;
@@ -187,13 +184,12 @@ function toId(item: { fullName?: string; name: string; }): string {
}
function toLink(item: AST.ModuleMember | AST.EnumMember | AST.TypeReference): string {
var result = `<a href="#${ toId(item) }">${ sanitize(item.name) }`;
let result = `<a href="#${ toId(item) }">${ sanitize(item.name) }`;
var itemWithGenerics = <AST.HasGenerics>item;
if (itemWithGenerics.generics !== undefined && itemWithGenerics.generics.length > 0) {
var generics = <(string | AST.TypeReference | AST.IntrinsicTypeReference)[]>itemWithGenerics.generics;
if (AST.hasGenerics(item) && item.generics.length > 0) {
const generics = item.generics as (string | AST.TypeReference | AST.IntrinsicTypeReference)[];
result += sanitize(`.<${ generics.map(generic =>
(generic instanceof AST.TypeReference || generic instanceof AST.IntrinsicTypeReference) ? generic.name : <string>generic
(generic instanceof AST.TypeReference || generic instanceof AST.IntrinsicTypeReference) ? generic.name : generic
).join(', ') }>`);
}
@@ -203,9 +199,9 @@ function toLink(item: AST.ModuleMember | AST.EnumMember | AST.TypeReference): st
}
function writeDescription(text: string): string {
var result = sanitize(text).replace(/\{@link ([^} ]+)\}/g, (substring, linkTarget) => `<a href="#${ linkTarget }">${ linkTarget }</a>`);
let result = sanitize(text).replace(/\{@link ([^} ]+)\}/g, (substring, linkTarget) => `<a href="#${ linkTarget }">${ linkTarget }</a>`);
var inCodeBlock = false;
let inCodeBlock = false;
result = result.split("\n").map(line => {
if (line.substr(0, " ".length) === " ") {
line = line.substr(" ".length);
@@ -288,7 +284,7 @@ function functionToHtml(func: AST.Function): string[] {
}
function interfaceToHtml(interfase: AST.Interface): string[] {
var members: AST.InterfaceMember[] = [];
const members: AST.InterfaceMember[] = [];
Object.keys(interfase.members).forEach(memberName => members.push(interfase.members[memberName]));
members.sort(sorter);
@@ -310,7 +306,7 @@ function interfaceToHtml(interfase: AST.Interface): string[] {
return functionToHtml(member).map(indenter(2));
}
else {
throw new Error(`Unrecognized member type: ${ (<any>member.constructor).name }`);
throw new Error(`Unrecognized member type: ${ (member as any).constructor.name }`);
}
}))).concat([
' </dd>',
@@ -320,7 +316,7 @@ function interfaceToHtml(interfase: AST.Interface): string[] {
}
function classToHtml(clazz: AST.Class): string[] {
var members: AST.InterfaceMember[] = [];
const members: AST.InterfaceMember[] = [];
Object.keys(clazz.members).forEach(memberName => members.push(clazz.members[memberName]));
members.sort(sorter);
@@ -330,7 +326,7 @@ function classToHtml(clazz: AST.Class): string[] {
clazz.isAbstract ? ' abstract' : ''}${
clazz.isPrivate ? ' private' : ''}">`,
` <dt class="name">class ${ toLink(clazz) }${
(clazz.baseType !== null) ? ` extends ${ (clazz.baseType instanceof AST.TypeReference) ? toLink(<AST.TypeReference>clazz.baseType) : clazz.baseType.name }` : '' }${
(clazz.baseType !== null) ? ` extends ${ (clazz.baseType instanceof AST.TypeReference) ? toLink(clazz.baseType) : clazz.baseType.name }` : '' }${
(clazz.interfaces.length > 0) ? ` implements ${ clazz.interfaces.map(interfase => interfase instanceof AST.TypeReference ? toLink(interfase) : interfase.name).join(', ') }` : ''}</dt>`,
' <dd class="description">',
` ${ writeDescription(clazz.description) }`,
@@ -350,7 +346,7 @@ function classToHtml(clazz: AST.Class): string[] {
return functionToHtml(member).map(indenter(2));
}
else {
throw new Error(`Unrecognized member type: ${ (<any>member.constructor).name }`);
throw new Error(`Unrecognized member type: ${ (member as any).constructor.name }`);
}
}))).concat([
' </dd>',
@@ -406,30 +402,26 @@ function propertyToHtml(property: AST.Property): string[] {
}
export function build(outputFilePath: string, root: string, rootNamespaceName: string): FileTransform {
var compiler = new Compiler();
return new FileTransform(function (file: File): void {
var self: FileTransform = this;
const compiler = new Compiler();
return new FileTransform(function (file): void {
// Compile
compiler.compile(file);
// Walk
var walkResult = walk(compiler, root, rootNamespaceName);
var namespaces = walkResult.namespaces;
var modules = walkResult.modules;
const walkResult = walk(compiler, root, rootNamespaceName);
const namespaces = walkResult.namespaces;
const modules = walkResult.modules;
// Make HTML
var namespaceNames = Object.keys(namespaces)
const namespaceNames = Object.keys(namespaces)
.filter(namespaceName => namespaceName.substr(0, rootNamespaceName.length) === rootNamespaceName)
.sort((ns1, ns2) => ns1.localeCompare(ns2));
var moduleNames = Object.keys(modules).sort((ns1, ns2) => ns1.localeCompare(ns2));
const moduleNames = Object.keys(modules).sort((ns1, ns2) => ns1.localeCompare(ns2)).filter(moduleName => Object.keys(modules[moduleName].members).length > 0);
moduleNames = moduleNames.filter(moduleName => Object.keys(modules[moduleName].members).length > 0);
self.push({
this.push({
path: outputFilePath,
contents: Buffer.concat([new Buffer(
`<?xml version="1.0" encoding="utf-8" ?>
@@ -589,9 +581,9 @@ export function build(outputFilePath: string, root: string, rootNamespaceName: s
<label><input type="checkbox" id="show-private" />Show private</label>
`
)].concat(namespaceNames.map(namespaceName => {
var namespace = namespaces[namespaceName];
const namespace = namespaces[namespaceName];
var namespaceMembers: AST.NamespaceMember[] = [];
const namespaceMembers: AST.NamespaceMember[] = [];
for (const memberName of Object.keys(namespace.members)) {
namespaceMembers.push(namespace.members[memberName]);
}
@@ -613,13 +605,13 @@ export function build(outputFilePath: string, root: string, rootNamespaceName: s
`
)]));
})).concat(moduleNames.map(moduleName => {
var module = modules[moduleName];
const module = modules[moduleName];
var moduleMembers: AST.ModuleMemberWithoutReference[] = [];
const moduleMembers: AST.ModuleMemberWithoutReference[] = [];
for (const memberName of Object.keys(module.members)) {
var member = module.members[memberName];
if ((<AST.HasParent><any>member).parent === module) {
moduleMembers.push(<AST.ModuleMemberWithoutReference>member);
const member = module.members[memberName];
if ((member as AST.HasParent).parent === module) {
moduleMembers.push(member as AST.ModuleMemberWithoutReference);
}
}
@@ -649,22 +641,22 @@ export function build(outputFilePath: string, root: string, rootNamespaceName: s
<div class="content">
`
)]).concat(flatten(namespaceNames.map(namespaceName => {
var namespace = namespaces[namespaceName];
const namespace = namespaces[namespaceName];
var namespaceMembers: AST.NamespaceMember[] = [];
const namespaceMembers: AST.NamespaceMember[] = [];
for (const memberName of Object.keys(namespace.members)) {
namespaceMembers.push(namespace.members[memberName]);
}
namespaceMembers.sort(sorter);
var properties = <AST.Property[]>namespaceMembers.filter(member => member instanceof AST.Property);
var functions = <AST.Function[]>namespaceMembers.filter(member => member instanceof AST.Function);
var interfaces = <AST.Interface[]>namespaceMembers.filter(member => member instanceof AST.Interface);
var classes = <AST.Class[]>namespaceMembers.filter(member => member instanceof AST.Class);
var enums = <AST.Enum[]>namespaceMembers.filter(member => member instanceof AST.Enum);
const properties = namespaceMembers.filter(member => member instanceof AST.Property) as AST.Property[];
const functions = namespaceMembers.filter(member => member instanceof AST.Function) as AST.Function[];
const interfaces = namespaceMembers.filter(member => member instanceof AST.Interface) as AST.Interface[];
const classes = namespaceMembers.filter(member => member instanceof AST.Class) as AST.Class[];
const enums = namespaceMembers.filter(member => member instanceof AST.Enum) as AST.Enum[];
var result = [new Buffer(
const result = [new Buffer(
` <section class="namespace">
<h1 id="${ sanitize(namespaceName) }">Namespace ${ sanitize(namespaceName) }</h1>
`
@@ -762,13 +754,13 @@ export function build(outputFilePath: string, root: string, rootNamespaceName: s
return result;
}))).concat(flatten(moduleNames.map(moduleName => {
var module = modules[moduleName];
const module = modules[moduleName];
var moduleMembers: AST.ModuleMember[] = [];
const moduleMembers: AST.ModuleMember[] = [];
for (const memberName of Object.keys(module.members)) {
var member = module.members[memberName];
if ((<AST.HasParent><any>member).parent === module) {
moduleMembers.push(<AST.ModuleMember>member);
const member = module.members[memberName];
if ((member as AST.HasParent).parent === module) {
moduleMembers.push(member);
}
}
@@ -778,13 +770,13 @@ export function build(outputFilePath: string, root: string, rootNamespaceName: s
moduleMembers.sort(sorter);
var properties = <AST.Property[]>moduleMembers.filter(member => member instanceof AST.Property);
var functions = <AST.Function[]>moduleMembers.filter(member => member instanceof AST.Function);
var interfaces = <AST.Interface[]>moduleMembers.filter(member => member instanceof AST.Interface);
var classes = <AST.Class[]>moduleMembers.filter(member => member instanceof AST.Class);
var enums = <AST.Enum[]>moduleMembers.filter(member => member instanceof AST.Enum);
const properties = moduleMembers.filter(member => member instanceof AST.Property) as AST.Property[];
const functions = moduleMembers.filter(member => member instanceof AST.Function) as AST.Function[];
const interfaces = moduleMembers.filter(member => member instanceof AST.Interface) as AST.Interface[];
const classes = moduleMembers.filter(member => member instanceof AST.Class) as AST.Class[];
const enums = moduleMembers.filter(member => member instanceof AST.Enum) as AST.Enum[];
var result = [new Buffer(
const result = [new Buffer(
` <section class="module">
<h1 id="${ sanitize(moduleName) }">Module ${ sanitize(moduleName) }</h1>
`
+25
View File
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": false,
"strictNullChecks": false,
"target": "es5",
"module": "commonjs",
"moduleResolution": "classic",
"noImplicitUseStrict": false
},
"files": [
"./typescript/index.ts",
"./doc.ts",
"./node.d.ts",
"./typescript/typescript.d.ts",
"../node_modules/async-build/typings.d.ts"
]
}
+12 -2
View File
@@ -18,7 +18,7 @@
* limitations under the License.
*/
import * as ts from "typescript";
import ts = require("typescript");
export class HasParent {
public parent: HasParent = null;
@@ -30,7 +30,7 @@ export class HasParent {
return this.name;
}
var parent = this.parent;
const parent = this.parent;
if (parent instanceof Namespace) {
return parent.getMemberFullName(this);
}
@@ -188,7 +188,17 @@ export class UnresolvedType {
}
export type HasStringGenerics = Class | Interface | Function;
export function hasStringGenerics(item: NamespaceMember): item is HasStringGenerics {
return (item as HasGenerics).generics !== undefined;
}
export type HasGenerics = HasStringGenerics | TypeReference;
export function hasGenerics(item: ModuleMember | EnumMember | TypeReference): item is HasGenerics {
return (item as HasGenerics).generics !== undefined;
}
export type CanBePrivate = Class | Interface | Function | Getter | Setter | Enum | Reference;
export type CanBeProtected = Function;
export type CanBeStatic = Function;
+57 -178
View File
@@ -18,33 +18,52 @@
* limitations under the License.
*/
import * as fs from "fs";
import * as path from "path";
import * as ts from "typescript";
import path = require("path");
import ts = require("typescript");
import { File, FileTransform, FileWatcher } from "async-build";
import { File, FileTransform } from "async-build";
import * as AST from "./ast";
import { walk } from "./walker";
export interface StreamingCompilerHost extends ts.CompilerHost, ts.ParseConfigHost {
export interface StreamingCompilerHost extends ts.CompilerHost {
setOutputStream(outputStream: FileTransform): void;
}
function createCompilerHost(options: ts.CompilerOptions): StreamingCompilerHost {
const host = ts.createCompilerHost(options) as StreamingCompilerHost;
let _outputStream: FileTransform = null;
host.setOutputStream = outputStream => _outputStream = outputStream;
host.writeFile = (fileName, data, writeByteOrderMark, onError?, sourceFiles?): void => {
_outputStream.push({
path: fileName,
contents: new Buffer(data)
});
};
host.useCaseSensitiveFileNames = () => true;
host.getNewLine = () => "\n";
return host;
}
export class Compiler {
private _projectRoot: string = null;
private _host: StreamingCompilerHost;
private _program: ts.Program = null;
constructor(private _host: StreamingCompilerHost = new CompilerHost()) { }
compile(projectConfigFile: File) {
this._projectRoot = path.dirname(projectConfigFile.path);
var projectConfig = ts.parseJsonConfigFileContent(JSON.parse(projectConfigFile.contents.toString()), this._host, this._projectRoot);
const projectConfig = ts.parseJsonConfigFileContent(JSON.parse(projectConfigFile.contents.toString()), ts.sys, this._projectRoot);
this._host = createCompilerHost(projectConfig.options);
this._program = ts.createProgram(projectConfig.fileNames, projectConfig.options, this._host);
var syntacticDiagnostics = this._program.getSyntacticDiagnostics();
const syntacticDiagnostics = this._program.getSyntacticDiagnostics();
if (syntacticDiagnostics.length > 0) {
this._reportDiagnostics(syntacticDiagnostics);
throw new Error("There were one or more syntactic diagnostics.");
@@ -56,13 +75,13 @@ export class Compiler {
throw new Error("There were one or more options diagnostics.");
}
var globalDiagnostics = this._program.getGlobalDiagnostics();
const globalDiagnostics = this._program.getGlobalDiagnostics();
if (globalDiagnostics.length > 0) {
this._reportDiagnostics(globalDiagnostics);
throw new Error("There were one or more global diagnostics.");
}
var semanticDiagnostics = this._program.getSemanticDiagnostics();
const semanticDiagnostics = this._program.getSemanticDiagnostics();
if (semanticDiagnostics.length > 0) {
this._reportDiagnostics(semanticDiagnostics);
throw new Error("There were one or more semantic diagnostics.");
@@ -72,7 +91,7 @@ export class Compiler {
writeFiles(outputStream: FileTransform) {
this._host.setOutputStream(outputStream);
var emitDiagnostics = this._program.emit().diagnostics;
const emitDiagnostics = this._program.emit().diagnostics;
if (emitDiagnostics.length > 0) {
this._reportDiagnostics(emitDiagnostics);
throw new Error("There were one or more emit diagnostics.");
@@ -93,10 +112,10 @@ export class Compiler {
private _reportDiagnostics(diagnostics: ts.Diagnostic[]) {
for (const diagnostic of diagnostics) {
var message = "";
let message = "";
if (diagnostic.file) {
var location = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
const location = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
message = `${ diagnostic.file.fileName }(${ location.line + 1 },${ location.character }): `;
}
@@ -110,168 +129,23 @@ export class Compiler {
};
}
const typeScriptModulePath = path.dirname(require.resolve("typescript"));
class CompilerHost implements StreamingCompilerHost {
protected _sourceFiles = Object.create(null);
private _outputStream: FileTransform = null;
setOutputStream(outputStream: FileTransform): void {
this._outputStream = outputStream;
}
// ts.ModuleResolutionHost members
fileExists(fileName: string): boolean {
return fs.existsSync(fileName);
}
readFile(fileName: string): string {
if (!this.fileExists(fileName)) {
return undefined;
}
return fs.readFileSync(fileName, { encoding: "utf8" });
}
// ts.CompilerHost members
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError: (message: string) => void): ts.SourceFile {
if (fileName in this._sourceFiles) {
return this._sourceFiles[fileName];
}
try {
var text = fs.readFileSync(fileName, { encoding: "utf8" });
var result = ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5);
this._sourceFiles[fileName] = result;
}
catch (ex) {
if (onError) {
onError(ex.message);
}
}
return result;
}
getDefaultLibFileName(): string {
return path.join(typeScriptModulePath, "lib.dom.d.ts");
}
writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError: (message?: string) => void): void {
this._outputStream.push({
path: fileName,
contents: new Buffer(data)
});
}
getCurrentDirectory(): string {
return path.resolve(".");
}
getCanonicalFileName(fileName: string): string {
return ts.normalizeSlashes(path.resolve(fileName));
}
useCaseSensitiveFileNames(): boolean {
return true;
}
getNewLine(): string {
return "\n";
}
// ts.ParseConfigHost members
readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
return ts.sys.readDirectory(rootDir, extension, exclude).map(fileName => this.getCanonicalFileName(fileName));
}
}
class WatchCompilerHost extends CompilerHost {
private _fileWatcher = new FileWatcher(fileNames => this._onFilesChanged(fileNames));
private _filesChangedSinceLast: string[] = [];
constructor(private _onChangeCallback: () => void) {
super();
}
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError: (message: string) => void): ts.SourceFile {
var result = super.getSourceFile(fileName, languageVersion, onError);
if (result !== undefined) {
this._fileWatcher.watchFile(fileName);
}
return result;
};
private _onFilesChanged(fileNames: string[]) {
for (const fileName of fileNames) {
delete this._sourceFiles[fileName];
}
this._onChangeCallback();
}
}
export function build(root: string, rootNamespaceName: string): FileTransform {
var compiler = new Compiler();
return new FileTransform(function (projectConfigFile: File): void {
var self: FileTransform = this;
const compiler = new Compiler();
return new FileTransform(function (projectConfigFile): void {
console.log("Compiling " + projectConfigFile.path + "...");
compiler.compile(projectConfigFile);
var walkResult = walk(compiler, root, rootNamespaceName);
const walkResult = walk(compiler, root, rootNamespaceName);
addJSDocComments(walkResult.modules);
compiler.writeFiles(self);
compiler.writeFiles(this);
console.log("Compile succeeded.");
});
}
export function watch(root: string, rootNamespaceName: string): FileTransform {
return new FileTransform(function (projectConfigFile: File): void {
var self: FileTransform = this;
function compile() {
console.log("Compiling " + projectConfigFile.path + "...");
compiler.compile(projectConfigFile);
compiler.writeFiles(self);
console.log("Compile succeeded.");
self.push({
path: "END",
contents: ""
});
};
var compilerHost = new WatchCompilerHost(() => {
try {
compile();
}
catch (ex) {
console.error("Compile failed." + ex.stack);
}
});
var compiler = new Compiler(compilerHost);
compile();
console.log("Listening for changes...");
}, callback => { });
}
function addJSDocComments(modules: { [name: string]: AST.Module }): void {
function visitor(current: AST.Module | AST.ModuleMember | AST.InterfaceMember) {
if (current instanceof AST.Module) {
@@ -282,18 +156,18 @@ function addJSDocComments(modules: { [name: string]: AST.Module }): void {
return;
}
var newComments: string[] = [];
const newComments: string[] = [];
if (current instanceof AST.Class) {
newComments.push("@constructor");
if (current.baseType !== null) {
var baseType = current.baseType;
const baseType = current.baseType;
newComments.push(
"@extends {" +
baseType.fullName + (
(baseType instanceof AST.TypeReference && baseType.generics.length) > 0 ?
(".<" + (<AST.TypeReference>baseType).generics.map(generic => generic.fullName).join(", ") + ">") :
(".<" + (baseType as AST.TypeReference).generics.map(generic => generic.fullName).join(", ") + ">") :
""
) +
"}"
@@ -323,37 +197,37 @@ function addJSDocComments(modules: { [name: string]: AST.Module }): void {
return;
}
if ((<AST.HasParent><any>current).parent instanceof AST.Namespace) {
newComments.push("@memberOf " + (<AST.HasParent><any>current).parent.fullName);
if (current.parent instanceof AST.Namespace) {
newComments.push("@memberOf " + current.parent.fullName);
}
if ((<AST.HasStringGenerics>current).generics !== undefined && (<AST.HasStringGenerics>current).generics.length > 0) {
newComments.push("@template " + (<AST.HasStringGenerics>current).generics.join(", "));
if (AST.hasStringGenerics(current) && current.generics.length > 0) {
newComments.push("@template " + current.generics.join(", "));
}
if ((<AST.CanBePrivate><any>current).isPrivate) {
if ((current as AST.CanBePrivate).isPrivate) {
newComments.push("@private");
}
if ((<AST.CanBeProtected>current).isProtected) {
if ((current as AST.CanBeProtected).isProtected) {
newComments.push("@protected");
}
if ((<AST.CanBeStatic>current).isStatic) {
if ((current as AST.CanBeStatic).isStatic) {
newComments.push("@static");
}
if (newComments.length > 0) {
if (current instanceof AST.Property) {
var nodes: ts.Node[] = [];
const nodes: ts.Node[] = [];
if (current.getter !== null) { nodes.push(current.getter.astNode); }
if (current.setter !== null && nodes[0] !== current.setter.astNode) { nodes.push(current.setter.astNode); }
for (const node of nodes) {
(<any>node)["typescript-new-comment"] = newComments;
(node as any)["typescript-new-comment"] = newComments;
}
}
else {
(<any>(<AST.Class | AST.Interface | AST.Function | AST.Enum>current).astNode)["typescript-new-comment"] = newComments;
(current.astNode as any)["typescript-new-comment"] = newComments;
}
}
}
@@ -363,6 +237,7 @@ function addJSDocComments(modules: { [name: string]: AST.Module }): void {
}
}
/*
class FakeSourceFile {
public text: string;
public lineMap: number[];
@@ -403,8 +278,11 @@ class FakeSourceFile {
}
var fakeSourceFiles: { [name: string]: FakeSourceFile } = Object.create(null);
*/
export const oldGetLeadingCommentRangesOfNodeFromText: typeof ts.getLeadingCommentRangesOfNodeFromText = ts.getLeadingCommentRangesOfNodeFromText.bind(ts);
/*
ts.getLeadingCommentRangesOfNodeFromText = (node: ts.Node, text: string) => {
const originalComments = oldGetLeadingCommentRangesOfNodeFromText(node, text);
@@ -422,12 +300,13 @@ ts.getLeadingCommentRangesOfNodeFromText = (node: ts.Node, text: string) => {
};
var oldWriteCommentRange: typeof ts.writeCommentRange = ts.writeCommentRange.bind(ts);
ts.writeCommentRange = (text: string, lineMap: number[], writer: ts.EmitTextWriter, comment: ts.CommentRange, newLine: string) => {
ts.writeCommentRange = (text: string, lineMap: number[], writer: ts.EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => {
if ((<{ sourceFile: ts.SourceFile }><any>comment).sourceFile) {
const currentSourceFile = (<{ sourceFile: ts.SourceFile }><any>comment).sourceFile;
text = currentSourceFile.text;
lineMap = currentSourceFile.lineMap;
}
return oldWriteCommentRange(text, lineMap, writer, comment, newLine);
return oldWriteCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
};
*/
+14 -13
View File
@@ -1,22 +1,23 @@
declare namespace ts {
export interface EmitTextWriter { }
interface EmitTextWriter { }
export interface IntrinsicType extends Type {
interface IntrinsicType extends Type {
intrinsicName: string;
}
export interface SourceFile {
interface SourceFile {
lineMap: number[];
}
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U;
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration): ExpressionWithTypeArguments;
export function getClassImplementsHeritageClauseElements(node: ClassDeclaration): NodeArray<ExpressionWithTypeArguments>;
export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration): NodeArray<ExpressionWithTypeArguments>;
export function getLeadingCommentRangesOfNodeFromText(node: Node, text: string): CommentRange[];
export function getLineStarts(sourceFile: SourceFile): number[];
export function getSourceFileOfNode(node: Node): SourceFile;
export function getTextOfNode(node: Node, includeTrivia?: boolean): string;
export function normalizeSlashes(path: string): string;
export function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string): void;
function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U;
function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration): ExpressionWithTypeArguments;
function getClassImplementsHeritageClauseElements(node: ClassLikeDeclaration): ExpressionWithTypeArguments[];
function getInterfaceBaseTypeNodes(node: InterfaceDeclaration): ExpressionWithTypeArguments[];
function getLeadingCommentRangesOfNodeFromText(node: Node, text: string): CommentRange[];
function getLineStarts(sourceFile: SourceFile): number[];
function getSourceFileOfNode(node: Node): SourceFile;
function getTextOfNode(node: Node, includeTrivia?: boolean): string;
function normalizeSlashes(path: string): string;
function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string): void;
function hasModifier(node: Node, flags: ModifierFlags): boolean;
}
+1 -1
View File
@@ -18,4 +18,4 @@
* limitations under the License.
*/
export { build, watch } from "./compiler";
export { build } from "./compiler";
+175 -166
View File
@@ -18,8 +18,8 @@
* limitations under the License.
*/
import * as path from "path";
import * as ts from "typescript";
import path = require("path");
import ts = require("typescript");
import { Compiler, oldGetLeadingCommentRangesOfNodeFromText } from "./compiler";
@@ -68,13 +68,13 @@ class Walker {
}
walk(sourceFile: ts.SourceFile): void {
var moduleName = this._moduleNameFromFileName(sourceFile.fileName);
const moduleName = this._moduleNameFromFileName(sourceFile.fileName);
if (!(moduleName in this.modules)) {
this.modules[moduleName] = new AST.Module(moduleName);
}
var module = this._scope.enter(this.modules[moduleName]);
const module = this._scope.enter(this.modules[moduleName]);
this._currentSourceFile = sourceFile;
for (const statement of sourceFile.statements) {
@@ -87,31 +87,31 @@ class Walker {
private _walk(node: ts.Node, parent: AST.Module): void {
switch (node.kind) {
case ts.SyntaxKind.VariableStatement:
this._visitVariableStatement(<ts.VariableStatement>node, parent);
this._visitVariableStatement(node as ts.VariableStatement, parent);
break;
case ts.SyntaxKind.FunctionDeclaration:
this._visitFunctionDeclaration(<ts.FunctionDeclaration>node, parent);
this._visitFunctionDeclaration(node as ts.FunctionDeclaration, parent);
break;
case ts.SyntaxKind.ClassDeclaration:
this._visitClassDeclaration(<ts.ClassDeclaration>node, parent);
this._visitClassDeclaration(node as ts.ClassDeclaration, parent);
break;
case ts.SyntaxKind.InterfaceDeclaration:
this._visitInterfaceDeclaration(<ts.InterfaceDeclaration>node, parent);
this._visitInterfaceDeclaration(node as ts.InterfaceDeclaration, parent);
break;
case ts.SyntaxKind.EnumDeclaration:
this._visitEnumDeclaration(<ts.EnumDeclaration>node, parent);
this._visitEnumDeclaration(node as ts.EnumDeclaration, parent);
break;
case ts.SyntaxKind.ImportDeclaration:
this._visitImportDeclaration(<ts.ImportDeclaration>node, parent);
this._visitImportDeclaration(node as ts.ImportDeclaration, parent);
break;
case ts.SyntaxKind.ExportDeclaration:
this._visitExportDeclaration(<ts.ExportDeclaration>node, parent);
this._visitExportDeclaration(node as ts.ExportDeclaration, parent);
break;
case ts.SyntaxKind.ExpressionStatement:
@@ -121,7 +121,7 @@ class Walker {
break;
default:
console.error(node.kind, (<any>ts).SyntaxKind[node.kind], node);
console.error(node.kind, ts.SyntaxKind[node.kind], node);
throw new Error("Unrecognized node.");
}
}
@@ -130,20 +130,20 @@ class Walker {
switch (node.kind) {
case ts.SyntaxKind.PropertySignature:
case ts.SyntaxKind.PropertyDeclaration:
this._visitProperty(<ts.PropertyDeclaration>node, clazz);
this._visitProperty(node as ts.PropertyDeclaration, clazz);
break;
case ts.SyntaxKind.MethodSignature:
case ts.SyntaxKind.MethodDeclaration:
this._visitMethod(<ts.MethodDeclaration>node, clazz);
this._visitMethod(node as ts.MethodDeclaration, clazz);
break;
case ts.SyntaxKind.GetAccessor:
this._visitGetAccessor(<ts.AccessorDeclaration>node, clazz);
this._visitGetAccessor(node as ts.AccessorDeclaration, clazz);
break;
case ts.SyntaxKind.SetAccessor:
this._visitSetAccessor(<ts.AccessorDeclaration>node, clazz);
this._visitSetAccessor(node as ts.AccessorDeclaration, clazz);
break;
case ts.SyntaxKind.TypeParameter:
@@ -152,7 +152,7 @@ class Walker {
break;
default:
console.error(node.kind, (<any>ts).SyntaxKind[node.kind], node);
console.error(node.kind, ts.SyntaxKind[node.kind], node);
throw new Error("Unrecognized node.");
}
}
@@ -161,12 +161,12 @@ class Walker {
switch (node.kind) {
case ts.SyntaxKind.PropertySignature:
case ts.SyntaxKind.PropertyDeclaration:
this._visitProperty(<ts.PropertyDeclaration>node, interfase);
this._visitProperty(node as ts.PropertyDeclaration, interfase);
break;
case ts.SyntaxKind.MethodSignature:
case ts.SyntaxKind.MethodDeclaration:
this._visitMethod(<ts.MethodDeclaration>node, interfase);
this._visitMethod(node as ts.MethodDeclaration, interfase);
break;
case ts.SyntaxKind.TypeParameter:
@@ -176,24 +176,24 @@ class Walker {
break;
default:
console.error(node.kind, (<any>ts).SyntaxKind[node.kind], node);
console.error(node.kind, ts.SyntaxKind[node.kind], node);
throw new Error("Unrecognized node.");
}
}
private _visitProperty(node: ts.PropertyDeclaration, parent: AST.Class | AST.Interface) {
if ((node.flags & ts.NodeFlags.Private) === ts.NodeFlags.Private) {
if (ts.hasModifier(node, ts.ModifierFlags.Private)) {
return;
}
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
if (jsDoc.typeAnnotation === null) {
this._notifyIncorrectJsDoc(`Field ${ ts.getTextOfNode(node.name) } has no @type annotation.`);
jsDoc.typeAnnotation = "*";
}
var property = this._scope.enter(new AST.Property(ts.getTextOfNode(node.name)));
const property = this._scope.enter(new AST.Property(ts.getTextOfNode(node.name)));
parent.members[property.name] = property;
property.getter = new AST.Getter(node, jsDoc.description, jsDoc.typeAnnotation, false);
property.setter = new AST.Setter(node, jsDoc.description, jsDoc.typeAnnotation, false);
@@ -201,9 +201,9 @@ class Walker {
}
private _visitMethod(node: ts.MethodDeclaration, parent: AST.Class | AST.Interface) {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var parameters = this._connectParameters(node.parameters, jsDoc.parameters,
const parameters = this._connectParameters(node.parameters, jsDoc.parameters,
parameterName => `Could not find @param annotation for ${ parameterName } on method ${ ts.getTextOfNode(node.name) }`
);
@@ -212,25 +212,25 @@ class Walker {
jsDoc.returnType = new AST.ReturnType("", "*");
}
var isPrivate = (node.flags & ts.NodeFlags.Private) === ts.NodeFlags.Private;
var isProtected = (node.flags & ts.NodeFlags.Protected) === ts.NodeFlags.Protected;
var isStatic = (node.flags & ts.NodeFlags.Static) === ts.NodeFlags.Static;
const isPrivate = ts.hasModifier(node, ts.ModifierFlags.Private);
const isProtected = ts.hasModifier(node, ts.ModifierFlags.Protected);
const isStatic = ts.hasModifier(node, ts.ModifierFlags.Static);
var generics = this._getGenericsOfSignatureDeclaration(node);
const generics = this._getGenericsOfSignatureDeclaration(node);
var method = this._scope.enter(new AST.Function(ts.getTextOfNode(node.name), node, jsDoc.description, generics, parameters, jsDoc.returnType, jsDoc.isAbstract, isPrivate, isProtected, isStatic));
const method = this._scope.enter(new AST.Function(ts.getTextOfNode(node.name), node, jsDoc.description, generics, parameters, jsDoc.returnType, jsDoc.isAbstract, isPrivate, isProtected, isStatic));
parent.members[method.name] = method;
this._scope.leave();
}
private _visitGetAccessor(node: ts.AccessorDeclaration, clazz: AST.Class): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var name = ts.getTextOfNode(node.name);
const name = ts.getTextOfNode(node.name);
var isPrivate = (node.flags & ts.NodeFlags.Private) === ts.NodeFlags.Private;
const isPrivate = ts.hasModifier(node, ts.ModifierFlags.Private);
var property = <AST.Property>clazz.members[name];
let property = clazz.members[name] as AST.Property;
if (property === undefined) {
this._scope.enter(property = new AST.Property(name));
@@ -247,13 +247,13 @@ class Walker {
}
private _visitSetAccessor(node: ts.AccessorDeclaration, clazz: AST.Class): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var name = ts.getTextOfNode(node.name);
const name = ts.getTextOfNode(node.name);
var isPrivate = (node.flags & ts.NodeFlags.Private) === ts.NodeFlags.Private;
const isPrivate = ts.hasModifier(node, ts.ModifierFlags.Private);
var property = <AST.Property>clazz.members[name];
let property = clazz.members[name] as AST.Property;
if (property === undefined) {
this._scope.enter(property = new AST.Property(name));
@@ -274,17 +274,17 @@ class Walker {
return;
}
var declaration = node.declarationList.declarations[0];
if ((declaration.flags & ts.NodeFlags.Ambient) === ts.NodeFlags.Ambient) {
const declaration = node.declarationList.declarations[0];
if (ts.hasModifier(declaration, ts.ModifierFlags.Ambient)) {
return;
}
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
if (jsDoc.typeAnnotation === null) {
return;
}
var property = this._scope.enter(new AST.Property(ts.getTextOfNode(declaration.name)));
const property = this._scope.enter(new AST.Property(ts.getTextOfNode(declaration.name)));
property.getter = new AST.Getter(node, jsDoc.description, jsDoc.typeAnnotation, false);
parent.members[property.name] = property;
@@ -293,13 +293,13 @@ class Walker {
}
private _visitFunctionDeclaration(node: ts.FunctionDeclaration, parent: AST.Module): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var isPrivate = (node.flags & ts.NodeFlags.Export) !== ts.NodeFlags.Export;
const isPrivate = !ts.hasModifier(node, ts.ModifierFlags.Export);
var generics = this._getGenericsOfSignatureDeclaration(node);
const generics = this._getGenericsOfSignatureDeclaration(node);
var parameters = this._connectParameters(node.parameters, jsDoc.parameters,
const parameters = this._connectParameters(node.parameters, jsDoc.parameters,
parameterName => `Could not find @param annotation for ${ parameterName } on function ${ node.name.text }`
);
@@ -312,7 +312,7 @@ class Walker {
jsDoc.returnType = new AST.ReturnType("", "*");
}
var freeFunction = this._scope.enter(new AST.Function(node.name.text, node, jsDoc.description, generics, parameters, jsDoc.returnType, jsDoc.isAbstract, isPrivate, false, false));
const freeFunction = this._scope.enter(new AST.Function(node.name.text, node, jsDoc.description, generics, parameters, jsDoc.returnType, jsDoc.isAbstract, isPrivate, false, false));
parent.members[freeFunction.name] = freeFunction;
@@ -320,32 +320,32 @@ class Walker {
}
private _visitClassDeclaration(node: ts.ClassDeclaration, parent: AST.Module): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var baseTypeHeritageClauseElement = ts.getClassExtendsHeritageClauseElement(node) || null;
var baseType: AST.UnresolvedType = null;
const type = this._typeChecker.getTypeAtLocation(node) as ts.InterfaceType;
const generics = this._getGenericsOfInterfaceType(type);
const baseTypeHeritageClauseElement = ts.getClassExtendsHeritageClauseElement(node) || null;
let baseType: AST.UnresolvedType = null;
if (baseTypeHeritageClauseElement !== null) {
baseType = new AST.UnresolvedType(
this._typeChecker.getTypeAtLocation(baseTypeHeritageClauseElement).symbol,
this._getGenericsOfTypeReferenceNode(baseTypeHeritageClauseElement)
this._getGenericsOfTypeReferenceNode(baseTypeHeritageClauseElement, generics)
);
}
var interfaces = (ts.getClassImplementsHeritageClauseElements(node) || []).map(type => new AST.UnresolvedType(
const interfaces = (ts.getClassImplementsHeritageClauseElements(node) || []).map(type => new AST.UnresolvedType(
this._typeChecker.getTypeAtLocation(type).symbol,
this._getGenericsOfTypeReferenceNode(type)
this._getGenericsOfTypeReferenceNode(type, generics)
));
var isPrivate = (node.flags & ts.NodeFlags.Export) !== ts.NodeFlags.Export;
const isPrivate = !ts.hasModifier(node, ts.ModifierFlags.Export);
var type = <ts.InterfaceType>this._typeChecker.getTypeAtLocation(node);
var generics = this._getGenericsOfInterfaceType(type);
var parameters: AST.Parameter[] = [];
let parameters: AST.Parameter[] = [];
if (type.symbol.members["__constructor"] !== undefined) {
parameters = this._connectParameters((<ts.ConstructorDeclaration>type.symbol.members["__constructor"].declarations[0]).parameters, jsDoc.parameters,
parameters = this._connectParameters((type.symbol.members["__constructor"].declarations[0] as ts.ConstructorDeclaration).parameters, jsDoc.parameters,
parameterName => `Could not find @param annotation for ${ parameterName } on constructor in class ${ node.name.text }`
);
}
@@ -353,11 +353,11 @@ class Walker {
this._notifyIncorrectJsDoc("There are @param annotations on this class but it has no constructors.");
}
var clazz = this._scope.enter(new AST.Class(node.name.text, node, jsDoc.description, generics, parameters, baseType, interfaces, jsDoc.isAbstract, isPrivate));
const clazz = this._scope.enter(new AST.Class(node.name.text, node, jsDoc.description, generics, parameters, baseType, interfaces, jsDoc.isAbstract, isPrivate));
parent.members[clazz.name] = clazz;
ts.forEachValue(type.symbol.exports, symbol => {
ts.forEachProperty(type.symbol.exports, symbol => {
if (symbol.name === "prototype") {
return;
}
@@ -367,7 +367,7 @@ class Walker {
}
});
ts.forEachValue(type.symbol.members, symbol => {
ts.forEachProperty(type.symbol.members, symbol => {
for (const declaration of symbol.declarations) {
this._walkClassMember(declaration, clazz);
}
@@ -377,28 +377,28 @@ class Walker {
}
private _visitInterfaceDeclaration(node: ts.InterfaceDeclaration, parent: AST.Module): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var baseTypes = (ts.getInterfaceBaseTypeNodes(node) || []).map(type => new AST.UnresolvedType(
const type = this._typeChecker.getTypeAtLocation(node) as ts.InterfaceType;
const generics = this._getGenericsOfInterfaceType(type);
const baseTypes = (ts.getInterfaceBaseTypeNodes(node) || []).map(type => new AST.UnresolvedType(
this._typeChecker.getTypeAtLocation(type).symbol,
this._getGenericsOfTypeReferenceNode(type)
this._getGenericsOfTypeReferenceNode(type, generics)
));
var existingInterfaceType = parent.members[node.name.text];
const existingInterfaceType = parent.members[node.name.text];
if (existingInterfaceType !== undefined) {
return;
}
var isPrivate = (node.flags & ts.NodeFlags.Export) !== ts.NodeFlags.Export;
const isPrivate = !ts.hasModifier(node, ts.ModifierFlags.Export);
var type = <ts.InterfaceType>this._typeChecker.getTypeAtLocation(node);
var generics = this._getGenericsOfInterfaceType(type);
var interfase = this._scope.enter(new AST.Interface(node.name.text, node, jsDoc.description, generics, baseTypes, isPrivate));
const interfase = this._scope.enter(new AST.Interface(node.name.text, node, jsDoc.description, generics, baseTypes, isPrivate));
parent.members[interfase.name] = interfase;
ts.forEachValue(type.symbol.members, symbol => {
ts.forEachProperty(type.symbol.members, symbol => {
for (const declaration of symbol.declarations) {
this._walkInterfaceMember(declaration, interfase);
}
@@ -408,33 +408,33 @@ class Walker {
}
private _visitEnumDeclaration(node: ts.EnumDeclaration, parent: AST.Module): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var existingEnumType = parent.members[node.name.text];
const existingEnumType = parent.members[node.name.text];
if (existingEnumType !== undefined) {
return;
}
var isPrivate = (node.flags & ts.NodeFlags.Export) !== ts.NodeFlags.Export;
const isPrivate = !ts.hasModifier(node, ts.ModifierFlags.Export);
var type = this._typeChecker.getTypeAtLocation(node);
const type = this._typeChecker.getTypeAtLocation(node);
var enumType = this._scope.enter(new AST.Enum(node.name.text, node, jsDoc.description, isPrivate));
const enumType = this._scope.enter(new AST.Enum(node.name.text, node, jsDoc.description, isPrivate));
parent.members[enumType.name] = enumType;
ts.forEachValue(type.symbol.exports, symbol => {
this._visitEnumMember(<ts.EnumMember>symbol.declarations[0], enumType);
ts.forEachProperty(type.symbol.exports, symbol => {
this._visitEnumMember(symbol.declarations[0] as ts.EnumMember, enumType);
});
this._scope.leave();
}
private _visitEnumMember(node: ts.EnumMember, parent: AST.Enum): void {
var jsDoc = this._parseJSDoc(node);
const jsDoc = this._parseJSDoc(node);
var value = (node.initializer === undefined) ? null : parseInt((<ts.LiteralExpression>node.initializer).text);
const value = (node.initializer === undefined) ? null : parseInt((node.initializer as ts.LiteralExpression).text);
var enumMember = this._scope.enter(new AST.EnumMember(ts.getTextOfNode(node.name), (jsDoc === null) ? "" : jsDoc.description, value));
const enumMember = this._scope.enter(new AST.EnumMember(ts.getTextOfNode(node.name), (jsDoc === null) ? "" : jsDoc.description, value));
parent.members.push(enumMember);
@@ -451,16 +451,16 @@ class Walker {
throw new Error("Default import is not supported.");
}
var moduleName = this._resolve((<ts.LiteralExpression>node.moduleSpecifier).text, parent);
const moduleName = this._resolve((node.moduleSpecifier as ts.LiteralExpression).text, parent);
if ((<ts.NamespaceImport>node.importClause.namedBindings).name !== undefined) {
if ((node.importClause.namedBindings as ts.NamespaceImport).name !== undefined) {
// import * as foo from "baz";
parent.members[(<ts.NamespaceImport>node.importClause.namedBindings).name.text] = new AST.Reference(moduleName, "*", true);
parent.members[(node.importClause.namedBindings as ts.NamespaceImport).name.text] = new AST.Reference(moduleName, "*", true);
}
else if ((<ts.NamedImports>node.importClause.namedBindings).elements !== undefined) {
else if ((node.importClause.namedBindings as ts.NamedImports).elements !== undefined) {
// import { foo, bar } from "baz";
for (const element of (<ts.NamedImports>node.importClause.namedBindings).elements) {
var importedName = element.propertyName && element.propertyName.text || element.name.text;
for (const element of (node.importClause.namedBindings as ts.NamedImports).elements) {
const importedName = element.propertyName && element.propertyName.text || element.name.text;
parent.members[element.name.text] = new AST.Reference(moduleName, importedName, true);
}
}
@@ -472,22 +472,22 @@ class Walker {
private _visitExportDeclaration(node: ts.ExportDeclaration, parent: AST.Module): void {
if (node.moduleSpecifier !== undefined) {
// export { foo } from "bar";
var moduleName = this._resolve((<ts.LiteralExpression>node.moduleSpecifier).text, parent);
const moduleName = this._resolve((node.moduleSpecifier as ts.LiteralExpression).text, parent);
for (const element of node.exportClause.elements) {
var importedName = element.propertyName && element.propertyName.text || element.name.text;
const importedName = element.propertyName && element.propertyName.text || element.name.text;
parent.members[element.name.text] = new AST.Reference(moduleName, importedName, false);
}
}
else {
// export { foo };
for (const element of node.exportClause.elements) {
(<AST.CanBePrivate><any>parent.members[element.name.text]).isPrivate = false;
(parent.members[element.name.text] as AST.CanBePrivate).isPrivate = false;
}
}
}
private _resolve(relativeModuleName: string, currentModule: AST.Module): string {
var result = ts.normalizeSlashes(path.join(currentModule.name, `../${ relativeModuleName }`));
let result = ts.normalizeSlashes(path.join(currentModule.name, `../${ relativeModuleName }`));
if (result[0] !== ".") {
result = `./${ result }`;
@@ -497,7 +497,7 @@ class Walker {
}
private _parseJSDoc(node: ts.Node): JSDoc {
var comments = oldGetLeadingCommentRangesOfNodeFromText(node, this._currentSourceFile.text);
let comments = oldGetLeadingCommentRangesOfNodeFromText(node, this._currentSourceFile.text);
if (comments === undefined) {
comments = [];
@@ -507,41 +507,41 @@ class Walker {
comments = [comments[comments.length - 1]];
}
var comment =
const comment =
(comments.length === 0) ?
"" :
this._currentSourceFile.text.substring(comments[0].pos, comments[0].end);
var commentStartIndex = comment.indexOf("/**");
var commentEndIndex = comment.lastIndexOf("*/");
const commentStartIndex = comment.indexOf("/**");
const commentEndIndex = comment.lastIndexOf("*/");
var lines =
const lines =
(commentStartIndex === -1 || commentEndIndex === -1) ?
[] :
comment.substring(commentStartIndex + 2, commentEndIndex).split("\n").map(line => {
var match = line.match(/^[ \t]*\* (.*)/);
const match = line.match(/^[ \t]*\* (.*)/);
if (match === null) {
return "";
}
return match[1];
});
var rootDescription = "";
let rootDescription = "";
var parameters: { [name: string]: AST.Parameter } = Object.create(null);
const parameters: { [name: string]: AST.Parameter } = Object.create(null);
var typeAnnotation: string = null;
let typeAnnotation: string = null;
var returnType: AST.ReturnType = null;
let returnType: AST.ReturnType = null;
var isAbstract = false;
let isAbstract = false;
var lastRead: { description: string } = null;
let lastRead: { description: string } = null;
for (const line of lines) {
var firstWordMatch = line.match(/^\s*(\S+)(\s*)/);
var firstWord = (firstWordMatch !== null) ? firstWordMatch[1] : "";
var remainingLine = (firstWordMatch !== null) ? line.substring(firstWordMatch[0].length) : "";
const firstWordMatch = line.match(/^\s*(\S+)(\s*)/);
const firstWord = (firstWordMatch !== null) ? firstWordMatch[1] : "";
let remainingLine = (firstWordMatch !== null) ? line.substring(firstWordMatch[0].length) : "";
if (firstWord[0] === "@") {
lastRead = null;
@@ -552,30 +552,33 @@ class Walker {
isAbstract = true;
break;
case "@param":
var type: string;
case "@param": {
let type: string;
[type, remainingLine] = this._readType(remainingLine);
var [, name, description] = remainingLine.match(/(\S+)\s*(.*)/);
const [, name, description] = remainingLine.match(/(\S+)\s*(.*)/);
var subParameterMatch = name.match(/^(?:(.+)\.([^\.]+))|(?:(.+)\[("[^\[\]"]+")\])$/);
const subParameterMatch = name.match(/^(?:(.+)\.([^\.]+))|(?:(.+)\[("[^\[\]"]+")\])$/);
if (subParameterMatch === null) {
parameters[name] = lastRead = new AST.Parameter(name, description, type);
}
else {
var parentName = subParameterMatch[1] || subParameterMatch[3];
var childName = subParameterMatch[2] || subParameterMatch[4];
var parentParameter = parameters[parentName];
const parentName = subParameterMatch[1] || subParameterMatch[3];
const childName = subParameterMatch[2] || subParameterMatch[4];
const parentParameter = parameters[parentName];
parentParameter.subParameters.push(lastRead = new AST.Parameter(childName, description, type));
}
break;
case "@return":
var [type, description] = this._readType(remainingLine);
break;
}
case "@return": {
const [type, description] = this._readType(remainingLine);
returnType = lastRead = new AST.ReturnType(description, type);
break;
}
case "@type":
[typeAnnotation] = this._readType(remainingLine);
@@ -606,9 +609,9 @@ class Walker {
return ["*", remainingLine];
}
var index = -1;
var numberOfUnterminatedBraces = 0;
for (var i = 0; i < remainingLine.length; i++) {
let index = -1;
let numberOfUnterminatedBraces = 0;
for (let i = 0; i < remainingLine.length; i++) {
if (remainingLine[i] === "{") {
numberOfUnterminatedBraces++;
}
@@ -626,7 +629,7 @@ class Walker {
throw new Error("Unterminated type specifier.");
}
var type = remainingLine.substr(1, index - 1);
const type = remainingLine.substr(1, index - 1);
remainingLine = remainingLine.substr(index + 1).replace(/^\s+/, "");
return [type, remainingLine];
@@ -640,16 +643,24 @@ class Walker {
return signatureDeclaration.typeParameters.map(typeParameter => typeParameter.name.text);
}
private _getGenericsOfTypeReferenceNode(typeReferenceNode: ts.ExpressionWithTypeArguments): (AST.UnresolvedType | AST.IntrinsicTypeReference)[] {
private _getGenericsOfTypeReferenceNode(typeReferenceNode: ts.ExpressionWithTypeArguments, intrinsicGenerics: string[]): (AST.UnresolvedType | AST.IntrinsicTypeReference)[] {
if (typeReferenceNode.typeArguments === undefined) {
return [];
}
var typeReference = <ts.TypeReference>this._typeChecker.getTypeAtLocation(typeReferenceNode);
const typeReference = this._typeChecker.getTypeAtLocation(typeReferenceNode) as ts.TypeReference;
return typeReference.typeArguments.map(typeArgument => {
if ((<ts.IntrinsicType>typeArgument).intrinsicName !== undefined) {
return new AST.IntrinsicTypeReference((<ts.IntrinsicType>typeArgument).intrinsicName);
if ((typeArgument as ts.IntrinsicType).intrinsicName !== undefined) {
return new AST.IntrinsicTypeReference((typeArgument as ts.IntrinsicType).intrinsicName);
}
if (typeArgument.flags & ts.TypeFlags.TypeParameter) {
if (intrinsicGenerics.indexOf(typeArgument.symbol.name) !== -1) {
return new AST.IntrinsicTypeReference(typeArgument.symbol.name);
}
throw new Error(`Unbound type parameter ${ typeArgument.symbol.name }`);
}
return new AST.UnresolvedType(typeArgument.symbol, []);
@@ -668,12 +679,12 @@ class Walker {
private _connectParameters(astParameters: ts.ParameterDeclaration[], jsDocParameters: { [name: string]: AST.Parameter }, onMissingMessageCallback: (parameterName: string) => string) {
return astParameters.map(parameter => {
var parameterName = (<ts.Identifier>parameter.name).text;
let parameterName = (parameter.name as ts.Identifier).text;
if (parameterName[0] === "_") {
parameterName = parameterName.substr(1);
}
var jsDocParameter = jsDocParameters[parameterName];
let jsDocParameter = jsDocParameters[parameterName];
if (jsDocParameter === undefined) {
this._notifyIncorrectJsDoc(onMissingMessageCallback.call(this, parameterName));
@@ -685,8 +696,8 @@ class Walker {
}
private _notifyIncorrectJsDoc(message: string): void {
var fileName = path.basename(this._currentSourceFile.fileName);
if (fileName === "lib.core.d.ts" || fileName === "lib.dom.d.ts") {
const fileName = path.basename(this._currentSourceFile.fileName);
if (fileName === "lib.es5.d.ts" || fileName === "lib.dom.d.ts") {
return;
}
@@ -695,17 +706,17 @@ class Walker {
link(rootNamespaceName: string): void {
for (const moduleName of Object.keys(this.modules)) {
var module = this.modules[moduleName];
const module = this.modules[moduleName];
for (const memberName of Object.keys(module.members)) {
var member = module.members[memberName];
const member = module.members[memberName];
if (member instanceof AST.Class) {
if (member.unresolvedBaseType instanceof AST.UnresolvedType) {
member.baseType = this._resolveTypeReference(<AST.UnresolvedType>member.unresolvedBaseType);
member.baseType = this._resolveTypeReference(member.unresolvedBaseType);
}
else {
member.baseType = <AST.TypeReference | AST.IntrinsicTypeReference>member.unresolvedBaseType;
member.baseType = member.unresolvedBaseType;
}
member.interfaces = member.unresolvedInterfaces.map(interfase => {
@@ -713,7 +724,7 @@ class Walker {
return this._resolveTypeReference(interfase);
}
return <AST.TypeReference | AST.IntrinsicTypeReference>interfase;
return interfase;
});
}
@@ -723,12 +734,12 @@ class Walker {
return this._resolveTypeReference(baseType);
}
return <AST.TypeReference | AST.IntrinsicTypeReference>baseType;
return baseType;
});
}
else if (member instanceof AST.Enum) {
var value = 0;
let value = 0;
for (const enumMember of member.members) {
if (enumMember.value === null) {
enumMember.value = value;
@@ -750,17 +761,17 @@ class Walker {
private _moduleToNamespace(module: AST.Module): void {
for (const memberName of Object.keys(module.members)) {
var member = module.members[memberName];
let member = module.members[memberName];
if (member instanceof AST.Reference) {
if ((<AST.Reference>member).isPrivate) {
if (member.isPrivate) {
continue;
}
if (member.name === "*") {
var newNamespace = this._scope.enter(new AST.Namespace(memberName));
const newNamespace = this._scope.enter(new AST.Namespace(memberName));
var existingNamespace = this.namespaces[newNamespace.fullName];
const existingNamespace = this.namespaces[newNamespace.fullName];
if (existingNamespace !== undefined) {
this._scope.leave();
this._scope.enter(existingNamespace);
@@ -769,10 +780,10 @@ class Walker {
this.namespaces[newNamespace.fullName] = newNamespace;
}
var referencedModuleName = (<AST.Reference>member).moduleName;
var referencedModule = this.modules[referencedModuleName];
let referencedModuleName = member.moduleName;
let referencedModule = this.modules[referencedModuleName];
if (referencedModule === undefined && ((referencedModuleName + "/index") in this.modules)) {
(<AST.Reference>member).moduleName = referencedModuleName = referencedModuleName + "/index";
member.moduleName = referencedModuleName = referencedModuleName + "/index";
referencedModule = this.modules[referencedModuleName];
}
this._moduleToNamespace(referencedModule);
@@ -781,56 +792,56 @@ class Walker {
}
else {
while (member instanceof AST.Reference) {
member = this.modules[(<AST.Reference>member).moduleName].members[member.name];
member = this.modules[member.moduleName].members[member.name];
}
this._scope.enter(<AST.NamespaceMember><any>member);
this._scope.enter(member);
this._scope.leave();
(<AST.Namespace>this._scope.current).members[member.name] = <AST.NamespaceMember>member;
(this._scope.current as AST.Namespace).members[member.name] = member;
}
}
else if (!(<AST.CanBePrivate><any>member).isPrivate) {
this._scope.enter(<AST.NamespaceMember>member);
else if (!(member as AST.CanBePrivate).isPrivate) {
this._scope.enter(member);
this._scope.leave();
(<AST.Namespace>this._scope.current).members[member.name] = <AST.NamespaceMember>member;
(this._scope.current as AST.Namespace).members[member.name] = member;
}
}
}
private _resolveTypeReference(unresolvedType: AST.UnresolvedType): AST.TypeReference {
var node: ts.Node = unresolvedType.symbol.declarations[0];
let node: ts.Node = unresolvedType.symbol.declarations[0];
while (node.kind !== ts.SyntaxKind.SourceFile) {
node = node.parent;
}
var sourceFile = <ts.SourceFile>node;
const sourceFile = node as ts.SourceFile;
var moduleName = this._moduleNameFromFileName(sourceFile.fileName);
var module = this.modules[moduleName];
const moduleName = this._moduleNameFromFileName(sourceFile.fileName);
const module = this.modules[moduleName];
var result = module.members[unresolvedType.symbol.name];
let result = module.members[unresolvedType.symbol.name];
if (result === undefined) {
throw new Error(`Type ${ unresolvedType.symbol.name } could not be resolved.`);
}
while (result instanceof AST.Reference) {
result = this.modules[(<AST.Reference>result).moduleName].members[result.name];
result = this.modules[result.moduleName].members[result.name];
}
var resultGenerics = unresolvedType.generics.map(generic => {
const resultGenerics = unresolvedType.generics.map(generic => {
if (generic instanceof AST.UnresolvedType) {
return this._resolveTypeReference(generic);
}
return <AST.IntrinsicTypeReference>generic;
return generic;
});
return new AST.TypeReference(<AST.NamespaceMember><any>result, resultGenerics);
return new AST.TypeReference(result, resultGenerics);
}
private _moduleNameFromFileName(fileName: string): string {
var result = ts.normalizeSlashes(path.relative(this._compiler.projectRoot, fileName));
let result = ts.normalizeSlashes(path.relative(this._compiler.projectRoot, fileName));
result = result.substr(0, result.length - ".ts".length);
@@ -843,16 +854,14 @@ class Walker {
}
export function walk(compiler: Compiler, root: string, rootNamespaceName: string) {
var sourceFiles = compiler.sourceFiles;
var rootFileName = ts.normalizeSlashes(path.resolve(root));
var rootSourceFile = sourceFiles.filter(sourceFile => sourceFile.fileName === rootFileName)[0];
const sourceFiles = compiler.sourceFiles;
var walker = new Walker(compiler);
const walker = new Walker(compiler);
// Walk
for (const sourceFile of sourceFiles) {
if (
path.basename(sourceFile.fileName) === "lib.core.d.ts" ||
path.basename(sourceFile.fileName) === "lib.es5.d.ts" ||
path.basename(sourceFile.fileName) === "lib.dom.d.ts" ||
sourceFile.fileName.substr(-"references.d.ts".length) === "references.d.ts"
) {
+4 -4
View File
@@ -17,7 +17,7 @@
"main": "lib/libjass.js",
"scripts": {
"prepublish": "node ./build.js clean default",
"build": "tsc ./build/typescript/index.ts ./build/doc.ts ./build/node.d.ts ./build/typescript/typescript.d.ts ./node_modules/async-build/typings.d.ts -m commonjs -t es5 -noImplicitAny --moduleResolution classic",
"build": "tsc -p ./build/tsconfig.json",
"test": "node ./build.js test",
"test-lib": "intern-client config=tests/intern reporters=Pretty",
"test-minified": "intern-client config=tests/intern reporters=Pretty minified=true",
@@ -26,12 +26,12 @@
},
"devDependencies": {
"async": "1.x >=1.4",
"async-build": "0.3.0",
"async-build": "0.3.1",
"intern": "3.x >=3.2.0",
"npm": "3.x",
"pngjs": "2.3.1",
"pngjs": "3.x",
"sax": "1.x",
"typescript": "1.8.10",
"typescript": "next",
"uglify-js": "2.x >=2.4.24"
},
"private": true
+8 -8
View File
@@ -67,27 +67,27 @@ export { version } from "./version";
export function configure(newConfig: {
debugMode?: boolean,
verboseMode?: boolean,
Set?: typeof set.Set,
Map?: typeof map.Map,
Promise?: typeof promise.Promise,
Set?: typeof set.Set | null,
Map?: typeof map.Map | null,
Promise?: typeof promise.Promise | null,
}): void {
if ("debugMode" in newConfig) {
if (typeof newConfig.debugMode === "boolean") {
settings.setDebugMode(newConfig.debugMode);
}
if ("verboseMode" in newConfig) {
if (typeof newConfig.verboseMode === "boolean") {
settings.setVerboseMode(newConfig.verboseMode);
}
if ("Set" in newConfig) {
if (typeof newConfig.Set === "function" || newConfig.Set === null) {
set.setImplementation(newConfig.Set);
}
if ("Map" in newConfig) {
if (typeof newConfig.Map === "function" || newConfig.Map === null) {
map.setImplementation(newConfig.Map);
}
if ("Promise" in newConfig) {
if (typeof newConfig.Promise === "function" || newConfig.Promise === null) {
promise.setImplementation(newConfig.Promise);
}
}
+2 -2
View File
@@ -28,7 +28,7 @@ import { Map } from "../utility/map";
* @param {string} line
* @return {Property}
*/
export function parseLineIntoProperty(line: string): Property {
export function parseLineIntoProperty(line: string): Property | null {
const colonPos = line.indexOf(":");
if (colonPos === -1) {
return null;
@@ -47,7 +47,7 @@ export function parseLineIntoProperty(line: string): Property {
* @param {!Array.<string>} formatSpecifier
* @return {TypedTemplate}
*/
export function parseLineIntoTypedTemplate(line: string, formatSpecifier: string[]): TypedTemplate {
export function parseLineIntoTypedTemplate(line: string, formatSpecifier: string[]): TypedTemplate | null {
const property = parseLineIntoProperty(line);
if (property === null) {
return null;
+92 -93
View File
@@ -71,7 +71,7 @@ class ParserRun {
/**
* @type {ParseNode}
*/
get result(): ParseNode {
get result(): ParseNode | null {
return this._result;
}
@@ -124,7 +124,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_enclosedTags(parent: ParseNode): ParseNode {
parse_enclosedTags(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
current.value = [];
@@ -135,7 +135,7 @@ class ParserRun {
}
for (let next = this._peek(); this._haveMore() && next !== "}"; next = this._peek()) {
let childNode: ParseNode = null;
let childNode: ParseNode | null = null;
if (this.read(current, "\\") !== null) {
childNode =
@@ -237,7 +237,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_newline(parent: ParseNode): ParseNode {
parse_newline(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "\\N") === null) {
@@ -254,7 +254,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_hardspace(parent: ParseNode): ParseNode {
parse_hardspace(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "\\h") === null) {
@@ -301,7 +301,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_a(parent: ParseNode): ParseNode {
parse_tag_a(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "a") === null) {
@@ -339,8 +339,8 @@ class ParserRun {
const valueNode = new ParseNode(current, next);
let value: number;
switch (valueNode.value) {
let value: number = -1;
switch ((valueNode.value)) {
case "1":
value = 1;
break;
@@ -387,7 +387,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_alpha(parent: ParseNode): ParseNode {
parse_tag_alpha(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -395,7 +395,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_an(parent: ParseNode): ParseNode {
parse_tag_an(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "an") === null) {
@@ -421,7 +421,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_b(parent: ParseNode): ParseNode {
parse_tag_b(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "b") === null) {
@@ -429,7 +429,7 @@ class ParserRun {
return null;
}
let valueNode: ParseNode = null;
let valueNode: ParseNode | null = null;
let next = this._peek();
@@ -459,7 +459,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_be(parent: ParseNode): ParseNode {
parse_tag_be(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -467,7 +467,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_blur(parent: ParseNode): ParseNode {
parse_tag_blur(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -475,7 +475,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_bord(parent: ParseNode): ParseNode {
parse_tag_bord(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -483,7 +483,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_c(parent: ParseNode): ParseNode {
parse_tag_c(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -491,7 +491,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_clip(parent: ParseNode): ParseNode {
parse_tag_clip(parent: ParseNode): ParseNode | null {
return this._parse_tag_clip_or_iclip("clip", parent);
}
@@ -499,7 +499,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fad(parent: ParseNode): ParseNode {
parse_tag_fad(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fad") === null) {
@@ -543,7 +543,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fade(parent: ParseNode): ParseNode {
parse_tag_fade(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fade") === null) {
@@ -646,7 +646,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fax(parent: ParseNode): ParseNode {
parse_tag_fax(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -654,7 +654,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fay(parent: ParseNode): ParseNode {
parse_tag_fay(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -662,7 +662,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fn(parent: ParseNode): ParseNode {
parse_tag_fn(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fn") === null) {
@@ -690,7 +690,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fr(parent: ParseNode): ParseNode {
parse_tag_fr(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -698,7 +698,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_frx(parent: ParseNode): ParseNode {
parse_tag_frx(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -706,7 +706,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fry(parent: ParseNode): ParseNode {
parse_tag_fry(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -714,7 +714,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_frz(parent: ParseNode): ParseNode {
parse_tag_frz(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -722,7 +722,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fs(parent: ParseNode): ParseNode {
parse_tag_fs(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -730,7 +730,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fsplus(parent: ParseNode): ParseNode {
parse_tag_fsplus(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fs+") === null) {
@@ -754,7 +754,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fsminus(parent: ParseNode): ParseNode {
parse_tag_fsminus(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fs-") === null) {
@@ -778,7 +778,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fscx(parent: ParseNode): ParseNode {
parse_tag_fscx(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fscx") === null) {
@@ -802,7 +802,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fscy(parent: ParseNode): ParseNode {
parse_tag_fscy(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "fscy") === null) {
@@ -826,7 +826,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_fsp(parent: ParseNode): ParseNode {
parse_tag_fsp(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -834,7 +834,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_i(parent: ParseNode): ParseNode {
parse_tag_i(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -842,7 +842,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_iclip(parent: ParseNode): ParseNode {
parse_tag_iclip(parent: ParseNode): ParseNode | null {
return this._parse_tag_clip_or_iclip("iclip", parent);
}
@@ -850,7 +850,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_k(parent: ParseNode): ParseNode {
parse_tag_k(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "k") === null) {
@@ -874,7 +874,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_K(parent: ParseNode): ParseNode {
parse_tag_K(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "K") === null) {
@@ -898,7 +898,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_kf(parent: ParseNode): ParseNode {
parse_tag_kf(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "kf") === null) {
@@ -922,7 +922,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_ko(parent: ParseNode): ParseNode {
parse_tag_ko(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "ko") === null) {
@@ -946,7 +946,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_move(parent: ParseNode): ParseNode {
parse_tag_move(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "move") === null) {
@@ -998,8 +998,8 @@ class ParserRun {
return null;
}
let t1Node: ParseNode = null;
let t2Node: ParseNode = null;
let t1Node: ParseNode | null = null;
let t2Node: ParseNode | null = null;
if (this.read(current, ",") !== null) {
t1Node = this.parse_decimal(current);
@@ -1037,7 +1037,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_org(parent: ParseNode): ParseNode {
parse_tag_org(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "org") === null) {
@@ -1081,7 +1081,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_p(parent: ParseNode): ParseNode {
parse_tag_p(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1089,7 +1089,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_pbo(parent: ParseNode): ParseNode {
parse_tag_pbo(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1097,7 +1097,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_pos(parent: ParseNode): ParseNode {
parse_tag_pos(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "pos") === null) {
@@ -1141,7 +1141,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_q(parent: ParseNode): ParseNode {
parse_tag_q(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "q") === null) {
@@ -1167,7 +1167,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_r(parent: ParseNode): ParseNode {
parse_tag_r(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "r") === null) {
@@ -1195,7 +1195,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_s(parent: ParseNode): ParseNode {
parse_tag_s(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1203,7 +1203,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_shad(parent: ParseNode): ParseNode {
parse_tag_shad(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1211,7 +1211,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_t(parent: ParseNode): ParseNode {
parse_tag_t(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, "t") === null) {
@@ -1224,9 +1224,9 @@ class ParserRun {
return null;
}
let startNode: ParseNode = null;
let endNode: ParseNode = null;
let accelNode: ParseNode = null;
let startNode: ParseNode | null = null;
let endNode: ParseNode | null = null;
let accelNode: ParseNode | null = null;
const firstNode = this.parse_decimal(current);
if (firstNode !== null) {
@@ -1268,7 +1268,7 @@ class ParserRun {
const transformTags: parts.Part[] = [];
for (let next = this._peek(); this._haveMore() && next !== ")" && next !== "}"; next = this._peek()) {
let childNode: ParseNode = null;
let childNode: ParseNode | null = null;
if (this.read(current, "\\") !== null) {
childNode =
@@ -1354,7 +1354,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_u(parent: ParseNode): ParseNode {
parse_tag_u(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1362,7 +1362,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_xbord(parent: ParseNode): ParseNode {
parse_tag_xbord(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1370,7 +1370,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_xshad(parent: ParseNode): ParseNode {
parse_tag_xshad(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1378,7 +1378,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_ybord(parent: ParseNode): ParseNode {
parse_tag_ybord(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1386,7 +1386,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_yshad(parent: ParseNode): ParseNode {
parse_tag_yshad(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1394,7 +1394,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_1a(parent: ParseNode): ParseNode {
parse_tag_1a(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1402,7 +1402,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_1c(parent: ParseNode): ParseNode {
parse_tag_1c(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1410,7 +1410,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_2a(parent: ParseNode): ParseNode {
parse_tag_2a(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1418,7 +1418,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_2c(parent: ParseNode): ParseNode {
parse_tag_2c(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1426,7 +1426,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_3a(parent: ParseNode): ParseNode {
parse_tag_3a(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1434,7 +1434,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_3c(parent: ParseNode): ParseNode {
parse_tag_3c(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1442,7 +1442,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_4a(parent: ParseNode): ParseNode {
parse_tag_4a(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1450,7 +1450,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_tag_4c(parent: ParseNode): ParseNode {
parse_tag_4c(parent: ParseNode): ParseNode | null {
throw new Error("Method not implemented.");
}
@@ -1461,7 +1461,7 @@ class ParserRun {
parse_drawingInstructions(parent: ParseNode): ParseNode {
const current = new ParseNode(parent);
let currentType: string = null;
let currentType: string | null = null;
const numberParts: ParseNode[] = [];
current.value = [];
@@ -1518,7 +1518,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_decimalInt32(parent: ParseNode): ParseNode {
parse_decimalInt32(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const isNegative = this.read(current, "-") !== null;
@@ -1550,7 +1550,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_hexInt32(parent: ParseNode): ParseNode {
parse_hexInt32(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const isNegative = this.read(current, "-") !== null;
@@ -1590,7 +1590,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_decimalOrHexInt32(parent: ParseNode): ParseNode {
parse_decimalOrHexInt32(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const valueNode =
@@ -1612,7 +1612,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_decimal(parent: ParseNode): ParseNode {
parse_decimal(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const negative = (this.read(current, "-") !== null);
@@ -1637,12 +1637,12 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_unsignedDecimal(parent: ParseNode): ParseNode {
parse_unsignedDecimal(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const characteristicNode = new ParseNode(current, "");
let mantissaNode: ParseNode = null;
let mantissaNode: ParseNode | null = null;
for (let next = this._peek(); this._haveMore() && next >= "0" && next <= "9"; next = this._peek()) {
characteristicNode.value += next;
@@ -1675,7 +1675,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_enableDisable(parent: ParseNode): ParseNode {
parse_enableDisable(parent: ParseNode): ParseNode | null {
const next = this._peek();
if (next === "0" || next === "1") {
@@ -1692,7 +1692,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_color(parent: ParseNode): ParseNode {
parse_color(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
while (this.read(current, "&") !== null || this.read(current, "H") !== null) { }
@@ -1720,7 +1720,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_alpha(parent: ParseNode): ParseNode {
parse_alpha(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
while (this.read(current, "&") !== null || this.read(current, "H") !== null) { }
@@ -1744,7 +1744,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
parse_colorWithAlpha(parent: ParseNode): ParseNode {
parse_colorWithAlpha(parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
const valueNode = this.parse_decimalOrHexInt32(current);
@@ -1770,7 +1770,7 @@ class ParserRun {
* @param {string} next
* @return {ParseNode}
*/
read(parent: ParseNode, next: string): ParseNode {
read(parent: ParseNode, next: string): ParseNode | null {
if (this._peek(next.length) !== next) {
return null;
}
@@ -1801,7 +1801,7 @@ class ParserRun {
* @param {!ParseNode} parent
* @return {ParseNode}
*/
private _parse_tag_clip_or_iclip(tagName: "clip" | "iclip", parent: ParseNode): ParseNode {
private _parse_tag_clip_or_iclip(tagName: "clip" | "iclip", parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (this.read(current, tagName) === null) {
@@ -1814,12 +1814,12 @@ class ParserRun {
return null;
}
let x1Node: ParseNode = null;
let x2Node: ParseNode = null;
let y1Node: ParseNode = null;
let y2Node: ParseNode = null;
let scaleNode: ParseNode = null;
let commandsNode: ParseNode = null;
let x1Node: ParseNode | null = null;
let x2Node: ParseNode | null = null;
let y1Node: ParseNode | null = null;
let y2Node: ParseNode | null = null;
let scaleNode: ParseNode | null = null;
let commandsNode: ParseNode | null = null;
const firstNode = this.parse_decimal(current);
@@ -1895,19 +1895,18 @@ class ParserRun {
function makeTagParserFunction(
tagName: string,
tagConstructor: { new (value: any): parts.Part },
valueParser: (current: ParseNode) => ParseNode,
valueParser: (current: ParseNode) => ParseNode | null,
required: boolean
): void {
(ParserRun.prototype as any)[`parse_tag_${ tagName }`] = function (parent: ParseNode): ParseNode {
const self = this as ParserRun;
(ParserRun.prototype as any)[`parse_tag_${ tagName }`] = function (this: ParserRun, parent: ParseNode): ParseNode | null {
const current = new ParseNode(parent);
if (self.read(current, tagName) === null) {
if (this.read(current, tagName) === null) {
parent.pop();
return null;
}
const valueNode = valueParser.call(self, current);
const valueNode: ParseNode | null = valueParser.call(this, current);
if (valueNode !== null) {
current.value = new tagConstructor(valueNode.value);
@@ -1975,7 +1974,7 @@ class ParseNode {
private _end: number;
private _value: any;
constructor(private _parent: ParseNode, value: any = null) {
constructor(private _parent: ParseNode | null, value: any = null) {
if (_parent !== null) {
_parent.children.push(this);
}
@@ -2007,7 +2006,7 @@ class ParseNode {
/**
* @type {ParseNode}
*/
get parent(): ParseNode {
get parent(): ParseNode | null {
return this._parent;
}
+7 -7
View File
@@ -54,7 +54,7 @@ export class StreamParser {
private _shouldSwallowBom: boolean = true;
private _currentSection: Section = Section.ScriptInfo;
private _currentAttachment: Attachment = null;
private _currentAttachment: Attachment | null = null;
constructor(private _stream: Stream) {
this._stream.nextLine().then(line => this._onNextLine(line), reason => {
@@ -118,7 +118,7 @@ export class StreamParser {
/**
* @param {string} line
*/
private _onNextLine(line: string): void {
private _onNextLine(line: string | null): void {
if (line === null) {
this.currentSection = Section.EOF;
return;
@@ -290,10 +290,10 @@ export class SrtStreamParser {
private _shouldSwallowBom: boolean = true;
private _currentDialogueNumber: string = null;
private _currentDialogueStart: string = null;
private _currentDialogueEnd: string = null;
private _currentDialogueText: string = null;
private _currentDialogueNumber: string | null = null;
private _currentDialogueStart: string | null = null;
private _currentDialogueEnd: string | null = null;
private _currentDialogueText: string | null = null;
constructor(private _stream: Stream) {
this._stream.nextLine().then(line => this._onNextLine(line), reason => {
@@ -319,7 +319,7 @@ export class SrtStreamParser {
/**
* @param {string} line
*/
private _onNextLine(line: string): void {
private _onNextLine(line: string | null): void {
if (line === null) {
if (this._currentDialogueNumber !== null && this._currentDialogueStart !== null && this._currentDialogueEnd !== null && this._currentDialogueText !== null) {
this._ass.dialogues.push(new Dialogue(new Map([
+16 -16
View File
@@ -65,7 +65,7 @@ export interface Stream {
/**
* @return {!Promise.<?string>} A promise that will be resolved with the next line, or null if the stream is exhausted.
*/
nextLine(): Promise<string>;
nextLine(): Promise<string | null>;
}
/**
@@ -81,8 +81,8 @@ export class StringStream implements Stream {
/**
* @return {!Promise.<?string>} A promise that will be resolved with the next line, or null if the string has been completely read.
*/
nextLine(): Promise<string> {
let result: Promise<string>;
nextLine(): Promise<string | null> {
let result: Promise<string | null>;
if (this._readTill < this._str.length) {
const nextNewLinePos = this._str.indexOf("\n", this._readTill);
@@ -96,7 +96,7 @@ export class StringStream implements Stream {
}
}
else {
result = Promise.resolve<string>(null);
result = Promise.resolve<string | null>(null);
}
return result;
@@ -111,8 +111,8 @@ export class StringStream implements Stream {
*/
export class XhrStream implements Stream {
private _readTill: number = 0;
private _pendingDeferred: DeferredPromise<string> = null;
private _failedError: ErrorEvent = null;
private _pendingDeferred: DeferredPromise<string | null> | null = null;
private _failedError: ErrorEvent | null = null;
constructor(private _xhr: XMLHttpRequest) {
_xhr.addEventListener("progress", () => this._onXhrProgress(), false);
@@ -181,7 +181,7 @@ export class XhrStream implements Stream {
*/
private _tryResolveNextLine(): void {
if (this._failedError !== null) {
this._pendingDeferred.reject(this._failedError);
this._pendingDeferred!.reject(this._failedError);
return;
}
@@ -189,23 +189,23 @@ export class XhrStream implements Stream {
const nextNewLinePos = response.indexOf("\n", this._readTill);
if (nextNewLinePos !== -1) {
this._pendingDeferred.resolve(response.substring(this._readTill, nextNewLinePos));
this._pendingDeferred!.resolve(response.substring(this._readTill, nextNewLinePos));
this._readTill = nextNewLinePos + 1;
this._pendingDeferred = null;
}
else if (this._xhr.readyState === XMLHttpRequest.DONE) {
if (this._failedError !== null) {
this._pendingDeferred.reject(this._failedError);
this._pendingDeferred!.reject(this._failedError);
}
// No more data. This is the last line.
else if (this._readTill < response.length) {
this._pendingDeferred.resolve(response.substr(this._readTill));
this._pendingDeferred!.resolve(response.substr(this._readTill));
this._readTill = response.length;
}
else {
this._pendingDeferred.resolve(null);
this._pendingDeferred!.resolve(null);
}
this._pendingDeferred = null;
@@ -223,11 +223,11 @@ export class BrowserReadableStream implements Stream {
private _reader: ReadableStreamReader;
private _decoder: TextDecoder;
private _buffer: string = "";
private _pendingDeferred: DeferredPromise<string> = null;
private _pendingDeferred: DeferredPromise<string | null> | null = null;
constructor(stream: ReadableStream, encoding: string) {
this._reader = stream.getReader();
this._decoder = new global.TextDecoder(encoding, { ignoreBOM: true });
this._decoder = new global.TextDecoder!(encoding, { ignoreBOM: true });
}
/**
@@ -250,7 +250,7 @@ export class BrowserReadableStream implements Stream {
private _tryResolveNextLine(): void {
const nextNewLinePos = this._buffer.indexOf("\n");
if (nextNewLinePos !== -1) {
this._pendingDeferred.resolve(this._buffer.substr(0, nextNewLinePos));
this._pendingDeferred!.resolve(this._buffer.substr(0, nextNewLinePos));
this._buffer = this._buffer.substr(nextNewLinePos + 1);
this._pendingDeferred = null;
}
@@ -266,10 +266,10 @@ export class BrowserReadableStream implements Stream {
else {
// No more data.
if (this._buffer.length === 0) {
this._pendingDeferred.resolve(null);
this._pendingDeferred!.resolve(null);
}
else {
this._pendingDeferred.resolve(this._buffer);
this._pendingDeferred!.resolve(this._buffer);
this._buffer = "";
}
+1 -1
View File
@@ -103,7 +103,7 @@ export function getTtfNames(attachment: Attachment): Set<string> {
const reader = { dataView: new DataView(bytes.buffer), position: 0 };
const offsetTable = OffsetTable.read(reader);
let nameTableRecord: TableRecord = null;
let nameTableRecord: TableRecord | null = null;
for (let i = 0; i < offsetTable.numTables; i++) {
const tableRecord = TableRecord.read(reader);
if (tableRecord.c1 + tableRecord.c2 + tableRecord.c3 + tableRecord.c4 === "name") {
+19 -19
View File
@@ -186,14 +186,14 @@ export class Italic {
* @param {?boolean|?number} value {\b1} -> true, {\b0} -> false, {\b###} -> weight of the bold (number), {\b} -> null
*/
export class Bold {
constructor(private _value: boolean | number) { }
constructor(private _value: boolean | number | null) { }
/**
* The value of this bold tag.
*
* @type {?boolean|?number}
*/
get value(): boolean | number {
get value(): boolean | number | null {
return this._value;
}
}
@@ -384,14 +384,14 @@ export class GaussianBlur {
* @param {?string} value {\fn###} -> name (string), {\fn} -> null
*/
export class FontName {
constructor(private _value: string) { }
constructor(private _value: string | null) { }
/**
* The value of this font name tag.
*
* @type {?string}
*/
get value(): string {
get value(): string | null {
return this._value;
}
}
@@ -456,14 +456,14 @@ export class FontSizeMinus {
* @param {?number} value {\fscx###} -> scale (number), {\fscx} -> null
*/
export class FontScaleX {
constructor(private _value: number) { }
constructor(private _value: number | null) { }
/**
* The value of this horizontal font scaling tag.
*
* @type {?number}
*/
get value(): number {
get value(): number | null {
return this._value;
}
}
@@ -474,14 +474,14 @@ export class FontScaleX {
* @param {?number} value {\fscy###} -> scale (number), {\fscy} -> null
*/
export class FontScaleY {
constructor(private _value: number) { }
constructor(private _value: number | null) { }
/**
* The value of this vertical font scaling tag.
*
* @type {?number}
*/
get value(): number {
get value(): number | null {
return this._value;
}
}
@@ -852,14 +852,14 @@ export class WrappingStyle {
* @param {?string} value {\r###} -> style name (string), {\r} -> null
*/
export class Reset {
constructor(private _value: string) { }
constructor(private _value: string | null) { }
/**
* The value of this style reset tag.
*
* @type {?string}
*/
get value(): string {
get value(): string | null {
return this._value;
}
}
@@ -903,7 +903,7 @@ export class Position {
* @param {?number} t2
*/
export class Move {
constructor(private _x1: number, private _y1: number, private _x2: number, private _y2: number, private _t1: number, private _t2: number) { }
constructor(private _x1: number, private _y1: number, private _x2: number, private _y2: number, private _t1: number | null, private _t2: number | null) { }
/**
* The starting x value of this move tag.
@@ -946,7 +946,7 @@ export class Move {
*
* @type {?number}
*/
get t1(): number {
get t1(): number | null {
return this._t1;
}
@@ -955,7 +955,7 @@ export class Move {
*
* @type {?number}
*/
get t2(): number {
get t2(): number | null {
return this._t2;
}
}
@@ -1106,14 +1106,14 @@ export class ComplexFade {
* @param {!Array.<!libjass.parts.Tag>} tags
*/
export class Transform {
constructor(private _start: number, private _end: number, private _accel: number, private _tags: Part[]) { }
constructor(private _start: number | null, private _end: number | null, private _accel: number | null, private _tags: Part[]) { }
/**
* The starting time of this transform tag.
*
* @type {?number}
*/
get start(): number {
get start(): number | null {
return this._start;
}
@@ -1122,7 +1122,7 @@ export class Transform {
*
* @type {?number}
*/
get end(): number {
get end(): number | null {
return this._end;
}
@@ -1131,7 +1131,7 @@ export class Transform {
*
* @type {?number}
*/
get accel(): number {
get accel(): number | null {
return this._accel;
}
@@ -1299,10 +1299,10 @@ const addToString = function (ctor: Function, ctorName: string) {
if (!ctor.prototype.hasOwnProperty("toString")) {
const propertyNames = Object.getOwnPropertyNames(ctor.prototype).filter(property => property !== "constructor");
ctor.prototype.toString = function () {
ctor.prototype.toString = function (this: any) {
return (
ctorName + " { " +
propertyNames.map(name => `${ name }: ${ (this as any)[name] }`).join(", ") +
propertyNames.map(name => `${ name }: ${ this[name] }`).join(", ") +
((propertyNames.length > 0) ? " " : "") +
"}"
);
+3 -3
View File
@@ -41,10 +41,10 @@ import { ManualClock } from "./manual";
export class AutoClock implements Clock {
private _manualClock: ManualClock = new ManualClock();
private _nextAnimationFrameRequestId: number = null;
private _nextAnimationFrameRequestId: number | null = null;
private _lastKnownExternalTime: number = null;
private _lastKnownExternalTimeObtainedAt: number = null;
private _lastKnownExternalTime: number | null = null;
private _lastKnownExternalTimeObtainedAt: number | null = null;
constructor(private _getCurrentTime: () => number, private _autoPauseAfter: number) { }
+28
View File
@@ -0,0 +1,28 @@
/**
* libjass
*
* https://github.com/Arnavion/libjass
*
* Copyright 2013 Arnav Singh
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
interface Array<T> {
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
}
+3 -3
View File
@@ -45,7 +45,7 @@ export class RendererSettings {
*
* @type {Map.<string, (string|!Array.<string>)>}
*/
fontMap: Map<string, string | string[]>;
fontMap: Map<string, string | string[]> | null;
/**
* Subtitles will be pre-rendered for this amount of time (seconds).
@@ -121,13 +121,13 @@ export class RendererSettings {
const rule = styleSheet.cssRules[i];
if (isFontFaceRule(rule)) {
const name = rule.style.getPropertyValue("font-family").match(/^["']?(.*?)["']?$/)[1];
const name = rule.style.getPropertyValue("font-family").match(/^["']?(.*?)["']?$/)![1];
let src = rule.style.getPropertyValue("src");
if (!src) {
src = rule.cssText.split("\n")
.map(line => line.match(/src:\s*([^;]+?)\s*;/))
.filter(matches => matches !== null)
.filter((matches): matches is RegExpMatchArray => matches !== null)
.map(matches => matches[1])[0];
}
+6 -6
View File
@@ -71,12 +71,8 @@ export class AnimationCollection {
* @param {!Array.<!libjass.renderers.Keyframe>} keyframes
*/
add(timingFunction: string, keyframes: Keyframe[]): void {
if (keyframes.length < 1) {
throw new Error("Atleast one keyframe must be provided.");
}
let start: number = null;
let end: number = null;
let start: number | null = null;
let end: number | null = null;
for (const keyframe of keyframes) {
if (start === null) {
@@ -86,6 +82,10 @@ export class AnimationCollection {
end = keyframe.time;
}
if (start === null || end === null) {
throw new Error("Atleast one keyframe must be provided.");
}
let ruleCssText = "";
for (const keyframe of keyframes) {
+29 -27
View File
@@ -215,7 +215,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
}
});
let fontFetchPromise: Promise<FontFace>;
let fontFetchPromise: Promise<FontFace | null>;
if (existingFontFaces.length === 0) {
const fontFace = new FontFace(fontFamily, source);
const quotedFontFace = new FontFace(`"${ fontFamily }"`, source);
@@ -254,7 +254,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
// A url() URL. Extract the raw URL.
return match[2];
}).filter(url => url !== null);
}).filter((url): url is string => url !== null);
const attachedFontUrls = attachedFontsMap.get(fontFamily);
if (attachedFontUrls !== undefined) {
@@ -266,7 +266,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
let fontFetchPromise = fontFetchPromisesCache.get(url);
if (fontFetchPromise === undefined) {
fontFetchPromise =
new Promise<void>((resolve, reject) => {
new Promise<null>((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener("load", () => {
if (debugMode) {
@@ -290,7 +290,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
const allFontsFetchedPromise =
(thisFontFamilysFetchPromises.length === 0) ?
Promise.resolve<void>(null) :
Promise.resolve(null) :
Promise_first(thisFontFamilysFetchPromises).catch(reason => {
console.warn(`Fetching fonts for ${ fontFamily } at ${ urls.join(", ") } failed: %o`, reason);
return null;
@@ -354,7 +354,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
* @param {!libjass.Dialogue} dialogue
* @return {PreRenderedSub}
*/
preRender(dialogue: Dialogue): PreRenderedSub {
preRender(dialogue: Dialogue): PreRenderedSub | null {
const currentTimeRelativeToDialogueStart = this.clock.currentTime - dialogue.start;
if (dialogue.containsTransformTag && currentTimeRelativeToDialogueStart < 0) {
@@ -389,15 +389,15 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
const svgDefsElement = document.createElementNS("http://www.w3.org/2000/svg", "defs");
svgElement.appendChild(svgDefsElement);
let currentSpan: HTMLSpanElement = null;
let currentSpan: HTMLSpanElement | null = null;
const currentSpanStyles = new SpanStyles(this, dialogue, this._scaleX, this._scaleY, this.settings, this._fontSizeElement, svgDefsElement, this._fontMetricsCache);
let currentAnimationCollection: AnimationCollection = null;
let currentAnimationCollection: AnimationCollection | null = null;
let previousAddNewLine = false; // If two or more \N's are encountered in sequence, then all but the first will be created using currentSpanStyles.makeNewLine() instead
const startNewSpan = (addNewLine: boolean): void => {
if (currentSpan !== null && currentSpan.hasChildNodes()) {
sub.appendChild(currentSpanStyles.setStylesOnSpan(currentSpan, currentAnimationCollection));
sub.appendChild(currentSpanStyles.setStylesOnSpan(currentSpan, currentAnimationCollection!));
}
if (currentAnimationCollection !== null) {
@@ -571,11 +571,11 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
else if (part instanceof parts.ColorKaraoke) {
startNewSpan(false);
currentAnimationCollection.add("step-end", [
currentAnimationCollection!.add("step-end", [
new Keyframe(0, new Map([
["color", currentSpanStyles.secondaryColor.withAlpha(currentSpanStyles.secondaryAlpha).toString()],
["color", currentSpanStyles.secondaryColor!.withAlpha(currentSpanStyles.secondaryAlpha!).toString()],
])), new Keyframe(karaokeTimesAccumulator, new Map([
["color", currentSpanStyles.primaryColor.withAlpha(currentSpanStyles.primaryAlpha).toString()],
["color", currentSpanStyles.primaryColor!.withAlpha(currentSpanStyles.primaryAlpha!).toString()],
]))
]);
@@ -607,10 +607,10 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
dialogueAnimationCollection.add("linear", [new Keyframe(0, new Map([
["left", `${ (this._scaleX * part.x1).toFixed(3) }px`],
["top", `${ (this._scaleY * part.y1).toFixed(3) }px`],
])), new Keyframe(part.t1, new Map([
])), new Keyframe(part.t1!, new Map([
["left", `${ (this._scaleX * part.x1).toFixed(3) }px`],
["top", `${ (this._scaleY * part.y1).toFixed(3) }px`],
])), new Keyframe(part.t2, new Map([
])), new Keyframe(part.t2!, new Map([
["left", `${ (this._scaleX * part.x2).toFixed(3) }px`],
["top", `${ (this._scaleY * part.y2).toFixed(3) }px`],
])), new Keyframe(dialogue.end - dialogue.start, new Map([
@@ -651,7 +651,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
const progression =
(currentTimeRelativeToDialogueStart <= part.start) ? 0 :
(currentTimeRelativeToDialogueStart >= part.end) ? 1 :
Math.pow((currentTimeRelativeToDialogueStart - part.start) / (part.end - part.start), part.accel);
Math.pow((currentTimeRelativeToDialogueStart - part.start) / (part.end - part.start), part.accel!);
for (const tag of part.tags) {
if (tag instanceof parts.Border) {
@@ -821,7 +821,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
else if (tag instanceof parts.PrimaryColor) {
if (tag.value !== null) {
currentSpanStyles.primaryColor = currentSpanStyles.primaryColor.interpolate(tag.value, progression);
currentSpanStyles.primaryColor = currentSpanStyles.primaryColor!.interpolate(tag.value, progression);
}
else {
currentSpanStyles.primaryColor = null;
@@ -830,7 +830,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
else if (tag instanceof parts.SecondaryColor) {
if (tag.value !== null) {
currentSpanStyles.secondaryColor = currentSpanStyles.secondaryColor.interpolate(tag.value, progression);
currentSpanStyles.secondaryColor = currentSpanStyles.secondaryColor!.interpolate(tag.value, progression);
}
else {
currentSpanStyles.secondaryColor = null;
@@ -839,7 +839,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
else if (tag instanceof parts.OutlineColor) {
if (tag.value !== null) {
currentSpanStyles.outlineColor = currentSpanStyles.outlineColor.interpolate(tag.value, progression);
currentSpanStyles.outlineColor = currentSpanStyles.outlineColor!.interpolate(tag.value, progression);
}
else {
currentSpanStyles.outlineColor = null;
@@ -848,7 +848,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
else if (tag instanceof parts.ShadowColor) {
if (tag.value !== null) {
currentSpanStyles.shadowColor = currentSpanStyles.shadowColor.interpolate(tag.value, progression);
currentSpanStyles.shadowColor = currentSpanStyles.shadowColor!.interpolate(tag.value, progression);
}
else {
currentSpanStyles.shadowColor = null;
@@ -919,17 +919,17 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
}
else if (part instanceof parts.DrawingInstructions) {
currentSpan.appendChild(currentDrawingStyles.toSVG(part, currentSpanStyles.primaryColor.withAlpha(currentSpanStyles.primaryAlpha)));
currentSpan!.appendChild(currentDrawingStyles.toSVG(part, currentSpanStyles.primaryColor!.withAlpha(currentSpanStyles.primaryAlpha!)));
startNewSpan(false);
}
else if (part instanceof parts.Text) {
currentSpan.appendChild(document.createTextNode(part.value + "\u200C"));
currentSpan!.appendChild(document.createTextNode(part.value + "\u200C"));
startNewSpan(false);
}
else if (debugMode && part instanceof parts.Comment) {
currentSpan.appendChild(document.createTextNode(part.value));
currentSpan!.appendChild(document.createTextNode(part.value));
startNewSpan(false);
}
@@ -1029,16 +1029,18 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
console.log(dialogue.toString());
}
let preRenderedSub = this._preRenderedSubs.get(dialogue.id);
let thePreRenderedSub = this._preRenderedSubs.get(dialogue.id);
if (preRenderedSub === undefined) {
preRenderedSub = this.preRender(dialogue);
if (thePreRenderedSub === undefined) {
thePreRenderedSub = this.preRender(dialogue)!;
if (debugMode) {
console.log(dialogue.toString());
}
}
const preRenderedSub = thePreRenderedSub;
const result = preRenderedSub.sub.cloneNode(true);
const applyAnimationDelays = (node: HTMLElement) => {
@@ -1069,7 +1071,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
layerWrapper.className = `layer layer${ layer }`;
// Find the next greater layer div and insert this div before that one
let insertBeforeElement: HTMLDivElement = null;
let insertBeforeElement: HTMLDivElement | null = null;
for (let insertBeforeLayer = layer + 1; insertBeforeLayer < this._layerWrappers.length && insertBeforeElement === null; insertBeforeLayer++) {
if (this._layerWrappers[insertBeforeLayer] !== undefined) {
insertBeforeElement = this._layerWrappers[insertBeforeLayer];
@@ -1089,7 +1091,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
// Find the next greater layer,alignment div and insert this div before that one
const layerWrapper = this._layerWrappers[layer];
let insertBeforeElement: HTMLDivElement = null;
let insertBeforeElement: HTMLDivElement | null = null;
for (let insertBeforeAlignment = alignment + 1; insertBeforeAlignment < this._layerAlignmentWrappers[layer].length && insertBeforeElement === null; insertBeforeAlignment++) {
if (this._layerAlignmentWrappers[layer][insertBeforeAlignment] !== undefined) {
insertBeforeElement = this._layerAlignmentWrappers[layer][insertBeforeAlignment];
@@ -1113,7 +1115,7 @@ export class WebRenderer extends NullRenderer implements EventSource<string> {
if (dialogueAnimationStylesElement !== undefined) {
const sheet = dialogueAnimationStylesElement.sheet as CSSStyleSheet;
if (sheet.cssRules.length === 0) {
sheet.cssText = dialogueAnimationStylesElement.textContent;
sheet.cssText = dialogueAnimationStylesElement.textContent!;
}
}
+50 -50
View File
@@ -103,7 +103,7 @@ export class SpanStyles {
*
* @param {libjass.Style} newStyle The new defaults to reset the style to. If null, the styles are reset to the default style of the Dialogue.
*/
reset(newStyle: Style): void {
reset(newStyle: Style | undefined | null): void {
if (newStyle === undefined || newStyle === null) {
newStyle = this._defaultStyle;
}
@@ -607,7 +607,7 @@ export class SpanStyles {
*
* @type {(?boolean|?number)}
*/
set bold(value: boolean | number) {
set bold(value: boolean | number | null) {
this._bold = valueOrDefault(value, this._defaultStyle.bold);
}
@@ -634,7 +634,7 @@ export class SpanStyles {
*
* @type {number}
*/
get outlineWidth(): number {
get outlineWidth(): number | null {
return this._outlineWidth;
}
@@ -643,7 +643,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set outlineWidth(value: number) {
set outlineWidth(value: number | null) {
this._outlineWidth = valueOrDefault(value, this._defaultStyle.outlineThickness);
}
@@ -652,7 +652,7 @@ export class SpanStyles {
*
* @type {number}
*/
get outlineHeight(): number {
get outlineHeight(): number | null {
return this._outlineHeight;
}
@@ -661,7 +661,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set outlineHeight(value: number) {
set outlineHeight(value: number | null) {
this._outlineHeight = valueOrDefault(value, this._defaultStyle.outlineThickness);
}
@@ -670,7 +670,7 @@ export class SpanStyles {
*
* @type {number}
*/
get shadowDepthX(): number {
get shadowDepthX(): number | null {
return this._shadowDepthX;
}
@@ -679,7 +679,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set shadowDepthX(value: number) {
set shadowDepthX(value: number | null) {
this._shadowDepthX = valueOrDefault(value, this._defaultStyle.shadowDepth);
}
@@ -688,7 +688,7 @@ export class SpanStyles {
*
* @type {number}
*/
get shadowDepthY(): number {
get shadowDepthY(): number | null {
return this._shadowDepthY;
}
@@ -697,7 +697,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set shadowDepthY(value: number) {
set shadowDepthY(value: number | null) {
this._shadowDepthY = valueOrDefault(value, this._defaultStyle.shadowDepth);
}
@@ -706,7 +706,7 @@ export class SpanStyles {
*
* @type {number}
*/
get blur(): number {
get blur(): number | null {
return this._blur;
}
@@ -715,7 +715,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set blur(value: number) {
set blur(value: number | null) {
this._blur = valueOrDefault(value, 0);
}
@@ -724,7 +724,7 @@ export class SpanStyles {
*
* @type {number}
*/
get gaussianBlur(): number {
get gaussianBlur(): number | null {
return this._gaussianBlur;
}
@@ -733,7 +733,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set gaussianBlur(value: number) {
set gaussianBlur(value: number | null) {
this._gaussianBlur = valueOrDefault(value, 0);
}
@@ -742,7 +742,7 @@ export class SpanStyles {
*
* @type {?string}
*/
set fontName(value: string) {
set fontName(value: string | null) {
this._fontName = valueOrDefault(value, this._defaultStyle.fontName);
}
@@ -751,7 +751,7 @@ export class SpanStyles {
*
* @type {number}
*/
get fontSize(): number {
get fontSize(): number | null {
return this._fontSize;
}
@@ -760,7 +760,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set fontSize(value: number) {
set fontSize(value: number | null) {
this._fontSize = valueOrDefault(value, this._defaultStyle.fontSize);
}
@@ -769,7 +769,7 @@ export class SpanStyles {
*
* @type {number}
*/
get fontScaleX(): number {
get fontScaleX(): number | null {
return this._fontScaleX;
}
@@ -778,7 +778,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set fontScaleX(value: number) {
set fontScaleX(value: number | null) {
this._fontScaleX = valueOrDefault(value, this._defaultStyle.fontScaleX);
}
@@ -787,7 +787,7 @@ export class SpanStyles {
*
* @type {number}
*/
get fontScaleY(): number {
get fontScaleY(): number | null {
return this._fontScaleY;
}
@@ -796,7 +796,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set fontScaleY(value: number) {
set fontScaleY(value: number | null) {
this._fontScaleY = valueOrDefault(value, this._defaultStyle.fontScaleY);
}
@@ -805,7 +805,7 @@ export class SpanStyles {
*
* @type {number}
*/
get letterSpacing(): number {
get letterSpacing(): number | null {
return this._letterSpacing;
}
@@ -814,7 +814,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set letterSpacing(value: number) {
set letterSpacing(value: number | null) {
this._letterSpacing = valueOrDefault(value, this._defaultStyle.letterSpacing);
}
@@ -823,7 +823,7 @@ export class SpanStyles {
*
* @type {number}
*/
get rotationX(): number {
get rotationX(): number | null {
return this._rotationX;
}
@@ -832,7 +832,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set rotationX(value: number) {
set rotationX(value: number | null) {
this._rotationX = valueOrDefault(value, 0);
}
@@ -841,7 +841,7 @@ export class SpanStyles {
*
* @type {number}
*/
get rotationY(): number {
get rotationY(): number | null {
return this._rotationY;
}
@@ -850,7 +850,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set rotationY(value: number) {
set rotationY(value: number | null) {
this._rotationY = valueOrDefault(value, 0);
}
@@ -859,7 +859,7 @@ export class SpanStyles {
*
* @type {number}
*/
get rotationZ(): number {
get rotationZ(): number | null {
return this._rotationZ;
}
@@ -868,7 +868,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set rotationZ(value: number) {
set rotationZ(value: number | null) {
this._rotationZ = valueOrDefault(value, this._defaultStyle.rotationZ);
}
@@ -877,7 +877,7 @@ export class SpanStyles {
*
* @type {number}
*/
get skewX(): number {
get skewX(): number | null {
return this._skewX;
}
@@ -886,7 +886,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set skewX(value: number) {
set skewX(value: number | null) {
this._skewX = valueOrDefault(value, 0);
}
@@ -895,7 +895,7 @@ export class SpanStyles {
*
* @type {number}
*/
get skewY(): number {
get skewY(): number | null {
return this._skewY;
}
@@ -904,7 +904,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set skewY(value: number) {
set skewY(value: number | null) {
this._skewY = valueOrDefault(value, 0);
}
@@ -913,7 +913,7 @@ export class SpanStyles {
*
* @type {!libjass.Color}
*/
get primaryColor(): Color {
get primaryColor(): Color | null {
return this._primaryColor;
}
@@ -922,7 +922,7 @@ export class SpanStyles {
*
* @type {libjass.Color}
*/
set primaryColor(value: Color) {
set primaryColor(value: Color | null) {
this._primaryColor = valueOrDefault(value, this._defaultStyle.primaryColor);
}
@@ -931,7 +931,7 @@ export class SpanStyles {
*
* @type {!libjass.Color}
*/
get secondaryColor(): Color {
get secondaryColor(): Color | null {
return this._secondaryColor;
}
@@ -940,7 +940,7 @@ export class SpanStyles {
*
* @type {libjass.Color}
*/
set secondaryColor(value: Color) {
set secondaryColor(value: Color | null) {
this._secondaryColor = valueOrDefault(value, this._defaultStyle.secondaryColor);
}
@@ -949,7 +949,7 @@ export class SpanStyles {
*
* @type {!libjass.Color}
*/
get outlineColor(): Color {
get outlineColor(): Color | null {
return this._outlineColor;
}
@@ -958,7 +958,7 @@ export class SpanStyles {
*
* @type {libjass.Color}
*/
set outlineColor(value: Color) {
set outlineColor(value: Color | null) {
this._outlineColor = valueOrDefault(value, this._defaultStyle.outlineColor);
}
@@ -967,7 +967,7 @@ export class SpanStyles {
*
* @type {!libjass.Color}
*/
get shadowColor(): Color {
get shadowColor(): Color | null {
return this._shadowColor;
}
@@ -976,7 +976,7 @@ export class SpanStyles {
*
* @type {libjass.Color}
*/
set shadowColor(value: Color) {
set shadowColor(value: Color | null) {
this._shadowColor = valueOrDefault(value, this._defaultStyle.shadowColor);
}
@@ -985,7 +985,7 @@ export class SpanStyles {
*
* @type {number}
*/
get primaryAlpha(): number {
get primaryAlpha(): number | null {
return this._primaryAlpha;
}
@@ -994,7 +994,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set primaryAlpha(value: number) {
set primaryAlpha(value: number | null) {
this._primaryAlpha = valueOrDefault(value, this._defaultStyle.primaryColor.alpha);
}
@@ -1003,7 +1003,7 @@ export class SpanStyles {
*
* @type {number}
*/
get secondaryAlpha(): number {
get secondaryAlpha(): number | null {
return this._secondaryAlpha;
}
@@ -1012,7 +1012,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set secondaryAlpha(value: number) {
set secondaryAlpha(value: number | null) {
this._secondaryAlpha = valueOrDefault(value, this._defaultStyle.secondaryColor.alpha);
}
@@ -1021,7 +1021,7 @@ export class SpanStyles {
*
* @type {number}
*/
get outlineAlpha(): number {
get outlineAlpha(): number | null {
return this._outlineAlpha;
}
@@ -1030,7 +1030,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set outlineAlpha(value: number) {
set outlineAlpha(value: number | null) {
this._outlineAlpha = valueOrDefault(value, this._defaultStyle.outlineColor.alpha);
}
@@ -1039,7 +1039,7 @@ export class SpanStyles {
*
* @type {number}
*/
get shadowAlpha(): number {
get shadowAlpha(): number | null {
return this._shadowAlpha;
}
@@ -1048,7 +1048,7 @@ export class SpanStyles {
*
* @type {?number}
*/
set shadowAlpha(value: number) {
set shadowAlpha(value: number | null) {
this._shadowAlpha = valueOrDefault(value, this._defaultStyle.shadowColor.alpha);
}
}
@@ -1092,6 +1092,6 @@ function createComponentTransferFilter(color: Color): SVGFEComponentTransferElem
* @param {!T} defaultValue
* @return {!T}
*/
function valueOrDefault<T>(newValue: T, defaultValue: T): T {
function valueOrDefault<T>(newValue: T | null, defaultValue: T): T {
return ((newValue !== null) ? newValue : defaultValue);
}
+7
View File
@@ -1,9 +1,16 @@
{
"compilerOptions": {
"lib": ["es5", "dom"],
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": false,
"strictNullChecks": true,
"target": "es5",
"module": "amd",
+7 -7
View File
@@ -38,7 +38,7 @@ import { registerClass as serializable } from "../serialization";
declare const global: {
fetch?(url: string): Promise<{ body: ReadableStream; ok?: boolean; status?: number; }>;
ReadableStream?: { prototype: ReadableStream; };
ReadableStream?: Function & { prototype: ReadableStream; };
TextDecoder?: TextDecoderConstructor;
};
@@ -52,8 +52,8 @@ export class ASS {
private _dialogues: Dialogue[] = [];
private _attachments: Attachment[] = [];
private _stylesFormatSpecifier: string[] = null;
private _dialoguesFormatSpecifier: string[] = null;
private _stylesFormatSpecifier: string[] | null = null;
private _dialoguesFormatSpecifier: string[] | null = null;
/**
* The properties of this script.
@@ -96,7 +96,7 @@ export class ASS {
*
* @type {Array.<string>}
*/
get stylesFormatSpecifier(): string[] {
get stylesFormatSpecifier(): string[] | null {
return this._stylesFormatSpecifier;
}
@@ -105,7 +105,7 @@ export class ASS {
*
* @type {Array.<string>}
*/
get dialoguesFormatSpecifier(): string[] {
get dialoguesFormatSpecifier(): string[] | null {
return this._dialoguesFormatSpecifier;
}
@@ -114,7 +114,7 @@ export class ASS {
*
* @type {Array.<string>}
*/
set stylesFormatSpecifier(value: string[]) {
set stylesFormatSpecifier(value: string[] | null) {
this._stylesFormatSpecifier = value;
}
@@ -123,7 +123,7 @@ export class ASS {
*
* @type {Array.<string>}
*/
set dialoguesFormatSpecifier(value: string[]) {
set dialoguesFormatSpecifier(value: string[] | null) {
this._dialoguesFormatSpecifier = value;
}
+4 -4
View File
@@ -59,7 +59,7 @@ export class Dialogue {
private _alignment: number;
private _rawPartsString: string;
private _parts: parts.Part[] = null;
private _parts: parts.Part[] | null = null;
private _containsTransformTag: boolean = false;
@@ -184,7 +184,7 @@ export class Dialogue {
this._parsePartsString();
}
return this._parts;
return this._parts!;
}
/**
@@ -221,7 +221,7 @@ export class Dialogue {
}
else if (part instanceof parts.Move) {
if (part.t1 === null || part.t2 === null) {
this._parts[index] =
this._parts![index] =
new parts.Move(
part.x1, part.y1, part.x2, part.y2,
0, this._end - this._start
@@ -230,7 +230,7 @@ export class Dialogue {
}
else if (part instanceof parts.Transform) {
if (part.start === null || part.end === null || part.accel === null) {
this._parts[index] =
this._parts![index] =
new parts.Transform(
(part.start === null) ? 0 : part.start,
(part.end === null) ? (this._end - this._start) : part.end,
+1 -1
View File
@@ -84,7 +84,7 @@ export interface TypedTemplate {
* @param {T} defaultValue
* @return {T}
*/
export function valueOrDefault<T>(template: Map<string, string>, key: string, converter: (str: string) => T, validator: (value: T) => boolean, defaultValue: string): T {
export function valueOrDefault<T>(template: Map<string, string>, key: string, converter: (str: string) => T, validator: ((value: T) => boolean) | null, defaultValue: string): T {
const value = template.get(key);
if (value === undefined) {
return converter(defaultValue);
+13 -13
View File
@@ -18,16 +18,12 @@
* limitations under the License.
*/
declare const global: {
Map?: typeof Map;
};
export interface Map<K, V> {
/**
* @param {K} key
* @return {?V}
*/
get(key: K): V;
get(key: K): V | undefined;
/**
* @param {K} key
@@ -40,7 +36,7 @@ export interface Map<K, V> {
* @param {V} value
* @return {libjass.Map.<K, V>} This map
*/
set(key: K, value?: V): Map<K, V>;
set(key: K, value: V): this;
/**
* @param {K} key
@@ -56,7 +52,7 @@ export interface Map<K, V> {
* @param {function(V, K, libjass.Map.<K, V>)} callbackfn A function that is called with each key and value in the map.
* @param {*} thisArg
*/
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
forEach(callbackfn: (value: V, index: K, map: this) => void, thisArg?: any): void;
/**
* @type {number}
@@ -71,7 +67,7 @@ export interface Map<K, V> {
*
* @param {!Array.<!Array.<*>>=} iterable Only an array of elements (where each element is a 2-tuple of key and value) is supported.
*/
class SimpleMap<K, V> {
class SimpleMap<K, V> implements Map<K, V> {
private _keys: { [key: string]: K };
private _values: { [key: string]: V };
private _size: number;
@@ -96,7 +92,7 @@ class SimpleMap<K, V> {
* @param {K} key
* @return {?V}
*/
get(key: K): V {
get(key: K): V | undefined {
const property = this._keyToProperty(key);
if (property === null) {
@@ -125,7 +121,7 @@ class SimpleMap<K, V> {
* @param {V} value
* @return {libjass.Map.<K, V>} This map
*/
set(key: K, value: V): Map<K, V> {
set(key: K, value: V): this {
const property = this._keyToProperty(key);
if (property === null) {
@@ -176,7 +172,7 @@ class SimpleMap<K, V> {
* @param {function(V, K, libjass.Map.<K, V>)} callbackfn A function that is called with each key and value in the map.
* @param {*} thisArg
*/
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void {
forEach(callbackfn: (value: V, index: K, map: this) => void, thisArg?: any): void {
for (const property of Object.keys(this._keys)) {
callbackfn.call(thisArg, this._values[property], this._keys[property], this);
}
@@ -195,7 +191,7 @@ class SimpleMap<K, V> {
* @param {K} key
* @return {?string}
*/
private _keyToProperty(key: K): string {
private _keyToProperty(key: K): string | null {
if (typeof key === "number") {
return `#${ key }`;
}
@@ -237,12 +233,16 @@ if (typeof Map.prototype.forEach !== "function" || (() => {
Map = SimpleMap;
}
declare var global: {
Map?: typeof Map;
};
/**
* Sets the Map implementation used by libjass to the provided one. If null, {@link ./utility/map.SimpleMap} is used.
*
* @param {?function(new:Map, !Array.<!Array.<*>>=)} value
*/
export function setImplementation(value: typeof Map): void {
export function setImplementation(value: typeof Map | null): void {
if (value !== null) {
Map = value;
}
+23 -22
View File
@@ -18,15 +18,6 @@
* limitations under the License.
*/
declare const global: {
Promise?: typeof Promise;
MutationObserver?: typeof MutationObserver;
WebkitMutationObserver?: typeof MutationObserver;
process?: {
nextTick(callback: () => void): void;
}
};
export interface Thenable<T> {
/** @type {function(this:!Thenable.<T>, function(T|!Thenable.<T>), function(*))} */
then: ThenableThen<T>;
@@ -34,37 +25,38 @@ export interface Thenable<T> {
export interface ThenableThen<T> {
/** @type {function(this:!Thenable.<T>, function(T|!Thenable.<T>), function(*))} */
(resolve: (resolution: T | Thenable<T>) => void, reject: (reason: any) => void): void;
(this: Thenable<T>, resolve: ((resolution: T | Thenable<T>) => void) | undefined, reject: ((reason: any) => void) | undefined): void;
}
export interface Promise<T> extends Thenable<T> {
/**
* @param {?function(T):!Thenable.<U>} onFulfilled
* @param {function(T):!Thenable.<U>} onFulfilled
* @param {?function(*):(U|!Thenable.<U>)} onRejected
* @return {!Promise.<U>}
*/
then<U>(onFulfilled?: (value: T) => Thenable<U>, onRejected?: (reason: any) => U | Thenable<U>): Promise<U>;
then<U>(onFulfilled: (value: T) => Thenable<U> | undefined, onRejected?: (reason: any) => U | Thenable<U>): Promise<U>;
/**
* @param {?function(T):U} onFulfilled
* @param {function(T):U} onFulfilled
* @param {?function(*):(U|!Thenable.<U>)} onRejected
* @return {!Promise.<U>}
*/
then<U>(onFulfilled?: (value: T) => U, onRejected?: (reason: any) => U | Thenable<U>): Promise<U>;
then<U>(onFulfilled: (value: T) => U | undefined, onRejected?: (reason: any) => U | Thenable<U>): Promise<U>;
/**
* @param {function(*):(T|!Thenable.<T>)} onRejected
* @return {!Promise.<T>}
*/
catch(onRejected?: (reason: any) => T | Thenable<T>): Promise<T>;
catch(onRejected: (reason: any) => T | Thenable<T>): Promise<T>;
}
// Based on https://github.com/petkaantonov/bluebird/blob/1b1467b95442c12378d0ea280ede61d640ab5510/src/schedule.js
const enqueueJob: (callback: () => void) => void = (function () {
const MutationObserver = global.MutationObserver || global.WebkitMutationObserver;
if (global.process !== undefined && typeof global.process.nextTick === "function") {
const process = global.process;
return (callback: () => void) => {
global.process.nextTick(callback);
process.nextTick(callback);
};
}
else if (MutationObserver !== undefined) {
@@ -115,7 +107,7 @@ class SimplePromise<T> {
private _fulfillReactions: FulfilledPromiseReaction<T, any>[] = [];
private _rejectReactions: RejectedPromiseReaction<any>[] = [];
private _fulfilledValue: T = null;
private _fulfilledValue: T | null = null;
private _rejectedReason: any = null;
constructor(executor: (resolve: (resolution: T | Thenable<T>) => void, reject: (reason: any) => void) => void) {
@@ -137,7 +129,7 @@ class SimplePromise<T> {
* @param {?function(*):(U|!Thenable.<U>)} onRejected
* @return {!Promise.<U>}
*/
then<U>(onFulfilled: (value: T) => U | Thenable<U>, onRejected: (reason: any) => U | Thenable<U>): Promise<U> {
then<U>(onFulfilled: ((value: T) => U | Thenable<U>) | undefined, onRejected?: (reason: any) => U | Thenable<U>): Promise<U> {
const resultCapability = new DeferredPromise<U>();
if (typeof onFulfilled !== "function") {
@@ -165,7 +157,7 @@ class SimplePromise<T> {
break;
case SimplePromiseState.FULFILLED:
this._enqueueFulfilledReactionJob(fulfillReaction, this._fulfilledValue);
this._enqueueFulfilledReactionJob(fulfillReaction, this._fulfilledValue!);
break;
case SimplePromiseState.REJECTED:
@@ -180,8 +172,8 @@ class SimplePromise<T> {
* @param {function(*):(T|!Thenable.<T>)} onRejected
* @return {!Promise.<T>}
*/
catch(onRejected?: (reason: any) => T | Thenable<T>): Promise<T> {
return this.then(null, onRejected);
catch(onRejected: (reason: any) => T | Thenable<T>): Promise<T> {
return this.then(undefined, onRejected);
}
/**
@@ -403,6 +395,15 @@ export var Promise: {
race<T>(values: (T | Thenable<T>)[]): Promise<T>;
} = global.Promise || SimplePromise;
declare var global: {
Promise?: typeof Promise;
MutationObserver?: typeof MutationObserver;
WebkitMutationObserver?: typeof MutationObserver;
process?: {
nextTick(callback: () => void): void;
}
};
interface FulfilledPromiseReaction<T, U> {
/** @type {!libjass.DeferredPromise.<U>} */
capabilities: DeferredPromise<U>;
@@ -439,7 +440,7 @@ enum SimplePromiseState {
*
* @param {?function(new:Promise)} value
*/
export function setImplementation(value: typeof Promise): void {
export function setImplementation(value: typeof Promise | null): void {
if (value !== null) {
Promise = value;
}
+11 -11
View File
@@ -18,16 +18,12 @@
* limitations under the License.
*/
declare const global: {
Set?: typeof Set;
};
export interface Set<T> {
/**
* @param {T} value
* @return {libjass.Set.<T>} This set
*/
add(value: T): Set<T>;
add(value: T): this;
/**
*/
@@ -43,7 +39,7 @@ export interface Set<T> {
* @param {function(T, T, libjass.Set.<T>)} callbackfn A function that is called with each value in the set.
* @param {*} thisArg
*/
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
forEach(callbackfn: (value: T, index: T, set: this) => void, thisArg?: any): void;
/**
* @type {number}
@@ -58,7 +54,7 @@ export interface Set<T> {
*
* @param {!Array.<T>=} iterable Only an array of values is supported.
*/
class SimpleSet<T> {
class SimpleSet<T> implements Set<T> {
private _elements: { [key: string]: T };
private _size: number;
@@ -82,7 +78,7 @@ class SimpleSet<T> {
* @param {T} value
* @return {libjass.Set.<T>} This set
*/
add(value: T): Set<T> {
add(value: T): this {
const property = this._toProperty(value);
if (property === null) {
@@ -123,7 +119,7 @@ class SimpleSet<T> {
* @param {function(T, T, libjass.Set.<T>)} callbackfn A function that is called with each value in the set.
* @param {*} thisArg
*/
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void {
forEach(callbackfn: (value: T, index: T, set: this) => void, thisArg?: any): void {
for (const property of Object.keys(this._elements)) {
const element = this._elements[property];
callbackfn.call(thisArg, element, element, this);
@@ -143,7 +139,7 @@ class SimpleSet<T> {
* @param {T} value
* @return {?string}
*/
private _toProperty(value: T): string {
private _toProperty(value: T): string | null {
if (typeof value === "number") {
return `#${ value }`;
}
@@ -181,12 +177,16 @@ if (typeof Set.prototype.forEach !== "function" || (() => {
Set = SimpleSet;
}
declare var global: {
Set?: typeof Set;
};
/**
* Sets the Set implementation used by libjass to the provided one. If null, {@link ./utility/set.SimpleSet} is used.
*
* @param {?function(new:Set, !Array.<T>=)} value
*/
export function setImplementation(value: typeof Set): void {
export function setImplementation(value: typeof Set | null): void {
if (value !== null) {
Set = value;
}
+1 -1
View File
@@ -217,4 +217,4 @@ export class WorkerChannelImpl implements WorkerChannel {
}
}
registerWorkerCommand(WorkerCommands.Ping, parameters => Promise.resolve<void>(null));
registerWorkerCommand(WorkerCommands.Ping, parameters => Promise.resolve(null));
+1 -1
View File
@@ -30,7 +30,7 @@ export { WorkerCommands } from "./commands";
*/
export const supported = typeof Worker !== "undefined";
const _scriptNode = (typeof document !== "undefined" && document.currentScript !== undefined) ? document.currentScript : null;
const _scriptNode = (typeof document !== "undefined" && document.currentScript !== undefined) ? (document.currentScript as HTMLScriptElement) : null;
/**
* Create a new web worker and returns a {@link libjass.webworker.WorkerChannel} to it.
+1 -1
View File
@@ -41,6 +41,6 @@ export function registerWorkerCommand(command: WorkerCommands, handler: WorkerCo
* @param {number} command
* @return {?function(*, function(*, *))}
*/
export function getWorkerCommandHandler(command: WorkerCommands): WorkerCommandHandler {
export function getWorkerCommandHandler(command: WorkerCommands): WorkerCommandHandler | undefined {
return workerCommands.get(command);
}