karma-typescript-agile-preprocessor
Version:
Leverage the power of gulp-typescript for a simple yet powerful Karma preprocessor.
217 lines (216 loc) • 7.67 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const utils = require("./utils");
var FileChangeState;
(function (FileChangeState) {
FileChangeState[FileChangeState["New"] = 0] = "New";
FileChangeState[FileChangeState["Equal"] = 1] = "Equal";
FileChangeState[FileChangeState["Modified"] = 2] = "Modified";
FileChangeState[FileChangeState["Deleted"] = 3] = "Deleted";
FileChangeState[FileChangeState["NotFound"] = 4] = "NotFound";
})(FileChangeState = exports.FileChangeState || (exports.FileChangeState = {}));
var FileKind;
(function (FileKind) {
FileKind[FileKind["Source"] = 0] = "Source";
FileKind[FileKind["Config"] = 1] = "Config";
})(FileKind = exports.FileKind || (exports.FileKind = {}));
var File;
(function (File) {
function fromContent(fileName, content) {
let kind = FileKind.Source;
if (path.extname(fileName).toLowerCase() === 'json')
kind = FileKind.Config;
return {
fileNameNormalized: utils.normalizePath(fileName),
fileNameOriginal: fileName,
content,
kind
};
}
File.fromContent = fromContent;
function fromGulp(file) {
let str = file.contents.toString('utf8');
let data = fromContent(file.path, str);
data.gulp = file;
return data;
}
File.fromGulp = fromGulp;
function equal(a, b) {
if (a === undefined || b === undefined)
return a === b; // They could be both undefined.
return (a.fileNameOriginal === b.fileNameOriginal)
&& (a.content === b.content);
}
File.equal = equal;
function getChangeState(previous, current) {
if (previous === undefined) {
return current === undefined ? FileChangeState.NotFound : FileChangeState.New;
}
if (current === undefined) {
return FileChangeState.Deleted;
}
if (equal(previous, current)) {
return FileChangeState.Equal;
}
return FileChangeState.Modified;
}
File.getChangeState = getChangeState;
})(File = exports.File || (exports.File = {}));
class FileDictionary {
constructor(typescript) {
this.files = {};
this.firstSourceFile = undefined;
this.typescript = typescript;
}
addGulp(gFile) {
return this.addFile(File.fromGulp(gFile));
}
addContent(fileName, content) {
return this.addFile(File.fromContent(fileName, content));
}
addFile(file) {
if (file.kind === FileKind.Source) {
this.initTypeScriptSourceFile(file);
if (!this.firstSourceFile)
this.firstSourceFile = file;
}
this.files[file.fileNameNormalized] = file;
return file;
}
getFile(name) {
return this.files[utils.normalizePath(name)];
}
getFileNames(onlyGulp = false) {
const fileNames = [];
for (const fileName in this.files) {
if (!this.files.hasOwnProperty(fileName))
continue;
let file = this.files[fileName];
if (onlyGulp && !file.gulp)
continue;
fileNames.push(file.fileNameOriginal);
}
return fileNames;
}
getSourceFileNames(onlyGulp) {
const fileNames = this.getFileNames(onlyGulp);
const sourceFileNames = fileNames
.filter(fileName => fileName.substr(fileName.length - 5).toLowerCase() !== '.d.ts');
if (sourceFileNames.length === 0) {
// Only definition files, so we will calculate the common base path based on the
// paths of the definition files.
return fileNames;
}
return sourceFileNames;
}
get commonBasePath() {
const fileNames = this.getSourceFileNames(true);
return utils.getCommonBasePathOfArray(fileNames.map(fileName => {
const file = this.files[utils.normalizePath(fileName)];
return path.resolve(process.cwd(), file.gulp.base);
}));
}
// This empty setter will prevent that TS emits 'readonly' modifier.
// 'readonly' is not supported in current stable release.
set commonBasePath(value) { }
get commonSourceDirectory() {
const fileNames = this.getSourceFileNames();
return utils.getCommonBasePathOfArray(fileNames.map(fileName => {
const file = this.files[utils.normalizePath(fileName)];
return path.dirname(file.fileNameNormalized);
}));
}
// This empty setter will prevent that TS emits 'readonly' modifier.
// 'readonly' is not supported in current stable release.
set commonSourceDirectory(value) { }
}
exports.FileDictionary = FileDictionary;
class FileCache {
constructor(typescript, options) {
this.previous = undefined;
this.noParse = false; // true when using a file based compiler.
this.version = 0;
this.typescript = typescript;
this.options = options;
this.createDictionary();
}
addGulp(gFile) {
return this.current.addGulp(gFile);
}
addContent(fileName, content) {
return this.current.addContent(fileName, content);
}
reset() {
this.version++;
this.previous = this.current;
this.createDictionary();
}
createDictionary() {
this.current = new FileDictionary(this.typescript);
this.current.initTypeScriptSourceFile = (file) => this.initTypeScriptSourceFile(file);
}
initTypeScriptSourceFile(file) {
if (this.noParse)
return;
if (this.previous) {
let previous = this.previous.getFile(file.fileNameOriginal);
if (File.equal(previous, file)) {
file.ts = previous.ts; // Re-use previous source file.
return;
}
}
file.ts = this.typescript.createSourceFile(file.fileNameOriginal, file.content, this.options.target);
}
getFile(name) {
return this.current.getFile(name);
}
getFileChange(name) {
let previous;
if (this.previous) {
previous = this.previous.getFile(name);
}
let current = this.current.getFile(name);
return {
previous,
current,
state: File.getChangeState(previous, current)
};
}
getFileNames(onlyGulp = false) {
return this.current.getFileNames(onlyGulp);
}
get firstSourceFile() {
return this.current.firstSourceFile;
}
// This empty setter will prevent that TS emits 'readonly' modifier.
// 'readonly' is not supported in current stable release.
set firstSourceFile(value) { }
get commonBasePath() {
return this.current.commonBasePath;
}
set commonBasePath(value) { }
get commonSourceDirectory() {
return this.current.commonSourceDirectory;
}
set commonSourceDirectory(value) { }
isChanged(onlyGulp = false) {
if (!this.previous)
return true;
const files = this.getFileNames(onlyGulp);
const oldFiles = this.previous.getFileNames(onlyGulp);
if (files.length !== oldFiles.length)
return true;
for (const fileName of files) {
if (oldFiles.indexOf(fileName) === -1)
return true;
}
for (const fileName of files) {
const change = this.getFileChange(fileName);
if (change.state !== FileChangeState.Equal)
return true;
}
return false;
}
}
exports.FileCache = FileCache;