diff --git a/bin/themes/default/partials/member.sources.hbs b/bin/themes/default/partials/member.sources.hbs index 5c20f4b65..335a319d5 100644 --- a/bin/themes/default/partials/member.sources.hbs +++ b/bin/themes/default/partials/member.sources.hbs @@ -8,7 +8,11 @@ {{#if sources}} {{/if}} diff --git a/bin/typedoc.d.ts b/bin/typedoc.d.ts index 4b8c00ee2..c821b5c84 100644 --- a/bin/typedoc.d.ts +++ b/bin/typedoc.d.ts @@ -10,6 +10,7 @@ declare var Util: any; declare var VM: any; declare var Path: any; declare var FS: any; +declare var ShellJS: any; declare var typeScriptPath: any; declare module TypeScript { class SourceFile { @@ -1073,6 +1074,41 @@ declare module TypeDoc.Factories { private onEndDeclaration(state); } } +declare module TypeDoc.Factories { + /** + * A handler that watches for repositories with GitHub origin and links + * their source files to the related GitHub pages. + */ + class GitHubHandler extends BaseHandler { + /** + * List of known repositories. + */ + private repositories; + /** + * List of paths known to be not under git control. + */ + private ignoredPaths; + /** + * Create a new GitHubHandler instance. + * + * @param dispatcher The dispatcher this handler should be attached to. + */ + constructor(dispatcher: Dispatcher); + /** + * Check whether the given file is placed inside a repository. + * + * @param fileName The name of the file a repository should be looked for. + * @returns The found repository info or NULL. + */ + private getRepository(fileName); + /** + * Triggered when the dispatcher leaves the resolving phase. + * + * @param event An event object containing the related project and compiler instance. + */ + private onEndResolve(event); + } +} declare module TypeDoc.Factories { /** * A handler that sorts and groups the found reflections in the resolving phase. @@ -1922,6 +1958,10 @@ declare module TypeDoc.Models { * The number of the line that emitted the declaration. */ line: number; + /** + * URL for displaying the source file. + */ + url?: string; } /** * A reflection that represents a single declaration emitted by the TypeScript compiler. @@ -2182,30 +2222,110 @@ declare module TypeDoc.Models { } } declare module TypeDoc.Models { + /** + * Exposes information about a directory containing source files. + * + * One my access the root directory of a project through the [[ProjectReflection.directory]] + * property. Traverse through directories by utilizing the [[SourceDirectory.parent]] or + * [[SourceDirectory.directories]] properties. + */ class SourceDirectory { - public name: string; - public dirName: string; - public url: string; + /** + * The parent directory or NULL if this is a root directory. + */ public parent: SourceDirectory; + /** + * A list of all subdirectories. + */ public directories: { [name: string]: SourceDirectory; }; + /** + * A list of all files in this directory. + */ public files: SourceFile[]; - public groups: ReflectionGroup[]; + /** + * The name of this directory. + */ + public name: string; + /** + * The relative path from the root directory to this directory. + */ + public dirName: string; + /** + * The url of the page displaying the directory contents. + */ + public url: string; + /** + * Create a new SourceDirectory instance. + * + * @param name The new of directory. + * @param parent The parent directory instance. + */ constructor(name?: string, parent?: SourceDirectory); + /** + * Return a string describing this directory and its contents. + * + * @param indent Used internally for indention. + * @returns A string representing this directory and all of its children. + */ public toString(indent?: string): string; + /** + * Return a list of all reflections exposed by the files within this directory. + * + * @returns An aggregated list of all [[DeclarationReflection]] defined in the + * files of this directory. + */ public getAllReflections(): DeclarationReflection[]; } } declare module TypeDoc.Models { + /** + * Exposes information about a source file. + * + * One my access a list of all source files through the [[ProjectReflection.files]] property or as + * a tree structure through the [[ProjectReflection.directory]] property. + * + * Furthermore each reflection carries references to the related SourceFile with their + * [[DeclarationReflection.sources]] property. It is an array of of [[IDeclarationSource]] instances + * containing the reference in their [[IDeclarationSource.file]] field. + */ class SourceFile { - public name: string; + /** + * The original full system file name. + */ + public fullFileName: string; + /** + * A trimmed version of the file name. Contains only the path relative to the + * determined base path. + */ public fileName: string; + /** + * The base name of the file. + */ + public name: string; + /** + * A url pointing to a page displaying the contents of this file. + */ public url: string; + /** + * The representation of the parent directory of this source file. + */ public parent: SourceDirectory; + /** + * A list of all reflections that are declared in this file. + */ public reflections: DeclarationReflection[]; + /** + * A grouped list of the reflections declared in this file. + */ public groups: ReflectionGroup[]; - constructor(fileName: string); + /** + * Create a new SourceFile instance. + * + * @param fullFileName The full file name. + */ + constructor(fullFileName: string); } } declare module TypeDoc.Models { diff --git a/bin/typedoc.js b/bin/typedoc.js index 8d85bb01e..6d3660718 100644 --- a/bin/typedoc.js +++ b/bin/typedoc.js @@ -8,6 +8,7 @@ var Util = require('util'); var VM = require('vm'); var Path = require('path'); var FS = require('fs-extra'); +var ShellJS = require('shelljs'); var typeScriptPath = Path.dirname(require.resolve('typescript')); if (!FS.existsSync(Path.resolve(typeScriptPath, 'typescript.js'))) { @@ -3156,6 +3157,213 @@ var TypeDoc; var Factories = TypeDoc.Factories; })(TypeDoc || (TypeDoc = {})); var TypeDoc; +(function (TypeDoc) { + (function (Factories) { + /** + * Stores data of a repository. + */ + var Repository = (function () { + /** + * Create a new Repository instance. + * + * @param path The root path of the repository. + */ + function Repository(path) { + var _this = this; + /** + * The name of the branch this repository is on right now. + */ + this.branch = 'master'; + /** + * A list of all files tracked by the repository. + */ + this.files = []; + this.path = path; + ShellJS.pushd(path); + + var out = ShellJS.exec('git ls-remote --get-url', { silent: true }); + if (out.code == 0) { + var url, remotes = out.output.split('\n'); + for (var i = 0, c = remotes.length; i < c; i++) { + url = /git@github\.com:([^\/]+)\/(.*?)\.git/.exec(remotes[i]); + if (url) { + this.gitHubUser = url[1]; + this.gitHubProject = url[2]; + break; + } + } + } + + out = ShellJS.exec('git ls-files', { silent: true }); + if (out.code == 0) { + out.output.split('\n').forEach(function (file) { + if (file != '') { + _this.files.push(Factories.BasePath.normalize(path + '/' + file)); + } + }); + } + + out = ShellJS.exec('git rev-parse --abbrev-ref HEAD', { silent: true }); + if (out.code == 0) { + this.branch = out.output.replace('\n', ''); + } + + ShellJS.popd(); + } + /** + * Check whether the given file is tracked by this repository. + * + * @param fileName The name of the file to test for. + * @returns TRUE when the file is part of the repository, otherwise FALSE. + */ + Repository.prototype.contains = function (fileName) { + return this.files.indexOf(fileName) != -1; + }; + + /** + * Get the URL of the given file on GitHub. + * + * @param fileName The file whose GitHub URL should be determined. + * @returns An url pointing to the web preview of the given file or NULL. + */ + Repository.prototype.getGitHubURL = function (fileName) { + if (!this.gitHubUser || !this.gitHubProject || !this.contains(fileName)) { + return null; + } + + return [ + 'https://github.com', + this.gitHubUser, + this.gitHubProject, + 'blob', + this.branch, + fileName.substr(this.path.length + 1) + ].join('/'); + }; + + /** + * Try to create a new repository instance. + * + * Checks whether the given path is the root of a valid repository and if so + * creates a new instance of [[Repository]]. + * + * @param path The potential repository root. + * @returns A new instance of [[Repository]] or NULL. + */ + Repository.tryCreateRepository = function (path) { + var out, repository = null; + + ShellJS.pushd(path); + out = ShellJS.exec('git rev-parse --show-toplevel', { silent: true }); + ShellJS.popd(); + + if (out.code != 0) + return null; + return new Repository(Factories.BasePath.normalize(out.output.replace("\n", ''))); + }; + return Repository; + })(); + + /** + * A handler that watches for repositories with GitHub origin and links + * their source files to the related GitHub pages. + */ + var GitHubHandler = (function (_super) { + __extends(GitHubHandler, _super); + /** + * Create a new GitHubHandler instance. + * + * @param dispatcher The dispatcher this handler should be attached to. + */ + function GitHubHandler(dispatcher) { + _super.call(this, dispatcher); + /** + * List of known repositories. + */ + this.repositories = {}; + /** + * List of paths known to be not under git control. + */ + this.ignoredPaths = []; + + ShellJS.config.silent = true; + if (ShellJS.which('git')) { + dispatcher.on(Factories.Dispatcher.EVENT_END_RESOLVE, this.onEndResolve, this); + } + } + /** + * Check whether the given file is placed inside a repository. + * + * @param fileName The name of the file a repository should be looked for. + * @returns The found repository info or NULL. + */ + GitHubHandler.prototype.getRepository = function (fileName) { + // Check for known non-repositories + var dirName = Path.dirname(fileName); + for (var i = 0, c = this.ignoredPaths.length; i < c; i++) { + if (this.ignoredPaths[i] == dirName) { + return null; + } + } + + for (var path in this.repositories) { + if (!this.repositories.hasOwnProperty(path)) + continue; + if (fileName.substr(0, path.length) == path) { + return this.repositories[path]; + } + } + + // Try to create a new repository + var repository = Repository.tryCreateRepository(dirName); + if (repository) { + this.repositories[repository.path] = repository; + return repository; + } + + // No repository found, add path to ignored paths + var segments = dirName.split('/'); + for (var i = segments.length; i > 0; i--) { + this.ignoredPaths.push(segments.slice(0, i).join('/')); + } + + return null; + }; + + /** + * Triggered when the dispatcher leaves the resolving phase. + * + * @param event An event object containing the related project and compiler instance. + */ + GitHubHandler.prototype.onEndResolve = function (event) { + var _this = this; + event.project.files.forEach(function (sourceFile) { + var repository = _this.getRepository(sourceFile.fullFileName); + if (repository) { + sourceFile.url = repository.getGitHubURL(sourceFile.fullFileName); + } + }); + + event.project.reflections.forEach(function (reflection) { + reflection.sources.forEach(function (source) { + if (source.file && source.file.url) { + source.url = source.file.url + '#L' + source.line; + } + }); + }); + }; + return GitHubHandler; + })(Factories.BaseHandler); + Factories.GitHubHandler = GitHubHandler; + + /** + * Register this handler. + */ + Factories.Dispatcher.HANDLERS.push(GitHubHandler); + })(TypeDoc.Factories || (TypeDoc.Factories = {})); + var Factories = TypeDoc.Factories; +})(TypeDoc || (TypeDoc = {})); +var TypeDoc; (function (TypeDoc) { (function (Factories) { /** @@ -4511,8 +4719,9 @@ var TypeDoc; this.basePath.add(fileName); state.reflection.sources.push({ + file: this.fileMappings[fileName], fileName: fileName, - line: snapshot.getLineNumber(ast.start()) + line: snapshot.getLineNumber(ast.start()) + 1 }); }; @@ -5326,19 +5535,53 @@ var TypeDoc; var TypeDoc; (function (TypeDoc) { (function (Models) { + /** + * Exposes information about a directory containing source files. + * + * One my access the root directory of a project through the [[ProjectReflection.directory]] + * property. Traverse through directories by utilizing the [[SourceDirectory.parent]] or + * [[SourceDirectory.directories]] properties. + */ var SourceDirectory = (function () { + /** + * Create a new SourceDirectory instance. + * + * @param name The new of directory. + * @param parent The parent directory instance. + */ function SourceDirectory(name, parent) { - this.name = null; - this.dirName = null; + /** + * The parent directory or NULL if this is a root directory. + */ this.parent = null; + /** + * A list of all subdirectories. + */ this.directories = {}; + /** + * A list of all files in this directory. + */ this.files = []; + /** + * The name of this directory. + */ + this.name = null; + /** + * The relative path from the root directory to this directory. + */ + this.dirName = null; if (name && parent) { this.name = name; this.dirName = (parent.dirName ? parent.dirName + '/' : '') + name; this.parent = parent; } } + /** + * Return a string describing this directory and its contents. + * + * @param indent Used internally for indention. + * @returns A string representing this directory and all of its children. + */ SourceDirectory.prototype.toString = function (indent) { if (typeof indent === "undefined") { indent = ''; } var res = indent + this.name; @@ -5356,6 +5599,12 @@ var TypeDoc; return res; }; + /** + * Return a list of all reflections exposed by the files within this directory. + * + * @returns An aggregated list of all [[DeclarationReflection]] defined in the + * files of this directory. + */ SourceDirectory.prototype.getAllReflections = function () { var reflections = []; this.files.forEach(function (file) { @@ -5374,11 +5623,30 @@ var TypeDoc; var TypeDoc; (function (TypeDoc) { (function (Models) { + /** + * Exposes information about a source file. + * + * One my access a list of all source files through the [[ProjectReflection.files]] property or as + * a tree structure through the [[ProjectReflection.directory]] property. + * + * Furthermore each reflection carries references to the related SourceFile with their + * [[DeclarationReflection.sources]] property. It is an array of of [[IDeclarationSource]] instances + * containing the reference in their [[IDeclarationSource.file]] field. + */ var SourceFile = (function () { - function SourceFile(fileName) { + /** + * Create a new SourceFile instance. + * + * @param fullFileName The full file name. + */ + function SourceFile(fullFileName) { + /** + * A list of all reflections that are declared in this file. + */ this.reflections = []; - this.fileName = fileName; - this.name = Path.basename(fileName); + this.fileName = fullFileName; + this.fullFileName = fullFileName; + this.name = Path.basename(fullFileName); } return SourceFile; })(); diff --git a/package.json b/package.json index 5fd557510..9cbdc6325 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "minimatch": "^0.3.0", "handlebars": "^2.0.0-alpha.4", "marked": "^0.3.2", - "highlight.js": "^8.1.0" + "highlight.js": "^8.1.0", + "shelljs": "^0.3.0" }, "devDependencies": { "grunt": "^0.4.5", diff --git a/src/@init.ts b/src/@init.ts index 76b09e372..732813789 100644 --- a/src/@init.ts +++ b/src/@init.ts @@ -12,6 +12,7 @@ var Util = require('util'); var VM = require('vm'); var Path = require('path'); var FS = require('fs-extra'); +var ShellJS = require('shelljs'); var typeScriptPath = Path.dirname(require.resolve('typescript')); if (!FS.existsSync(Path.resolve(typeScriptPath, 'typescript.js'))) { diff --git a/src/typedoc/factories/handlers/GitHubHandler.ts b/src/typedoc/factories/handlers/GitHubHandler.ts new file mode 100644 index 000000000..439525caa --- /dev/null +++ b/src/typedoc/factories/handlers/GitHubHandler.ts @@ -0,0 +1,229 @@ +module TypeDoc.Factories +{ + /** + * Stores data of a repository. + */ + class Repository + { + /** + * The root path of this repository. + */ + path:string; + + /** + * The name of the branch this repository is on right now. + */ + branch:string = 'master'; + + /** + * A list of all files tracked by the repository. + */ + files:string[] = []; + + /** + * The user/organisation name of this repository on GitHub. + */ + gitHubUser:string; + + /** + * The project name of this repository on GitHub. + */ + gitHubProject:string; + + + /** + * Create a new Repository instance. + * + * @param path The root path of the repository. + */ + constructor(path:string) { + this.path = path; + ShellJS.pushd(path); + + var out = ShellJS.exec('git ls-remote --get-url', {silent:true}); + if (out.code == 0) { + var url, remotes = out.output.split('\n'); + for (var i = 0, c = remotes.length; i < c; i++) { + url = /git@github\.com:([^\/]+)\/(.*?)\.git/.exec(remotes[i]); + if (url) { + this.gitHubUser = url[1]; + this.gitHubProject = url[2]; + break; + } + } + } + + out = ShellJS.exec('git ls-files', {silent:true}); + if (out.code == 0) { + out.output.split('\n').forEach((file) => { + if (file != '') { + this.files.push(BasePath.normalize(path + '/' + file)); + } + }); + } + + out = ShellJS.exec('git rev-parse --abbrev-ref HEAD', {silent:true}); + if (out.code == 0) { + this.branch = out.output.replace('\n', ''); + } + + ShellJS.popd(); + } + + + /** + * Check whether the given file is tracked by this repository. + * + * @param fileName The name of the file to test for. + * @returns TRUE when the file is part of the repository, otherwise FALSE. + */ + contains(fileName:string):boolean { + return this.files.indexOf(fileName) != -1; + } + + + /** + * Get the URL of the given file on GitHub. + * + * @param fileName The file whose GitHub URL should be determined. + * @returns An url pointing to the web preview of the given file or NULL. + */ + getGitHubURL(fileName:string):string { + if (!this.gitHubUser || !this.gitHubProject || !this.contains(fileName)) { + return null; + } + + return [ + 'https://github.com', + this.gitHubUser, + this.gitHubProject, + 'blob', + this.branch, + fileName.substr(this.path.length + 1) + ].join('/'); + } + + + /** + * Try to create a new repository instance. + * + * Checks whether the given path is the root of a valid repository and if so + * creates a new instance of [[Repository]]. + * + * @param path The potential repository root. + * @returns A new instance of [[Repository]] or NULL. + */ + static tryCreateRepository(path:string):Repository { + var out, repository = null; + + ShellJS.pushd(path); + out = ShellJS.exec('git rev-parse --show-toplevel', {silent:true}); + ShellJS.popd(); + + if (out.code != 0) return null; + return new Repository(BasePath.normalize(out.output.replace("\n", ''))); + } + } + + + /** + * A handler that watches for repositories with GitHub origin and links + * their source files to the related GitHub pages. + */ + export class GitHubHandler extends BaseHandler + { + /** + * List of known repositories. + */ + private repositories:{[path:string]:Repository} = {}; + + /** + * List of paths known to be not under git control. + */ + private ignoredPaths:string[] = []; + + + /** + * Create a new GitHubHandler instance. + * + * @param dispatcher The dispatcher this handler should be attached to. + */ + constructor(dispatcher:Dispatcher) { + super(dispatcher); + + ShellJS.config.silent = true; + if (ShellJS.which('git')) { + dispatcher.on(Dispatcher.EVENT_END_RESOLVE, this.onEndResolve, this); + } + } + + + /** + * Check whether the given file is placed inside a repository. + * + * @param fileName The name of the file a repository should be looked for. + * @returns The found repository info or NULL. + */ + private getRepository(fileName:string):Repository { + // Check for known non-repositories + var dirName = Path.dirname(fileName); + for (var i = 0, c = this.ignoredPaths.length; i < c; i++) { + if (this.ignoredPaths[i] == dirName) { + return null; + } + } + + // Check for known repositories + for (var path in this.repositories) { + if (!this.repositories.hasOwnProperty(path)) continue; + if (fileName.substr(0, path.length) == path) { + return this.repositories[path]; + } + } + + // Try to create a new repository + var repository = Repository.tryCreateRepository(dirName); + if (repository) { + this.repositories[repository.path] = repository; + return repository; + } + + // No repository found, add path to ignored paths + var segments = dirName.split('/'); + for (var i:number = segments.length; i > 0; i--) { + this.ignoredPaths.push(segments.slice(0, i).join('/')); + } + + return null; + } + + + /** + * Triggered when the dispatcher leaves the resolving phase. + * + * @param event An event object containing the related project and compiler instance. + */ + private onEndResolve(event:DispatcherEvent) { + event.project.files.forEach((sourceFile) => { + var repository = this.getRepository(sourceFile.fullFileName); + if (repository) { + sourceFile.url = repository.getGitHubURL(sourceFile.fullFileName); + } + }); + + event.project.reflections.forEach((reflection) => { + reflection.sources.forEach((source) => { + if (source.file && source.file.url) { + source.url = source.file.url + '#L' + source.line; + } + }); + }); + } + } + + + /** + * Register this handler. + */ + Dispatcher.HANDLERS.push(GitHubHandler); +} \ No newline at end of file diff --git a/src/typedoc/factories/handlers/SourceHandler.ts b/src/typedoc/factories/handlers/SourceHandler.ts index c958a73cf..d80fad60c 100644 --- a/src/typedoc/factories/handlers/SourceHandler.ts +++ b/src/typedoc/factories/handlers/SourceHandler.ts @@ -87,8 +87,9 @@ module TypeDoc.Factories this.basePath.add(fileName); state.reflection.sources.push({ + file: this.fileMappings[fileName], fileName: fileName, - line: snapshot.getLineNumber(ast.start()) + line: snapshot.getLineNumber(ast.start()) + 1 }); } diff --git a/src/typedoc/models/reflections/DeclarationReflection.ts b/src/typedoc/models/reflections/DeclarationReflection.ts index 5aa8aa451..72e764366 100644 --- a/src/typedoc/models/reflections/DeclarationReflection.ts +++ b/src/typedoc/models/reflections/DeclarationReflection.ts @@ -60,6 +60,11 @@ module TypeDoc.Models * The number of the line that emitted the declaration. */ line:number; + + /** + * URL for displaying the source file. + */ + url?:string; } diff --git a/src/typedoc/models/reflections/SourceDirectory.ts b/src/typedoc/models/reflections/SourceDirectory.ts index df07795bd..9594d980d 100644 --- a/src/typedoc/models/reflections/SourceDirectory.ts +++ b/src/typedoc/models/reflections/SourceDirectory.ts @@ -1,22 +1,51 @@ module TypeDoc.Models { + /** + * Exposes information about a directory containing source files. + * + * One my access the root directory of a project through the [[ProjectReflection.directory]] + * property. Traverse through directories by utilizing the [[SourceDirectory.parent]] or + * [[SourceDirectory.directories]] properties. + */ export class SourceDirectory { - name:string = null; - - dirName:string = null; - - url:string; - + /** + * The parent directory or NULL if this is a root directory. + */ parent:SourceDirectory = null; + /** + * A list of all subdirectories. + */ directories:{[name:string]:SourceDirectory} = {}; + /** + * A list of all files in this directory. + */ files:SourceFile[] = []; - groups:ReflectionGroup[]; + /** + * The name of this directory. + */ + name:string = null; + + /** + * The relative path from the root directory to this directory. + */ + dirName:string = null; + + /** + * The url of the page displaying the directory contents. + */ + url:string; + /** + * Create a new SourceDirectory instance. + * + * @param name The new of directory. + * @param parent The parent directory instance. + */ constructor(name?:string, parent?:SourceDirectory) { if (name && parent) { this.name = name; @@ -26,6 +55,12 @@ module TypeDoc.Models } + /** + * Return a string describing this directory and its contents. + * + * @param indent Used internally for indention. + * @returns A string representing this directory and all of its children. + */ toString(indent:string = '') { var res = indent + this.name; @@ -42,6 +77,12 @@ module TypeDoc.Models } + /** + * Return a list of all reflections exposed by the files within this directory. + * + * @returns An aggregated list of all [[DeclarationReflection]] defined in the + * files of this directory. + */ getAllReflections():DeclarationReflection[] { var reflections = []; this.files.forEach((file) => { diff --git a/src/typedoc/models/reflections/SourceFile.ts b/src/typedoc/models/reflections/SourceFile.ts index cbdc6640e..bb3086ca8 100644 --- a/src/typedoc/models/reflections/SourceFile.ts +++ b/src/typedoc/models/reflections/SourceFile.ts @@ -1,23 +1,63 @@ module TypeDoc.Models { + /** + * Exposes information about a source file. + * + * One my access a list of all source files through the [[ProjectReflection.files]] property or as + * a tree structure through the [[ProjectReflection.directory]] property. + * + * Furthermore each reflection carries references to the related SourceFile with their + * [[DeclarationReflection.sources]] property. It is an array of of [[IDeclarationSource]] instances + * containing the reference in their [[IDeclarationSource.file]] field. + */ export class SourceFile { - name:string; + /** + * The original full system file name. + */ + fullFileName:string; + /** + * A trimmed version of the file name. Contains only the path relative to the + * determined base path. + */ fileName:string; + /** + * The base name of the file. + */ + name:string; + + /** + * A url pointing to a page displaying the contents of this file. + */ url:string; + /** + * The representation of the parent directory of this source file. + */ parent:SourceDirectory; + /** + * A list of all reflections that are declared in this file. + */ reflections:DeclarationReflection[] = []; + /** + * A grouped list of the reflections declared in this file. + */ groups:ReflectionGroup[]; - constructor(fileName:string) { - this.fileName = fileName; - this.name = Path.basename(fileName); + /** + * Create a new SourceFile instance. + * + * @param fullFileName The full file name. + */ + constructor(fullFileName:string) { + this.fileName = fullFileName; + this.fullFileName = fullFileName; + this.name = Path.basename(fullFileName); } } } \ No newline at end of file