├── .gitignore ├── .gitmodules ├── Jenkinsfile ├── README.md ├── app ├── assets │ └── stylesheets │ │ └── index.less ├── controllers │ ├── BaseController.scala │ ├── GitController.scala │ ├── GitInitController.scala │ ├── GithubController.scala │ ├── HomeController.scala │ ├── ParseController.scala │ ├── ProjectController.scala │ ├── SandboxController.scala │ ├── SbtController.scala │ ├── SbtHistoryController.scala │ ├── SbtPublishController.scala │ └── StaticSiteController.scala ├── models │ ├── parse │ │ ├── Importer.scala │ │ ├── ProjectDefinition.scala │ │ ├── Utils.scala │ │ ├── parser │ │ │ ├── TSDefLexical.scala │ │ │ ├── TSDefParser.scala │ │ │ ├── TSTokens.scala │ │ │ └── tree │ │ │ │ └── Tree.scala │ │ └── sc │ │ │ ├── printer │ │ │ ├── Printer.scala │ │ │ ├── PrinterFiles.scala │ │ │ ├── PrinterFilesMulti.scala │ │ │ ├── PrinterFilesSingle.scala │ │ │ └── PrinterHelper.scala │ │ │ ├── transform │ │ │ ├── ExcludedMembers.scala │ │ │ ├── IgnoredPackages.scala │ │ │ ├── ReplacementManager.scala │ │ │ ├── Replacements.scala │ │ │ └── Transformations.scala │ │ │ └── tree │ │ │ ├── ClassSymbol.scala │ │ │ ├── CommentSymbol.scala │ │ │ ├── ContainerSymbol.scala │ │ │ ├── FieldSymbol.scala │ │ │ ├── JSNameable.scala │ │ │ ├── MethodSymbol.scala │ │ │ ├── ModuleSymbol.scala │ │ │ ├── Name.scala │ │ │ ├── PackageSymbol.scala │ │ │ ├── ParamSymbol.scala │ │ │ ├── QualifiedName.scala │ │ │ ├── Symbol.scala │ │ │ ├── TypeAliasSymbol.scala │ │ │ ├── TypeParamSymbol.scala │ │ │ └── TypeRef.scala │ └── sandbox │ │ └── SandboxTask.scala ├── services │ ├── file │ │ └── FileService.scala │ ├── git │ │ └── GitService.scala │ ├── github │ │ └── GithubService.scala │ ├── parse │ │ ├── ClassReferenceService.scala │ │ ├── PrinterService.scala │ │ ├── TypeScriptFiles.scala │ │ └── TypeScriptImport.scala │ ├── project │ │ ├── ProjectDetailsService.scala │ │ ├── ProjectOutput.scala │ │ └── ProjectService.scala │ └── sbt │ │ ├── SbtHistoryService.scala │ │ ├── SbtResultParser.scala │ │ └── SbtService.scala ├── utils │ ├── Application.scala │ ├── Config.scala │ ├── DateUtils.scala │ ├── JsonSerializers.scala │ ├── Logging.scala │ ├── NumberUtils.scala │ └── web │ │ ├── ErrorHandler.scala │ │ ├── FormUtils.scala │ │ ├── LoggingFilter.scala │ │ ├── RequestHandler.scala │ │ └── WebFilters.scala └── views │ ├── component │ └── filterForm.scala.html │ ├── detail.scala.html │ ├── error │ ├── badRequest.scala.html │ ├── notFound.scala.html │ └── serverError.scala.html │ ├── git │ ├── detail.scala.html │ ├── form.scala.html │ ├── result.scala.html │ ├── results.scala.html │ └── test.scala.html │ ├── github │ ├── detail.scala.html │ ├── list.scala.html │ └── test.scala.html │ ├── history │ ├── compare.scala.html │ ├── detail.scala.html │ └── list.scala.html │ ├── home.scala.html │ ├── layout │ ├── basic.scala.html │ ├── materialize.scala.html │ └── simple.scala.html │ ├── list.scala.html │ ├── metrics.scala.html │ ├── parse │ ├── process.scala.html │ └── processAll.scala.html │ ├── problems.scala.html │ ├── project │ ├── update.scala.html │ └── updateAll.scala.html │ ├── sandbox │ ├── list.scala.html │ ├── metrics.scala.html │ └── run.scala.html │ └── sbt │ ├── form.scala.html │ ├── list.scala.html │ ├── published.scala.html │ ├── result.scala.html │ └── results.scala.html ├── build.sbt ├── conf ├── application.conf ├── logback.xml ├── replacement │ ├── accounting.txt │ ├── ace.txt │ ├── alertify.txt │ ├── algoliasearch.txt │ ├── apexjs.txt │ ├── arbiter.txt │ ├── async.txt │ ├── atmosphere.txt │ ├── awssdk.txt │ ├── bcrypt.txt │ ├── bigint.txt │ ├── biginteger.txt │ ├── bootstrap.txt │ ├── calq.txt │ ├── combokeys.txt │ ├── css.txt │ ├── datgui.txt │ ├── debug.txt │ ├── each.txt │ ├── expectations.txt │ ├── faker.txt │ ├── flipsnap.txt │ ├── gamepad.txt │ ├── github.txt │ ├── hashids.txt │ ├── jquery.txt │ ├── jqueryui.txt │ ├── less.txt │ ├── materializecss.txt │ ├── matterjs.txt │ ├── mixpanel.txt │ ├── msgpack.txt │ ├── nedb.txt │ ├── node.txt │ ├── pad.txt │ ├── phaser.txt │ ├── phaserpixi.txt │ ├── pixijs.txt │ ├── qwest.txt │ ├── react.txt │ ├── redis.txt │ ├── resumablejs.txt │ ├── title.txt │ ├── traverson.txt │ ├── trim.txt │ ├── ts │ │ ├── react.ts.txt │ │ └── sharepoint.ts.txt │ └── xterm.txt └── routes ├── project ├── Dependencies.scala ├── Packaging.scala ├── Server.scala ├── Shared.scala ├── build.properties └── plugins.sbt ├── public ├── browserconfig.xml ├── images │ └── ui │ │ └── favicon │ │ └── favicon.png └── manifest.json ├── scalastyle-config.xml └── util └── ts-dump ├── cycles.ts ├── index.ts ├── package-lock.json ├── package.json ├── props.ts ├── tests └── jQuery.d.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | project/project/target 3 | project/target 4 | target 5 | tmp 6 | .history 7 | dist 8 | /.idea 9 | /*.iml 10 | /out 11 | /backup 12 | /data 13 | /util/ts-dump/node_modules 14 | /.idea_modules 15 | /.classpath 16 | /.project 17 | /RUNNING_PID 18 | /.settings 19 | 20 | buildinfo.properties 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "util/scala-js-template"] 2 | path = util/scala-js-template 3 | url = git@github.com:DefinitelyScala/scala-js-template.git 4 | [submodule "typescript/DefinitelyTyped"] 5 | path = typescript/DefinitelyTyped 6 | url = https://github.com/DefinitelyTyped/DefinitelyTyped.git 7 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | stages { 5 | stage('Build') { 6 | steps { 7 | sh "sbt -no-colors -batch dist" 8 | archiveArtifacts artifacts: '**/target/universal/*.zip', fingerprint: true 9 | } 10 | } 11 | 12 | stage('Publish') { 13 | steps { 14 | echo 'TODO: publish' 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scala-js-typescript 2 | 3 | # ARCHIVED: These projects are superceded by the great work at https://github.com/ScalablyTyped/Distribution 4 | 5 | A TypeScript-to-Scala.js converter. 6 | Designed for parsing http://definitelytyped.org, powers http://definitelyscala.com. 7 | 8 | ## Running 9 | 10 | Right now the whole thing is a giant Scala Play Framework app that expects certain directories. 11 | You can run the freshly-cloned repository with `SBT`, but there won't be any projects. 12 | 13 | To run for your own TypeScript definitions ("foo") rename your `index.d.ts` to "foo.ts", and place it in `./data/typescript`. 14 | Then start the app with `sbt run`, and open [http://localhost:9000](). Select `Project List`, then your project. 15 | You'll see options to parse, build, and publish your project. Publishing won't work. 16 | 17 | In order to create the SBT project, you'll need to clone `git@github.com:DefinitelyScala/scala-js-template.git` into `./util`. 18 | 19 | More documentation coming soon. Feel free to email me if you run into trouble. 20 | 21 | ## License 22 | 23 | The code is licensed under [Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0). 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/index.less: -------------------------------------------------------------------------------- 1 | // General Styles 2 | body { 3 | display: flex; 4 | min-height: 100vh; 5 | flex-direction: column; 6 | background-color: #fcfcfc; 7 | } 8 | 9 | main { 10 | flex: 1 0 auto; 11 | .static-container { 12 | margin-top: 16px; 13 | } 14 | } 15 | 16 | // Helper Classes 17 | .initially-hidden { 18 | display: none; 19 | } 20 | 21 | .black { 22 | background-color: #555 !important; 23 | } 24 | 25 | .pre-wrap { 26 | white-space: pre-wrap; 27 | font-family: 'roboto-mono'; 28 | } 29 | 30 | .clear { 31 | clear: both; 32 | } 33 | 34 | // Materialize Tweaks 35 | .flash-error, .flash-success { 36 | text-align: center; 37 | padding: 10px; 38 | margin-bottom: 10px; 39 | } 40 | 41 | .flash-error { 42 | background-color: #ffffff; 43 | color: #8b0000; 44 | } 45 | 46 | footer.page-footer { 47 | margin: 0; 48 | padding: 0; 49 | .footer-copyright { 50 | height: 48px; 51 | line-height: 48px; 52 | padding: 0 10px; 53 | } 54 | } 55 | 56 | .right-link { 57 | float: right !important; 58 | margin-right: 0 !important; 59 | } 60 | 61 | .flash { 62 | padding: 20px; 63 | margin-bottom: 10px; 64 | } 65 | 66 | .btn, .btn-flat { 67 | text-transform: none !important; 68 | } 69 | 70 | // Navbar 71 | nav { 72 | a { 73 | -webkit-font-smoothing: antialiased; 74 | } 75 | } 76 | 77 | .nb-container { 78 | height: 48px; 79 | } 80 | 81 | #topnav { 82 | height: 48px; 83 | line-height: 48px; 84 | 85 | #user-dropdown-toggle { 86 | height: 48px; 87 | line-height: 48px; 88 | } 89 | 90 | .button-collapse i { 91 | height: 48px; 92 | line-height: 48px; 93 | } 94 | 95 | .brand-logo { 96 | margin: 0 14px; 97 | font-size: 1.6rem; 98 | 99 | &.center { 100 | margin: 0; 101 | } 102 | 103 | i { 104 | height: 48px; 105 | line-height: 48px; 106 | margin-right: 6px; 107 | } 108 | } 109 | 110 | @media only screen and (max-width: 992px) { 111 | .brand-logo { 112 | margin: 0; 113 | } 114 | } 115 | 116 | @media only screen and (max-width: 600px) { 117 | .fa-search { 118 | margin-top: 20px; 119 | } 120 | } 121 | 122 | .menu-toggle { 123 | font-size: 190%; 124 | margin-left: 12px; 125 | float: left; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/controllers/BaseController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import play.api.mvc._ 4 | import utils.{ Application, Logging } 5 | 6 | import scala.concurrent.Future 7 | 8 | abstract class BaseController() extends InjectedController with Logging { 9 | def app: Application 10 | 11 | def act(action: String)(block: Request[AnyContent] => Future[Result]) = Action.async { implicit request => 12 | block(request) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/controllers/GitController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import play.twirl.api.Html 4 | import services.git.GitService 5 | import services.github.GithubService 6 | import services.project.ProjectService 7 | import utils.Application 8 | import scala.concurrent.ExecutionContext.Implicits.global 9 | 10 | import scala.concurrent.Future 11 | import scala.util.control.NonFatal 12 | 13 | @javax.inject.Singleton 14 | class GitController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 15 | def detail(key: String) = act(s"git.$key") { implicit request => 16 | val projectDir = ProjectService.projectDir(key) 17 | val dir = projectDir / ".git" 18 | if (dir.exists) { 19 | Future.successful(Ok(views.html.git.detail(key))) 20 | } else { 21 | Future.successful(Ok(Html(s"Git repo for [$key] not found."))) 22 | } 23 | } 24 | 25 | def status(key: String) = act(s"git.status.$key") { implicit request => 26 | val result = GitService.status(ProjectService.projectDir(key)) 27 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 28 | } 29 | 30 | def statusAll() = act("git.status.all") { implicit request => 31 | val results = githubService.listRepos(includeTemplates = false).map { repos => 32 | repos.map { repo => 33 | val key = repo.name.stripPrefix("scala").stripPrefix("-").stripPrefix("js") 34 | val result = try { 35 | GitService.status(ProjectService.projectDir(key)) 36 | } catch { 37 | case NonFatal(x) => (-1, x.toString) 38 | } 39 | val out = result._2.split('\n').filterNot(_.contains("../../../")).mkString("\n") 40 | (repo.name, result._1, out) 41 | } 42 | } 43 | results.map(r => Ok(views.html.git.results(r))) 44 | } 45 | 46 | def reset(key: String) = act(s"git.reset.$key") { implicit request => 47 | val result = GitService.reset(ProjectService.projectDir(key)) 48 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 49 | } 50 | 51 | def resetAll() = act("git.reset.all") { implicit request => 52 | val results = githubService.listRepos(includeTemplates = false).map { repos => 53 | repos.map { repo => 54 | val key = repo.name.stripPrefix("scala").stripPrefix("-").stripPrefix("js") 55 | val result = try { 56 | GitService.reset(ProjectService.projectDir(key)) 57 | } catch { 58 | case NonFatal(x) => (-1, x.toString) 59 | } 60 | val out = result._2.split('\n').filterNot(_.contains("../../../")).mkString("\n") 61 | (repo.name, result._1, out) 62 | } 63 | } 64 | results.map(r => Ok(views.html.git.results(r))) 65 | } 66 | 67 | def commitForm() = act(s"project.commit.form") { implicit request => 68 | Future.successful(Ok(views.html.git.form())) 69 | } 70 | 71 | def commit(key: String) = act(s"git.commit.$key") { implicit request => 72 | val msg = request.body.asFormUrlEncoded.get("msg").mkString 73 | val result = GitService.commit(ProjectService.projectDir(key), Nil, msg) 74 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 75 | } 76 | 77 | def commitAll() = act("git.commit.all") { implicit request => 78 | val body = request.body.asFormUrlEncoded.get 79 | val msg = body("msg").mkString 80 | val files = body.getOrElse("files", Nil) 81 | val results = githubService.listRepos(includeTemplates = false).map { repos => 82 | repos.map { repo => 83 | val key = repo.name.stripPrefix("scala-js-") 84 | val result = GitService.commit(ProjectService.projectDir(key), files, msg) 85 | (repo.name, result._1, result._2) 86 | } 87 | } 88 | results.map(r => Ok(views.html.git.results(r))) 89 | } 90 | 91 | def push(key: String) = act(s"git.update.$key") { implicit request => 92 | val result = GitService.push(ProjectService.projectDir(key)) 93 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 94 | } 95 | 96 | def pushAll() = act("git.push.all") { implicit request => 97 | val results = githubService.listRepos(includeTemplates = false).map { repos => 98 | repos.map { repo => 99 | val key = repo.name.stripPrefix("scala").stripPrefix("-").stripPrefix("js") 100 | val result = GitService.push(ProjectService.projectDir(key)) 101 | (repo.name, result._1, result._2) 102 | } 103 | } 104 | results.map(r => Ok(views.html.git.results(r))) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/controllers/GitInitController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import models.parse.ProjectDefinition 4 | import scala.concurrent.ExecutionContext.Implicits.global 5 | import services.git.GitService 6 | import services.github.GithubService 7 | import services.project.{ ProjectDetailsService, ProjectService } 8 | import utils.Application 9 | 10 | import scala.concurrent.Future 11 | 12 | @javax.inject.Singleton 13 | class GitInitController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 14 | def createAll(q: Option[String]) = act("git.create.all") { implicit request => 15 | val projects = ProjectDetailsService.getAll(q, Some("norepo")) 16 | val results = projects.map { project => 17 | val projectDir = ProjectService.projectDir(project.key) 18 | val dir = projectDir / ".git" 19 | if (dir.exists) { 20 | project.key + ": Skipping invalid project with repo." 21 | } else { 22 | val result = GitService.init(projectDir) 23 | project.key + ": " + result._2 24 | } 25 | } 26 | Future.successful(Ok("Ok:\n\n" + results.mkString("\n"))) 27 | } 28 | 29 | def create(key: String) = act(s"git.create.$key") { implicit request => 30 | val projectDir = ProjectService.projectDir(key) 31 | val dir = projectDir / ".git" 32 | if (dir.exists) { 33 | throw new IllegalStateException(s"Git repo already exists for [$key].") 34 | } else { 35 | val result = GitService.init(projectDir) 36 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 37 | } 38 | } 39 | 40 | def addRemote(key: String) = act(s"git.add.remote.$key") { implicit request => 41 | val projectDir = ProjectService.projectDir(key) 42 | val result = GitService.addRemote(projectDir) 43 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 44 | } 45 | 46 | def firstCommit(key: String) = act(s"git.first.commit.$key") { implicit request => 47 | val projectDir = ProjectService.projectDir(key) 48 | val result = GitService.firstCommit(projectDir) 49 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 50 | } 51 | 52 | def secondCommit(key: String) = act(s"git.second.commit.$key") { implicit request => 53 | val projectDir = ProjectService.projectDir(key) 54 | val result = GitService.secondCommit(projectDir) 55 | Future.successful(Ok(views.html.git.result(key, result._1, result._2))) 56 | } 57 | 58 | def thirdCommit(key: String) = act(s"git.third.commit.$key") { implicit request => 59 | val projectDir = ProjectService.projectDir(key) 60 | val result = GitService.thirdCommit(projectDir) 61 | Future.successful(Ok(views.html.git.result(key, result._1, result._2, Some("Publish" -> controllers.routes.SbtPublishController.publish(key))))) 62 | } 63 | 64 | def fullInit(key: String) = act(s"git.full.init.$key") { implicit request => 65 | val projectDir = ProjectService.projectDir(key) 66 | val dir = projectDir / ".git" 67 | if (dir.exists) { 68 | throw new IllegalStateException(s"Git repo already exists for [$key].") 69 | } else { 70 | GitService.init(projectDir) 71 | } 72 | 73 | val proj = ProjectDefinition.fromJson(ProjectService.outDirFor(key)) 74 | 75 | githubService.create("scala-js-" + proj.keyNormalized, proj.description).map { result => 76 | GitService.addRemote(projectDir) 77 | GitService.firstCommit(projectDir) 78 | val result4 = GitService.secondCommit(projectDir) 79 | 80 | Ok(views.html.git.result(key, result4._1, result4._2, Some("Third" -> controllers.routes.GitInitController.thirdCommit(key)))) 81 | } 82 | } 83 | 84 | def initCommitsAll(q: Option[String]) = act("git.create.all") { implicit request => 85 | val projects = ProjectDetailsService.getAll(q, Some("built")) 86 | val results = projects.map { project => 87 | val projectDir = ProjectService.projectDir(project.key) 88 | val commitCount = GitService.commitCount(projectDir) 89 | if (commitCount == 0) { 90 | val proj = ProjectDefinition.fromJson(ProjectService.outDirFor(project.key)) 91 | githubService.create("scala-js-" + proj.keyNormalized, proj.description).map { result => 92 | GitService.addRemote(projectDir) 93 | GitService.firstCommit(projectDir) 94 | GitService.secondCommit(projectDir) 95 | } 96 | project.key + ": GO!" 97 | } else { 98 | project.key + ": Skip." 99 | } 100 | } 101 | Future.successful(Ok(s"Ok (${results.size}):\n\n" + results.mkString("\n"))) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/controllers/GithubController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import models.parse.ProjectDefinition 4 | import scala.concurrent.ExecutionContext.Implicits.global 5 | import play.twirl.api.Html 6 | import services.git.GitService 7 | import services.github.GithubService 8 | import services.project.{ ProjectDetailsService, ProjectService } 9 | import utils.Application 10 | 11 | import scala.concurrent.Future 12 | 13 | @javax.inject.Singleton 14 | class GithubController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 15 | def list = act(s"github.list") { implicit request => 16 | githubService.listRepos().map { repos => 17 | Ok(views.html.github.list(repos)) 18 | } 19 | } 20 | 21 | def mergeAll = act(s"github.merge") { implicit request => 22 | githubService.listRepos().map { repos => 23 | val result = repos.map { repo => 24 | val dir = ProjectService.projectDir(repo.name.stripPrefix("scala-js-")) 25 | if (!dir.exists) { 26 | dir.createDirectory() 27 | } 28 | val gitDir = dir / ".git" 29 | val ret = gitDir.exists 30 | if (ret) { 31 | log.info(s"Skipping existing github repository for [${repo.name}].") 32 | } else { 33 | log.info(s"Merging github repository for [${repo.name}].") 34 | val parent = dir.parent 35 | dir.delete(swallowIOExceptions = true) 36 | GitService.cloneRepo(parent, repo.name) 37 | } 38 | ret 39 | } 40 | Ok(Html(s"Ok: ${result.filterNot(x => x).size} github repos merged, ${result.count(x => x)} already present.")) 41 | } 42 | } 43 | 44 | def detail(key: String) = act(s"github.$key") { implicit request => 45 | githubService.detail(key).map { 46 | case Some(repo) => Ok(views.html.github.detail(repo)) 47 | case None => Ok(Html(s"Github repo for [$key] not found.")) 48 | } 49 | } 50 | 51 | def create(key: String) = act(s"github.create.$key") { implicit request => 52 | val proj = ProjectDefinition.fromJson(ProjectService.outDirFor(key)) 53 | githubService.create("scala-js-" + proj.keyNormalized, proj.description).map { result => 54 | Redirect(controllers.routes.GithubController.detail(proj.keyNormalized)) 55 | } 56 | } 57 | 58 | def createAll(q: Option[String]) = act(s"github.create.all") { implicit request => 59 | githubService.listRepos().flatMap { repos => 60 | val projects = ProjectDetailsService.getAll(q, Some("built"), repos) 61 | val results = projects.flatMap { project => 62 | val projectDir = ProjectService.projectDir(project.key) 63 | //val commitCount = GitService.commitCount(projectDir) 64 | if (project.repo && !project.github) { 65 | val proj = ProjectDefinition.fromJson(ProjectService.outDirFor(project.key)) 66 | Some(proj) 67 | } else { 68 | None 69 | } 70 | } 71 | val f = results.foldLeft(Future.successful(Seq.empty[ProjectDefinition])) { (ret, p) => 72 | ret.flatMap { r => 73 | githubService.create("scala-js-" + p.keyNormalized, p.description).map { result => 74 | val projectDir = ProjectService.projectDir(p.key) 75 | GitService.addRemote(projectDir) 76 | GitService.push(projectDir) 77 | log.info(p.key + "!!!!!!!!!") 78 | r :+ p 79 | } 80 | } 81 | } 82 | f.map(results => Ok(s"Ok (${results.size}):\n\n" + results.mkString("\n"))) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/controllers/HomeController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import models.parse.ProjectDefinition 4 | import scala.concurrent.ExecutionContext.Implicits.global 5 | import play.api.mvc.Action 6 | import services.github.GithubService 7 | import services.parse.TypeScriptFiles 8 | import services.project.{ ProjectDetailsService, ProjectService } 9 | import utils.Application 10 | 11 | import scala.concurrent.Future 12 | 13 | @javax.inject.Singleton 14 | class HomeController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 15 | def home(q: Option[String], filter: Option[String]) = act("home") { implicit request => 16 | val srcDirs = TypeScriptFiles.list(q) 17 | val keys = srcDirs.sorted.map(x => x -> ProjectDefinition.normalize(x)) 18 | 19 | Future.successful(Ok(views.html.home(q, filter, keys, app.config.debug))) 20 | } 21 | 22 | def list(q: Option[String], filter: Option[String]) = act("home") { implicit request => 23 | githubService.listRepos(includeTemplates = false).map { repos => 24 | val details = ProjectDetailsService.getAll(q, filter, repos) 25 | Ok(views.html.list(q, filter, details, app.config.debug)) 26 | } 27 | } 28 | 29 | def problems() = act("problems") { implicit request => 30 | githubService.listRepos(includeTemplates = false).map { repos => 31 | val details = ProjectDetailsService.getAll(None, None, repos) 32 | Ok(views.html.problems(details, app.config.debug)) 33 | } 34 | } 35 | 36 | def detail(key: String) = act(s"home.$key") { implicit request => 37 | githubService.detail(key).map { github => 38 | val outDir = ProjectService.outDirFor(key) 39 | val projectDir = ProjectService.projectDir(key) 40 | val hasRepo = (projectDir / ".git").exists 41 | val details = if (outDir.exists) { 42 | ProjectDefinition.fromJson(outDir) 43 | } else { 44 | ProjectDefinition(key, "?", "?", "?", "?") 45 | } 46 | 47 | Ok(views.html.detail(key, details, outDir, projectDir, hasRepo, github, app.config.debug)) 48 | } 49 | } 50 | 51 | def untrail(path: String) = Action.async { 52 | Future.successful(MovedPermanently(s"/$path")) 53 | } 54 | 55 | def externalLink(url: String) = act("external.link") { implicit request => 56 | Future.successful(Redirect(if (url.startsWith("http")) { url } else { "http://" + url })) 57 | } 58 | 59 | def ping(timestamp: Long) = act("ping") { implicit request => 60 | Future.successful(Ok(timestamp.toString)) 61 | } 62 | 63 | def robots() = act("robots") { implicit request => 64 | Future.successful(Ok("User-agent: *\nDisallow: /")) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/controllers/ParseController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import models.parse.parser.tree.DeclTree 4 | import play.twirl.api.Html 5 | import services.parse.{ PrinterService, TypeScriptFiles, TypeScriptImport } 6 | import utils.Application 7 | 8 | import scala.concurrent.Future 9 | 10 | object ParseController { 11 | case class Result(key: String, content: String, tree: Option[List[DeclTree]], text: Seq[String]) 12 | } 13 | 14 | @javax.inject.Singleton 15 | class ParseController @javax.inject.Inject() (override val app: Application) extends BaseController { 16 | def copy() = act(s"parse.copy") { implicit request => 17 | val result = TypeScriptFiles.copy() 18 | Future.successful(Ok(Html(s"[${utils.NumberUtils.withCommas(result._1 - result._2)}] of [${utils.NumberUtils.withCommas(result._1)}] files copied."))) 19 | } 20 | 21 | def parseAll(q: Option[String]) = act("parse.all") { implicit request => 22 | val scripts = TypeScriptFiles.list(q) 23 | val results = scripts.par.map { script => 24 | log.info(s"Parsing [$script]...") 25 | parseLibrary(script) 26 | }.seq 27 | Future.successful(Ok(views.html.parse.processAll(results, app.config.debug))) 28 | } 29 | 30 | def parse(key: String) = act(s"parse.$key") { implicit request => 31 | val result = parseLibrary(key) 32 | Future.successful(Ok(views.html.parse.process(key, result.content, result.tree, None, result.text, app.config.debug))) 33 | } 34 | 35 | def refresh(key: String) = act(s"refresh.$key") { implicit request => 36 | val result = parseLibrary(key) 37 | if (result.tree.isDefined) { 38 | Future.successful(Redirect(controllers.routes.ProjectController.update(key))) 39 | } else { 40 | throw new IllegalStateException("Cannot parse.") 41 | } 42 | } 43 | 44 | def parseLibrary(key: String) = { 45 | val content = TypeScriptFiles.getContent(key) 46 | val tree = TypeScriptImport.parse(content) 47 | val res = tree match { 48 | case Right(t) => Some(t) -> PrinterService(key, t).export() 49 | case Left(err) => None -> Seq("Error: " + err) 50 | } 51 | ParseController.Result(key, content, res._1, res._2) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/controllers/ProjectController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import services.file.FileService 4 | import services.project.ProjectService 5 | import utils.Application 6 | 7 | import scala.concurrent.Future 8 | 9 | @javax.inject.Singleton 10 | class ProjectController @javax.inject.Inject() (override val app: Application, parseController: ParseController) extends BaseController { 11 | def update(key: String) = act(s"update.$key") { implicit request => 12 | val created = ProjectService(key).update() 13 | Future.successful(Ok(views.html.project.update(key, created, app.config.debug))) 14 | } 15 | 16 | def updateAll(q: Option[String]) = act("project.all") { implicit request => 17 | val outDirs = FileService.getDir("out").list.filter(_.isDirectory).filter(_.name.contains(q.getOrElse(""))).toSeq 18 | val results = outDirs.par.map(outDir => outDir.name -> ProjectService(outDir.name).update()).seq 19 | Future.successful(Ok(views.html.project.updateAll(results, app.config.debug))) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/controllers/SandboxController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import akka.util.Timeout 4 | import models.sandbox.SandboxTask 5 | import scala.concurrent.ExecutionContext.Implicits.global 6 | import utils.Application 7 | 8 | import scala.concurrent.Future 9 | import scala.concurrent.duration._ 10 | 11 | @javax.inject.Singleton 12 | class SandboxController @javax.inject.Inject() (override val app: Application) extends BaseController { 13 | implicit val timeout = Timeout(10.seconds) 14 | 15 | def list = act("sandbox.list") { implicit request => 16 | Future.successful(Ok(views.html.sandbox.list())) 17 | } 18 | 19 | def sandbox(key: String) = act("sandbox." + key) { implicit request => 20 | val sandbox = SandboxTask.withName(key) 21 | sandbox.run(app).map { result => 22 | Ok(views.html.sandbox.run(sandbox, result)) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/controllers/SbtController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import better.files.File 4 | import services.github.GithubService 5 | import services.project.ProjectService 6 | import services.sbt.{ SbtHistoryService, SbtResultParser, SbtService } 7 | import utils.Application 8 | 9 | import scala.concurrent.Future 10 | 11 | @javax.inject.Singleton 12 | class SbtController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 13 | def list(q: Option[String]) = act(s"sbt.list") { implicit request => 14 | val statuses = SbtHistoryService.statuses() 15 | Future.successful(Ok(views.html.sbt.list(q, statuses))) 16 | } 17 | 18 | def last(key: String) = act(s"sbt.last") { implicit request => 19 | val status = SbtHistoryService.status(key) 20 | val result = SbtResultParser.parse(status) 21 | Future.successful(Ok(views.html.sbt.result(key, result, status.contentAsString))) 22 | } 23 | 24 | def clean(key: String) = act(s"sbt.build.$key") { implicit request => 25 | val projectDir = ProjectService.projectDir(key) 26 | val buildResult = SbtService.clean(projectDir) 27 | val result = SbtResultParser.Result(key, Nil, Nil, Nil) 28 | Future.successful(Ok(views.html.sbt.result(key, result, buildResult._2))) 29 | } 30 | 31 | def build(key: String) = act(s"sbt.build.$key") { implicit request => 32 | val projectDir = ProjectService.projectDir(key) 33 | if (projectDir.exists) { 34 | val buildResult = SbtService.build(projectDir) 35 | val status = SbtHistoryService.status(key) 36 | val result = SbtResultParser.parse(status) 37 | Future.successful(Ok(views.html.sbt.result(key, result, buildResult._2))) 38 | } else { 39 | throw new IllegalStateException(s"No project found for [$key].") 40 | } 41 | } 42 | 43 | def buildForm(q: Option[String]) = act(s"sbt.build.all") { implicit request => 44 | Future.successful(Ok(views.html.sbt.form(q))) 45 | } 46 | 47 | private[this] def test(f: File, start: Option[String]) = { 48 | val name = f.name.stripPrefix("scala-js-") 49 | if (start.exists(_ > name)) { 50 | (f.name, 0, "Skipped") 51 | } else { 52 | if (name == "clone" || name == "notify") { 53 | (f.name, 0, "Ignored") 54 | } else { 55 | val x = SbtService.build(f) 56 | (f.name, x._1, x._2) 57 | } 58 | } 59 | } 60 | 61 | def formatAll(q: Option[String]) = act(s"sbt.build.all") { implicit request => 62 | val projects = ProjectService.list(q) 63 | val result = projects.map { x => 64 | val ret = SbtService.format(x) 65 | (x.name, ret._1, ret._2) 66 | }.seq 67 | Future.successful { 68 | log.info(s"Formatted [${result.size}] projects.") 69 | Ok(views.html.sbt.results(result)) 70 | } 71 | } 72 | 73 | def buildAll(q: Option[String], start: Option[String]) = act(s"sbt.build.all") { implicit request => 74 | val projects = ProjectService.list(q).sortBy(_.path) 75 | val result = projects.map(x => test(x, start)).seq 76 | Future.successful { 77 | log.info(s"Processed [${result.size}] projects, with [${result.count(_._2 == 0)}] passing and [${result.count(_._2 != 0)}] failing.") 78 | Ok(views.html.sbt.results(result)) 79 | } 80 | } 81 | 82 | def cleanAll(q: Option[String]) = act(s"sbt.clean.all") { implicit request => 83 | val projects = ProjectService.list(q) 84 | val result = projects.map { x => 85 | val ret = SbtService.clean(x) 86 | (x.name, ret._1, ret._2) 87 | } 88 | Future.successful { 89 | log.info(s"Processed [${result.size}] projects, with [${result.count(_._2 == 0)}] passing and [${result.count(_._2 != 0)}] failing.") 90 | Ok(views.html.sbt.results(result)) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/controllers/SbtHistoryController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import services.github.GithubService 4 | import services.sbt.SbtHistoryService 5 | import utils.Application 6 | 7 | import scala.concurrent.Future 8 | 9 | @javax.inject.Singleton 10 | class SbtHistoryController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 11 | def list() = act(s"sbt.history") { implicit request => 12 | val result = SbtHistoryService.list() 13 | Future.successful(Ok(views.html.history.list(result))) 14 | } 15 | 16 | def compare() = act(s"sbt.history.compare") { implicit request => 17 | val files = request.queryString.getOrElse("q", Nil).toList 18 | files match { 19 | case lName :: rName :: Nil => 20 | val lSeq = SbtHistoryService.read(lName) 21 | val rSeq = SbtHistoryService.read(rName) 22 | val keys = (lSeq.map(_._1) ++ rSeq.map(_._1)).distinct.sorted 23 | Future.successful(Ok(views.html.history.compare(keys, lName, lSeq.toMap, rName, rSeq.toMap))) 24 | case _ => throw new IllegalStateException(s"Invalid [q] param: [${files.mkString(", ")}].") 25 | } 26 | 27 | } 28 | 29 | def write() = act(s"sbt.history.write") { implicit request => 30 | SbtHistoryService.write() 31 | Future.successful(Redirect(routes.SbtHistoryController.list())) 32 | } 33 | 34 | def detail(key: String) = act(s"sbt.history.detail") { implicit request => 35 | val result = SbtHistoryService.read(key) 36 | Future.successful(Ok(views.html.history.detail(key, result))) 37 | } 38 | 39 | def delete(key: String) = act(s"sbt.history.delete") { implicit request => 40 | SbtHistoryService.delete(key) 41 | Future.successful(Redirect(routes.SbtHistoryController.list())) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/controllers/SbtPublishController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import play.api.libs.ws.WSClient 4 | import services.github.GithubService 5 | import services.project.{ ProjectDetailsService, ProjectService } 6 | import services.sbt.{ SbtResultParser, SbtService } 7 | import utils.Application 8 | import scala.concurrent.ExecutionContext.Implicits.global 9 | 10 | import scala.concurrent.Future 11 | 12 | @javax.inject.Singleton 13 | class SbtPublishController @javax.inject.Inject() (override val app: Application, githubService: GithubService, wsClient: WSClient) extends BaseController { 14 | private[this] val key = "href=\":scala-js-" 15 | 16 | private[this] def getPublishedJars = { 17 | val mFuture = wsClient.url("https://dl.bintray.com/definitelyscala/maven/com/definitelyscala/").get 18 | wsClient.url("https://jcenter.bintray.com/com/definitelyscala/").get.flatMap { jRsp => 19 | val j = jRsp.body.split('\n').flatMap { line => 20 | line.indexOf(key) match { 21 | case -1 => None 22 | case x => Some(line.substring(x + key.length, line.indexOf("_sjs"))) 23 | } 24 | } 25 | mFuture.map { mRsp => 26 | val m = mRsp.body.split('\n').flatMap { line => 27 | line.indexOf(key) match { 28 | case -1 => None 29 | case x => Some(line.substring(x + key.length, line.indexOf("_sjs"))) 30 | } 31 | } 32 | m -> j 33 | } 34 | } 35 | } 36 | 37 | def list() = act(s"publish.list") { implicit request => 38 | getPublishedJars.flatMap { publishedKeys => 39 | githubService.listRepos().map { repos => 40 | val repoKeys = repos.map(_.key) 41 | 42 | val keys = (publishedKeys._1 ++ publishedKeys._2 ++ repoKeys).distinct.sorted 43 | 44 | Ok(views.html.sbt.published(keys, repoKeys.toSet, publishedKeys._1.toSet, publishedKeys._2.toSet)) 45 | } 46 | } 47 | } 48 | 49 | def publish(key: String) = act(s"sbt.publish.$key") { implicit request => 50 | val projectDir = ProjectService.projectDir(key) 51 | if (projectDir.exists) { 52 | val publishResult = SbtService.publish(projectDir) 53 | 54 | val result = SbtResultParser.Result(key, Nil, Nil, Nil) 55 | 56 | Future.successful(Ok(views.html.sbt.result(key, result, publishResult._2))) 57 | } else { 58 | throw new IllegalStateException(s"No project found for [$key].") 59 | } 60 | } 61 | 62 | def publishAll(q: Option[String]) = act(s"sbt.publish.all") { implicit request => 63 | getPublishedJars.flatMap { publishedKeys => 64 | githubService.listRepos().map { repos => 65 | val deetSet = ProjectDetailsService.getAll(q = None, filter = Some("built"), repos = repos).filter(_.github).map(_.key).toSet 66 | val results = repos.map { repo => 67 | val f = ProjectService.projectDir(repo.key) 68 | if (deetSet(repo.key)) { 69 | val x = SbtService.publish(f) 70 | (f.name, x._1, x._2) 71 | } else { 72 | (f.name, 0, "Skipped") 73 | } 74 | } 75 | Ok(views.html.sbt.results(results)) 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/controllers/StaticSiteController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import better.files._ 4 | import models.parse.ProjectDefinition 5 | import scala.concurrent.ExecutionContext.Implicits.global 6 | import play.twirl.api.Html 7 | import services.file.FileService 8 | import services.github.GithubService 9 | import utils.Application 10 | 11 | @javax.inject.Singleton 12 | class StaticSiteController @javax.inject.Inject() (override val app: Application, githubService: GithubService) extends BaseController { 13 | private[this] def htmlFor(projName: String, definition: ProjectDefinition) = { 14 | s"""
15 |
16 |
${definition.version}
17 | ${definition.name} 18 |
19 | https://github.com/DefinitelyScala/$projName 20 |
""" 21 | } 22 | 23 | def generate() = act("static.site") { implicit request => 24 | val root = "../definitelyscala.com".toFile 25 | 26 | if (!root.exists) { 27 | throw new IllegalStateException(s"Missing static site root [${root.path}].") 28 | } 29 | 30 | githubService.listRepos(includeTemplates = false).map { repos => 31 | val src = root / "index.template.html" 32 | val dest = root / "index.html" 33 | 34 | val outDirs = FileService.getDir("out").list.filter(_.isDirectory).toSeq.map(_.name).sorted 35 | 36 | val items = outDirs.flatMap { o => 37 | repos.find(_.name.stripPrefix("scala-js-") == ProjectDefinition.normalize(o)).map(o -> _) 38 | } 39 | 40 | val definitions = items.map { i => 41 | val projName = "scala-js-" + ProjectDefinition.normalize(i._1) 42 | val outDir = FileService.getDir("out") / i._1 43 | (projName, i._2.stars, ProjectDefinition.fromJson(outDir)) 44 | } 45 | 46 | val favorites = definitions.filter(_._2 > 0).sortBy(x => (-x._2) -> x._3.keyNormalized).map(d => htmlFor(d._1, d._3)).mkString("\n ") 47 | 48 | val allString = definitions.map(d => htmlFor(d._1, d._3)).mkString("\n ") 49 | 50 | val originalContent = src.contentAsString 51 | val favoritesContent = originalContent.replace("[favorites]", favorites) 52 | val allContent = favoritesContent.replace("[items]", allString) 53 | 54 | dest.delete(swallowIOExceptions = true) 55 | dest.write(allContent) 56 | 57 | Ok(Html(s"Site exported (${items.size} repositories).")) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/models/parse/ProjectDefinition.scala: -------------------------------------------------------------------------------- 1 | package models.parse 2 | 3 | import utils.JsonSerializers._ 4 | 5 | object ProjectDefinition { 6 | implicit val jsonEncoder: Encoder[ProjectDefinition] = deriveEncoder 7 | implicit val jsonDecoder: Decoder[ProjectDefinition] = deriveDecoder 8 | 9 | def normalize(key: String) = key.replaceAllLiterally("-", "").replaceAllLiterally(".", "").replaceAllLiterally("_", "") 10 | 11 | def fromJson(dir: better.files.File) = { 12 | val file = dir / "project.json" 13 | val original = file.contentAsString 14 | val depsReplaced = if (original.contains("dependencies")) { 15 | original 16 | } else { 17 | original.replaceAllLiterally("}", ", \"dependencies\": []\n}") 18 | } 19 | val buildVerReplaced = if (depsReplaced.contains("buildVersion")) { 20 | depsReplaced 21 | } else { 22 | depsReplaced.replaceAllLiterally("}", ", \"buildVersion\": \"1.1.0\"\n}") 23 | } 24 | decodeJson[ProjectDefinition](buildVerReplaced).right.get 25 | } 26 | } 27 | 28 | case class ProjectDefinition( 29 | key: String, 30 | name: String, 31 | url: String, 32 | version: String, 33 | authors: String, 34 | buildVersion: String = "1.1.0", 35 | dependencies: Seq[String] = Nil) { 36 | val keyNormalized = ProjectDefinition.normalize(key) 37 | 38 | val description = s"Scala.js facades for $name $version." 39 | 40 | private[this] val dependencyString = if (dependencies.isEmpty) { 41 | "" 42 | } else { 43 | ", " + dependencies.map(d => s""""com.definitelyscala" %%% "scala-js-$d" % "$buildVersion"""").mkString(", ") 44 | } 45 | 46 | private[this] val dependencySummary = if (dependencies.isEmpty) { 47 | "" 48 | } else { 49 | s"\nThis project depends on ${dependencies.map(d => s"`scala-js-$d`").mkString(", ")}.\n" 50 | } 51 | 52 | val asMap = Map( 53 | "key" -> key, 54 | "keyNormalized" -> keyNormalized, 55 | "name" -> name, 56 | "url" -> url, 57 | "version" -> version, 58 | "authors" -> authors, 59 | "dependencies" -> dependencyString, 60 | "buildVersion" -> buildVersion, 61 | "dependencySummary" -> dependencySummary) 62 | } 63 | -------------------------------------------------------------------------------- /app/models/parse/Utils.scala: -------------------------------------------------------------------------------- 1 | package models.parse 2 | 3 | object Utils { 4 | def scalaEscape(ident: String): String = if (needsEscaping(ident)) { 5 | "`" + ident + "`" 6 | } else { 7 | ident 8 | } 9 | 10 | def needsEscaping(ident: String): Boolean = ident.isEmpty || 11 | (!ident.head.isUnicodeIdentifierStart && ident.head != '_') || 12 | !ident.tail.forall(_.isUnicodeIdentifierPart) || 13 | isScalaKeyword(ident) 14 | 15 | val isScalaKeyword: Set[String] = Set( 16 | "abstract", "case", "class", "catch", "def", "do", "else", "extends", 17 | "false", "final", "finally", "for", "forSome", "if", "implicit", 18 | "import", "lazy", "match", "new", "null", "object", "override", 19 | "package", "private", "protected", "return", "sealed", "super", "then", "this", 20 | "throw", "trait", "true", "try", "type", "val", "var", "with", "while", 21 | "yield", ".", "_", ":", "=", "=>", "<-", "<:", "<%", ">:", "#", "@") 22 | } 23 | -------------------------------------------------------------------------------- /app/models/parse/parser/TSDefLexical.scala: -------------------------------------------------------------------------------- 1 | package models.parse.parser 2 | 3 | import scala.util.parsing.input.CharArrayReader.EofCh 4 | import scala.util.parsing.combinator._ 5 | import scala.util.parsing.combinator.lexical._ 6 | import scala.collection.mutable 7 | import scala.util.parsing.input.CharSequenceReader 8 | 9 | class TSDefLexical extends Lexical with TSTokens with ImplicitConversions { 10 | override def whitespace: Parser[Any] = rep(elem("whitespace", _ => false)) 11 | 12 | override def token: Parser[Token] = { 13 | multiLineCommentParser | 14 | importCommentParser | 15 | singleLineCommentParser | 16 | whitespaceParser | 17 | identifier | 18 | numericLiteral | 19 | stringLiteral | 20 | EofCh ^^^ EOF | 21 | delim | 22 | failure("illegal character") 23 | } 24 | 25 | def tokens = rep(token) 26 | def tokenizeString(s: String) = phrase(tokens)(new CharSequenceReader(s, 0)) 27 | 28 | val whitespaceParser = rep1(whitespaceChar) ^^ { c => Whitespace("?") } 29 | 30 | val importCommentParser = 'i' ~> 'm' ~> 'p' ~> 'o' ~> 'r' ~> 't' ~> ' ' ~> rep(chrExcept(EofCh, '\n')) ^^ { text => ImportComment(text.mkString) } 31 | val singleLineCommentParser = '/' ~> '/' ~> rep(chrExcept(EofCh, '\n')) ^^ { text => LineComment(text.mkString) } 32 | val multiLineCommentParser = ('/' ~> '*' ~> rep1(not('*' ~ '/') ~> chrExcept(EofCh)) <~ '*' <~ '/') ^^ { text => MultilineComment(text.mkString) } 33 | 34 | def identifier = stringOf1(identifierStart, identifierPart) ^^ { 35 | x => if (reserved contains x) Keyword(x) else Identifier(x) 36 | } 37 | 38 | def identifierStart = elem("", isIdentifierStart) | (pseudoChar filter isIdentifierStart) 39 | def identifierPart = elem("", isIdentifierPart) | (pseudoChar filter isIdentifierPart) 40 | 41 | private[this] val hexNum = (elem('x') | 'X') ~> rep1(hexDigit) ^^ { 42 | digits => digits.foldLeft(0L)(_ * 16 + _).toString 43 | } 44 | private[this] val octalNum = rep1(octalDigit) ^^ { 45 | digits => digits.foldLeft(0L)(_ * 8 + _).toString 46 | } 47 | private[this] val digitNum = stringOf1(digit) ~ opt(stringOf1('.', digit)) ^^ { 48 | case part1 ~ part2 => part1 + part2.getOrElse("") 49 | } 50 | 51 | def numericLiteral = ('0' ~> (hexNum | octalNum | success("0")) | digitNum) ^^ NumericLit 52 | 53 | def stringLiteral = (quoted('\"') | quoted('\'')) ^^ StringLit 54 | 55 | def quoted(quoteChar: Char) = quoteChar ~> stringOf(inQuoteChar(quoteChar)) <~ quoteChar 56 | 57 | def inQuoteChar(quoteChar: Char) = chrExcept('\\', quoteChar, EofCh) | pseudoChar 58 | 59 | def pseudoChar = '\\' ~> ( 60 | 'x' ~> hexDigit ~ hexDigit ^^ { 61 | case d1 ~ d0 => (16 * d1 + d0).toChar 62 | } 63 | | 'u' ~> hexDigit ~ hexDigit ~ hexDigit ~ hexDigit ^^ { 64 | case d3 ~ d2 ~ d1 ~ d0 => (4096 * d3 + 256 * d2 + 16 * d1 + d0).toChar 65 | } 66 | | elem("", _ => true) ^^ { 67 | case '0' => '\u0000' 68 | case 'b' => '\u0008' 69 | case 't' => '\u0009' 70 | case 'n' => '\u000A' 71 | case 'v' => '\u000B' 72 | case 'f' => '\u000C' 73 | case 'r' => '\u000D' 74 | case c => c // including ' " \ 75 | }) 76 | 77 | def octalDigit = elem("octal digit", c => '0' <= c && c <= '7') ^^ (_ - '0') 78 | 79 | def hexDigit = accept("hex digit", { 80 | case c @ ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') => c - '0' 81 | case c @ ('A' | 'B' | 'C' | 'D' | 'E' | 'F') => c - 'A' + 10 82 | case c @ ('a' | 'b' | 'c' | 'd' | 'e' | 'f') => c - 'a' + 10 83 | }) 84 | 85 | // legal identifier chars 86 | def isIdentifierStart(c: Char): Boolean = c == '$' || c == '_' || c.isUnicodeIdentifierStart 87 | def isIdentifierPart(c: Char): Boolean = c == '$' || c.isUnicodeIdentifierPart 88 | 89 | def stringOf(p: => Parser[Char]): Parser[String] = rep(p) ^^ chars2string 90 | def stringOf1(p: => Parser[Char]): Parser[String] = rep1(p) ^^ chars2string 91 | def stringOf1(first: => Parser[Char], p: => Parser[Char]): Parser[String] = rep1(first, p) ^^ chars2string 92 | 93 | private def chars2string(chars: List[Char]) = chars.mkString("") 94 | 95 | // reserved words and delimiters 96 | 97 | /** The set of reserved identifiers: these will be returned as Keywords */ 98 | val reserved = new mutable.HashSet[String] 99 | 100 | /** The set of delimiters (ordering does not matter) */ 101 | val delimiters = new mutable.HashSet[String] 102 | 103 | private lazy val _delim: Parser[Token] = { 104 | /* construct parser for delimiters by |'ing together the parsers for the 105 | * individual delimiters, starting with the longest one -- otherwise a 106 | * delimiter D will never be matched if there is another delimiter that is 107 | * a prefix of D 108 | */ 109 | def parseDelim(s: String): Parser[Token] = accept(s.toList) ^^ { x => Keyword(s) } 110 | 111 | val d = new Array[String](delimiters.size) 112 | delimiters.copyToArray(d, 0) 113 | scala.util.Sorting.quickSort(d) 114 | d.toList.map(parseDelim).foldRight(failure("no matching delimiter"): Parser[Token])((x, y) => y | x) 115 | } 116 | 117 | protected def delim: Parser[Token] = _delim 118 | } 119 | -------------------------------------------------------------------------------- /app/models/parse/parser/TSTokens.scala: -------------------------------------------------------------------------------- 1 | package models.parse.parser 2 | 3 | import scala.util.parsing.combinator.token.StdTokens 4 | 5 | trait TSTokens extends StdTokens { 6 | case class ImportComment(chars: String) extends Token { 7 | override def toString = "// [import]: " + chars 8 | } 9 | 10 | case class LineComment(chars: String) extends Token { 11 | override def toString = "//" + chars 12 | } 13 | 14 | case class MultilineComment(chars: String) extends Token { 15 | override def toString = "/*" + chars + "*/" 16 | } 17 | 18 | case class Whitespace(chars: String) extends Token { 19 | override def toString = "[whitespace]" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/models/parse/sc/printer/PrinterFiles.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.printer 2 | 3 | import models.parse.sc.tree.Name 4 | 5 | trait PrinterFiles { 6 | def pushPackage(pkg: Name): Unit 7 | def popPackage(pkg: Name): Unit 8 | def getActiveObject: Option[Name] 9 | def setActiveObject(n: Name): Unit = () 10 | def clearActiveObject(n: Name): Unit = () 11 | 12 | def print(s: String): Unit 13 | 14 | def onComplete(): Seq[String] 15 | } 16 | -------------------------------------------------------------------------------- /app/models/parse/sc/printer/PrinterFilesMulti.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.printer 2 | 3 | import better.files._ 4 | import models.parse.ProjectDefinition 5 | import models.parse.sc.transform.ReplacementManager 6 | import models.parse.sc.tree.Name 7 | import services.parse.ClassReferenceService 8 | import utils.Logging 9 | 10 | case class PrinterFilesMulti(key: String, keyNormalized: String, root: File) extends PrinterFiles with Logging { 11 | log.info(s"Parsing multiple files for [$key]...") 12 | 13 | private[this] val stack = collection.mutable.Stack[(Name, File)]() 14 | private[this] var activeDir: Option[File] = Some(root) 15 | private[this] var activeObject: Option[Name] = None 16 | private[this] var activeFile: Option[File] = None 17 | 18 | if (root.exists) { 19 | root.delete() 20 | } 21 | root.createDirectory 22 | 23 | val rootObj = root / "package.scala" 24 | 25 | override def pushPackage(pkg: Name) = { 26 | val dir = activeDir match { 27 | case Some(active) => active / pkg.name 28 | case None => root / pkg.name 29 | } 30 | dir.createIfNotExists(asDirectory = true) 31 | 32 | activeDir = Some(dir) 33 | stack.push(pkg -> dir) 34 | } 35 | 36 | override def popPackage(pkg: Name) = { 37 | val popped = stack.pop() 38 | if (pkg != popped._1) { 39 | throw new IllegalStateException(s"Observed [$popped], not expected [$pkg].") 40 | } 41 | activeDir = activeDir.map(_.parent) 42 | } 43 | 44 | override def getActiveObject = activeObject 45 | 46 | override def setActiveObject(n: Name) = { 47 | activeObject.foreach(current => if (current.name != n.name) { 48 | throw new IllegalStateException(s"Attempt to set active object [$n] when [$current] is already set.") 49 | }) 50 | activeObject = Some(n) 51 | val file = activeDir match { 52 | case Some(active) => active / s"${ProjectDefinition.normalize(n.name)}.scala" 53 | case None => throw new IllegalStateException("No active directory.") 54 | } 55 | if (!file.exists) { 56 | val pkg = stack.map(_._1.name).reverse.mkString(".") 57 | file.createIfNotExists(createParents = true) 58 | if (pkg.isEmpty) { 59 | file.append(s"package com.definitelyscala.$keyNormalized\n") 60 | } else { 61 | file.append(s"package com.definitelyscala.$keyNormalized.$pkg\n") 62 | } 63 | 64 | file.append("\n") 65 | file.append("import scala.scalajs.js\n") 66 | } 67 | activeFile = Some(file) 68 | } 69 | 70 | override def clearActiveObject(n: Name) = activeObject match { 71 | case Some(active) => if (n == active) { 72 | activeFile = None 73 | activeObject = None 74 | } else { 75 | // Noop for now 76 | } 77 | case None => //throw new IllegalStateException(s"Attempt to clear active object with none active.") 78 | } 79 | 80 | def packageObject() = { 81 | activeDir.map(_ / "package.scala").getOrElse(rootObj) 82 | } 83 | 84 | def print(s: String) = { 85 | //log(s) 86 | activeFile match { 87 | case Some(file) => file.append(s) 88 | case None => packageObject().append(s) 89 | } 90 | } 91 | 92 | override def onComplete() = { 93 | val textContent = new StringBuilder 94 | val replacements = ReplacementManager.getReplacements(key) 95 | 96 | root.listRecursively().toList.map { file => 97 | if (!file.isDirectory) 98 | if (file.size <= 1024 && file.contentAsString.trim.isEmpty) { 99 | file.delete() 100 | } else { 101 | val originalContent = if (file.name == "package.scala") { 102 | Seq(s"package com.definitelyscala.$keyNormalized\n") ++ file.lines.toList 103 | } else { 104 | file.lines.toList 105 | } 106 | val newContent = replacements.replace(originalContent) 107 | val ret = ClassReferenceService.insertImports(file.pathAsString, newContent) 108 | val body = ret.mkString("\n") 109 | file.delete() 110 | file.write(body) 111 | textContent.append(" ::: " + file.pathAsString + "\n") 112 | textContent.append(body + "\n") 113 | } 114 | } 115 | textContent.toString.split('\n') 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/models/parse/sc/printer/PrinterFilesSingle.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.printer 2 | 3 | import better.files._ 4 | import models.parse.sc.transform.ReplacementManager 5 | import models.parse.sc.tree.Name 6 | import services.parse.ClassReferenceService 7 | 8 | case class PrinterFilesSingle(key: String, keyNormalized: String, file: File) extends PrinterFiles { 9 | if (file.exists) { 10 | file.delete() 11 | } 12 | 13 | file.append(s"package com.definitelyscala.$keyNormalized\n") 14 | 15 | file.append("\n") 16 | file.append("import scala.scalajs.js\n") 17 | 18 | override def pushPackage(pkg: Name) = { 19 | val p = pkg.name.replaceAllLiterally("-", "").replaceAllLiterally("_", "") 20 | file.append(s"package $p {\n") 21 | } 22 | override def popPackage(pkg: Name) = file.append(s"}\n") 23 | 24 | override def getActiveObject = None 25 | 26 | override def print(s: String) = file.append(s) 27 | 28 | override def onComplete() = { 29 | val replacements = ReplacementManager.getReplacements(key) 30 | val originalContent = file.lines.toList 31 | val newContent = replacements.replace(originalContent) 32 | val (rewrite, finalContent) = if (originalContent != newContent) { 33 | true -> newContent 34 | } else { 35 | false -> originalContent 36 | } 37 | 38 | val ret = ClassReferenceService.insertImports(file.pathAsString, finalContent) 39 | file.delete() 40 | file.write(ret.mkString("\n")) 41 | ret 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/models/parse/sc/printer/PrinterHelper.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.printer 2 | 3 | object PrinterHelper { 4 | class ListElemSeparator(val s: String) extends AnyVal 5 | 6 | object ListElemSeparator { 7 | val Comma = new ListElemSeparator(", ") 8 | val WithKeyword = new ListElemSeparator(" with ") 9 | } 10 | 11 | implicit class OutputHelper(val sc: StringContext) extends AnyVal { 12 | def p(args: Any*)(implicit printer: Printer, sep: ListElemSeparator = ListElemSeparator.Comma): Unit = { 13 | val strings = sc.parts.iterator 14 | val expressions = args.iterator 15 | 16 | printer.files.print(strings.next()) 17 | while (strings.hasNext) { 18 | expressions.next() match { 19 | case seq: Seq[_] => 20 | val iter = seq.iterator 21 | if (iter.hasNext) { 22 | printer.print(iter.next()) 23 | while (iter.hasNext) { 24 | printer.files.print(sep.s) 25 | printer.print(iter.next()) 26 | } 27 | } 28 | 29 | case expr => printer.print(expr) 30 | } 31 | printer.files.print(strings.next()) 32 | } 33 | } 34 | 35 | def pln(args: Any*)(implicit printer: Printer) = { 36 | p(args: _*)(printer, ListElemSeparator.Comma) 37 | printer.files.print("\n") 38 | } 39 | 40 | def plnw(args: Any*)(implicit printer: Printer) = { 41 | p(args: _*)(printer, ListElemSeparator.WithKeyword) 42 | printer.files.print("\n") 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/models/parse/sc/transform/ExcludedMembers.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.transform 2 | 3 | import enumeratum._ 4 | 5 | object ExcludedMembers { 6 | sealed abstract class Exclusions(val key: String, val global: Set[String] = Set.empty, val files: Map[String, Set[String]]) extends EnumEntry { 7 | override def toString = key 8 | } 9 | 10 | object Exclusions extends Enum[Exclusions] { 11 | case object AmCharts extends Exclusions("amcharts", files = Map( 12 | "AmCoordinateChart" -> Set("addListener"), "AmPieChart" -> Set("addListener"), "ValueAxis" -> Set("position", "addGuide", "removeGuide"))) 13 | case object AWSSDK extends Exclusions("aws-sdk", files = Map("ClientConfig" -> Set("credentials", "region"))) 14 | case object BigInteger extends Exclusions("big-integer", files = Map("BigInteger" -> Set("toString", "valueOf"))) 15 | case object Blocks extends Exclusions("blocks", files = Map("BlocksArray" -> Set("update", "extend"))) 16 | case object CanvasJS extends Exclusions("canvasjs", files = Map("ChartDataPoint" -> Set("legendMarkerColor"))) 17 | case object JQuery extends Exclusions("jquery", files = Map( 18 | "BaseJQueryEventObject" -> Set("currentTarget", "preventDefault", "stopImmediatePropagation", "stopPropagation", "target"), 19 | "JQueryInputEventObject" -> Set("metaKey", "pageX", "pageY"), 20 | "JQueryMouseEventObject" -> Set("pageX", "pageY"))) 21 | case object JQueryUI extends Exclusions("jqueryui", files = Map("DialogOptions" -> Set("open", "close"))) 22 | case object PixiJS extends Exclusions("pixi.js", global = Set("clone"), files = Map( 23 | "BaseRenderTexture" -> Set("height", "width", "realHeight", "realWidth", "resolution", "scaleMode", "hasLoaded", "destroy", "once", "on", "off"), 24 | "BaseTexture" -> Set("on", "once"), 25 | "BitmapText" -> Set("updateTransform"), 26 | "BlurFilter" -> Set("resolution", "padding"), 27 | "BlurXFilter" -> Set("resolution"), 28 | "BlurYFilter" -> Set("resolution"), 29 | "CanvasRenderer" -> Set("destroy", "resize", "on", "once"), 30 | "CanvasSpriteRenderer" -> Set("destroy"), 31 | "Container" -> Set("updateTransform", "renderWebGL", "renderCanvas", "once", "on", "off"), 32 | "DisplayObject" -> Set("interactive", "buttonMode", "hitArea", "interactiveChildren", "defaultCursor", "on", "once", "destroy"), 33 | "FilterManager" -> Set("destroy"), 34 | "Graphics" -> Set("_renderCanvas", "_calculateBounds", "destroy"), 35 | "GraphicsRenderer" -> Set("destroy"), 36 | "Loader" -> Set("on", "once"), 37 | "Mesh" -> Set("_renderWebGL", "_renderCanvas", "_calculateBounds"), 38 | "NineSlicePlane" -> Set("width", "height"), 39 | "ParticleContainer" -> Set("interactiveChildren", "onChildrenChange", "destroy"), 40 | "ParticleRenderer" -> Set("start", "destroy"), 41 | "Plane" -> Set("drawMode"), 42 | "RenderTexture" -> Set("valid"), 43 | "Rope" -> Set("_onTextureUpdate", "updateTransform"), 44 | "Sprite" -> Set("width", "height", "_calculateBounds", "_renderWebGL", "_renderCanvas", "destroy"), 45 | "SpriteRenderer" -> Set("flush", "start", "stop", "destroy"), 46 | "StencilManager" -> Set("destroy"), 47 | "Text" -> Set("width", "height", "renderWebGL", "_renderCanvas", "_calculateBounds", "destroy"), 48 | "TextStyle" -> Set( 49 | "align", "breakWords", "dropShadow", "dropShadowAngle", "dropShadowBlur", "dropShadowColor", "dropShadowDistance", "fill", "fillGradientType", 50 | "fontFamily", "fontSize", "fontStyle", "fontVariant", "fontWeight", "letterSpacing", "lineHeight", "lineJoin", "miterLimit", "padding", 51 | "stroke", "strokeThickness", "styleID", "textBaseline", "wordWrap", "wordWrapWidth"), 52 | "Texture" -> Set("on", "once"), 53 | "TilingSprite" -> Set( 54 | "_width", "_height", "_onTextureUpdate", "_renderWebGL", "_renderCanvas", "_calculateBounds", "getLocalBounds", "containsPoint", "width", "height"), 55 | "TransformStatic" -> Set("updateLocalTransform", "updateTransform"), 56 | "VideoBaseTexture" -> Set("update", "destroy", "source"), 57 | "VoidFilter" -> Set("glShaderKey"), 58 | "WebGLRenderer" -> Set("_backgroundColorRgba", "destroy", "resize", "on", "once"))) 59 | 60 | override val values = findValues 61 | } 62 | 63 | val badNames = Seq("toString", "clone", "notify") 64 | 65 | def check(key: String, cls: String, member: String) = Exclusions.withNameInsensitiveOption(key) match { 66 | case _ if badNames.contains(member) => false 67 | case Some(ex) => 68 | val matchKey = ex.global(member) 69 | val matchMember = ex.files.get(cls).exists(_.contains(member)) 70 | !(matchKey || matchMember) 71 | case None => true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/models/parse/sc/transform/IgnoredPackages.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.transform 2 | 3 | object IgnoredPackages { 4 | def forKey(key: String) = pkgs.getOrElse(key, Set.empty) 5 | 6 | val pkgs = Map( 7 | "accounting" -> Set("accounting"), 8 | "alertify" -> Set("alertify"), 9 | "algoliasearch" -> Set("algoliasearch"), 10 | "amcharts" -> Set("AmCharts"), 11 | "amplify" -> Set("amplify"), 12 | "atmosphere" -> Set("Atmosphere"), 13 | "bigint" -> Set("BigInt"), 14 | "busboy" -> Set("busboy"), 15 | "canvasjs" -> Set("CanvasJS"), 16 | "gamepad" -> Set("Gamepad"), 17 | "jqueryui" -> Set("JQueryUI"), 18 | "less" -> Set("Less"), 19 | "materializecss" -> Set("Materialize"), 20 | "matterjs" -> Set("Matter"), 21 | "node" -> Set("NodeJS"), 22 | "phaser" -> Set("Phaser"), 23 | "phaserpixi" -> Set("PIXI"), 24 | "pixijs" -> Set("PIXI"), 25 | "react" -> Set("React"), 26 | "test" -> Set("excluded"), 27 | "" -> Set("")) 28 | } 29 | -------------------------------------------------------------------------------- /app/models/parse/sc/transform/ReplacementManager.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.transform 2 | 3 | import scala.io.Source 4 | 5 | object ReplacementManager { 6 | def getReplacements(key: String) = Option(getClass.getClassLoader.getResourceAsStream(s"replacement/$key.txt")) match { 7 | case Some(stream) => 8 | val src = Source.fromInputStream(stream).getLines.toArray 9 | Replacements(key, Replacements.toRules(key, src)) 10 | case None => Replacements(key, Nil) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/models/parse/sc/transform/Replacements.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.transform 2 | 3 | import utils.Logging 4 | 5 | import scala.util.control.NonFatal 6 | 7 | object Replacements extends Logging { 8 | sealed trait Rule { 9 | def replace(lines: Seq[String]): Seq[String] 10 | } 11 | 12 | private[this] def unquote(txt: String) = if (txt.startsWith("\"") && txt.endsWith("\"")) { txt.substring(1, txt.length - 1) } else { txt } 13 | 14 | object Rule { 15 | case class AddLine(src: String, tgt: String) extends Rule { 16 | override def replace(lines: Seq[String]) = lines.flatMap { l => 17 | if (l == src) { Seq(l, tgt) } else { Seq(l) } 18 | } 19 | } 20 | case class RemoveLine(tgt: String) extends Rule { 21 | override def replace(lines: Seq[String]) = lines.filterNot { line => 22 | if (line.contains("debug.IDebug")) { 23 | throw new IllegalStateException(line) 24 | } 25 | line == tgt 26 | } 27 | } 28 | case class ReplaceLine(src: String, tgt: String) extends Rule { 29 | override def replace(lines: Seq[String]) = lines.map { l => 30 | if (l == src) { tgt } else { l } 31 | } 32 | } 33 | case class ReplaceText(src: String, tgt: String) extends Rule { 34 | override def replace(lines: Seq[String]) = lines.map { line => 35 | line.replaceAllLiterally(unquote(src), unquote(tgt)) 36 | } 37 | } 38 | } 39 | 40 | def toRules(id: String, lines: Seq[String]) = try { 41 | lines.zipWithIndex.foldLeft(Seq.empty[Rule]) { (rules, line) => 42 | line._1 match { 43 | case "+" => rules :+ Rule.AddLine(lines(line._2 + 1), lines(line._2 + 2)) 44 | case "-" => rules :+ Rule.RemoveLine(lines(line._2 + 1)) 45 | case "=" => rules :+ Rule.ReplaceLine(lines(line._2 + 1), lines(line._2 + 2)) 46 | case "*" => rules :+ Rule.ReplaceText(lines(line._2 + 1), lines(line._2 + 2)) 47 | case _ => rules 48 | } 49 | } 50 | } catch { 51 | case NonFatal(x) => 52 | log.error(s"Error processing replacements for [$id].", x) 53 | throw x 54 | } 55 | } 56 | 57 | case class Replacements(key: String, rules: Seq[Replacements.Rule]) { 58 | def replace(lines: Seq[String]) = rules.foldLeft(lines) { (l, r) => r.replace(l) } 59 | } 60 | -------------------------------------------------------------------------------- /app/models/parse/sc/transform/Transformations.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.transform 2 | 3 | import models.parse.sc.tree.{ Name, QualifiedName } 4 | 5 | object Transformations { 6 | def forName(n: QualifiedName) = { 7 | val last = n.parts.last 8 | types.get(last.name) match { 9 | case Some(tx) => QualifiedName(n.parts.dropRight(1) :+ Name(tx): _*) 10 | case None => n 11 | } 12 | } 13 | 14 | def types = Map( 15 | "XMLDocument" -> "Document", 16 | "RegExp" -> "js.RegExp", 17 | "PointerEvent" -> "Event", 18 | "WebGLContextEvent" -> "Event") 19 | } 20 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/ClassSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import scala.collection.mutable 4 | 5 | class ClassSymbol(nme: Name) extends ContainerSymbol(nme) { 6 | val tparams = new mutable.ListBuffer[TypeParamSymbol] 7 | val parents = new mutable.ListBuffer[TypeRef] 8 | var companionModule: ModuleSymbol = _ 9 | var isTrait: Boolean = true 10 | def isFancy: Boolean = members.exists { 11 | case x: MethodSymbol if x.isBracketAccess || x.name.name == "apply" => true 12 | case _ => false 13 | } 14 | var isSealed: Boolean = false 15 | var isAbstract: Boolean = false 16 | 17 | override def toString = { 18 | val sl = if (isSealed) { "sealed " } else { "" } 19 | val a = if (isAbstract) { "abstract " } else { "" } 20 | val t = if (isTrait) { s"trait $name" } else { s"class $name" } 21 | val p = if (tparams.isEmpty) { "" } else { tparams.mkString("<", ", ", ">") } 22 | sl + a + t + p 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/CommentSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class CommentSymbol(val text: String, val multiline: Boolean) extends Symbol(Name("")) { 4 | val cleanedText = text.replaceAllLiterally("@link", "") 5 | 6 | override def toString = if (multiline) { 7 | s"/*$cleanedText*/" 8 | } else { 9 | s"//$cleanedText" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/ContainerSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import scala.collection.mutable 4 | 5 | class ContainerSymbol(nme: Name) extends Symbol(nme) { 6 | val members = new mutable.ListBuffer[Symbol] 7 | 8 | private var _anonMemberCounter = 0 9 | def newAnonMemberName() = { 10 | _anonMemberCounter += 1 11 | "anon$" + _anonMemberCounter 12 | } 13 | 14 | def findClass(name: Name): Option[ClassSymbol] = members.collectFirst { 15 | case sym: ClassSymbol if sym.name == name => sym 16 | } 17 | 18 | def findModule(name: Name): Option[ModuleSymbol] = members.collectFirst { 19 | case sym: ModuleSymbol if sym.name == name => sym 20 | } 21 | 22 | def getClassOrCreate(name: Name): ClassSymbol = findClass(name).getOrElse { 23 | val result = new ClassSymbol(name) 24 | members += result 25 | findModule(name) foreach { companion => 26 | result.companionModule = companion 27 | companion.companionClass = result 28 | } 29 | result 30 | } 31 | 32 | def getModuleOrCreate(name: Name): ModuleSymbol = findModule(name) getOrElse { 33 | val result = new ModuleSymbol(name) 34 | members += result 35 | findClass(name) foreach { companion => 36 | result.companionClass = companion 37 | companion.companionModule = result 38 | } 39 | result 40 | } 41 | 42 | def newTypeAlias(name: Name): TypeAliasSymbol = { 43 | val result = new TypeAliasSymbol(name) 44 | members += result 45 | result 46 | } 47 | 48 | def newField(prot: Boolean, name: Name, readonly: Boolean = false): FieldSymbol = { 49 | val result = new FieldSymbol(prot, name, readonly) 50 | members += result 51 | result 52 | } 53 | 54 | def newMethod(prot: Boolean, name: Name): MethodSymbol = { 55 | val result = new MethodSymbol(prot, name) 56 | members += result 57 | result 58 | } 59 | 60 | def removeIfDuplicate(sym: MethodSymbol): Unit = { 61 | val isDuplicate = members.exists(s => (s ne sym) && (s == sym)) 62 | if (isDuplicate) 63 | members.remove(members.indexWhere(_ eq sym)) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/FieldSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import models.parse.sc.transform.Transformations 4 | 5 | class FieldSymbol(prot: Boolean, nme: Name, readonly: Boolean) extends Symbol(nme) with JSNameable { 6 | var tpe: TypeRef = TypeRef.Any 7 | 8 | def tpeTranslated = tpe.copy(typeName = Transformations.forName(tpe.typeName)) 9 | 10 | val p = if (prot) { 11 | "protected " 12 | } else { 13 | "" 14 | } 15 | val decl = if (readonly) { 16 | "val" 17 | } else if (name.name == name.name.toUpperCase) { 18 | "val" 19 | } else { 20 | "var" 21 | } 22 | 23 | override def toString = s"$jsNameStr$p$decl $name: $tpeTranslated" 24 | } 25 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/JSNameable.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | trait JSNameable extends Symbol { 4 | var jsName: Option[String] = None 5 | 6 | def protectName(): Unit = { 7 | val n = name.name 8 | if (jsName.isEmpty && (n.contains("$") || n == "apply")) { 9 | jsName = Some(n) 10 | } 11 | } 12 | 13 | protected def jsNameStr = jsName.fold("")(n => s"""@JSName("$n") """) 14 | } 15 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/MethodSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import scala.collection.mutable 4 | 5 | class MethodSymbol(prot: Boolean, nme: Name) extends Symbol(nme) with JSNameable { 6 | val tparams = new mutable.ListBuffer[TypeParamSymbol] 7 | val params = new mutable.ListBuffer[ParamSymbol] 8 | var resultType: TypeRef = TypeRef.Dynamic 9 | var isBracketAccess: Boolean = false 10 | val p = if (prot) { "protected " } else { "" } 11 | 12 | override def toString = { 13 | val bracketAccessStr = if (isBracketAccess) { "@JSBracketAccess " } else { "" } 14 | 15 | val tparamsStr = if (tparams.isEmpty) { 16 | "" 17 | } else { 18 | tparams.mkString("[", ", ", "]") 19 | } 20 | s"$jsNameStr$bracketAccessStr${p}def $name$tparamsStr(${params.mkString(", ")}): $resultType" 21 | } 22 | 23 | def paramTypes = params.map(_.tpe) 24 | 25 | override def equals(that: Any): Boolean = that match { 26 | case that: MethodSymbol => 27 | this.name == that.name && this.tparams == that.tparams && this.paramTypes == that.paramTypes && this.resultType == that.resultType 28 | case _ => false 29 | } 30 | 31 | override def hashCode() = prot.hashCode * nme.hashCode 32 | } 33 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/ModuleSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class ModuleSymbol(nme: Name) extends ContainerSymbol(nme) { 4 | var companionClass: ClassSymbol = _ 5 | 6 | override def toString = s"object $name" 7 | } 8 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/Name.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import models.parse.Utils 4 | 5 | object Name { 6 | val scala = Name("scala") 7 | val scalajs = Name("scalajs") 8 | val js = Name("js") 9 | val java = Name("java") 10 | val lang = Name("lang") 11 | 12 | val EMPTY = Name("") 13 | val CONSTRUCTOR = Name("") 14 | val REPEATED = Name("*") 15 | val SINGLETON = Name("") 16 | } 17 | 18 | case class Name(name: String) { 19 | override def toString = Utils.scalaEscape(name) 20 | } 21 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/PackageSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class PackageSymbol(nme: Name) extends ContainerSymbol(nme) { 4 | override def toString = s"package $name" 5 | 6 | def findPackage(name: Name): Option[PackageSymbol] = { 7 | members.collectFirst { 8 | case sym: PackageSymbol if sym.name == name => sym 9 | } 10 | } 11 | 12 | def getPackageOrCreate(name: Name): PackageSymbol = { 13 | findPackage(name) getOrElse { 14 | val result = new PackageSymbol(name) 15 | members += result 16 | result 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/ParamSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class ParamSymbol(nme: Name) extends Symbol(nme) { 4 | def this(nme: Name, tpe: TypeRef) = { 5 | this(nme) 6 | this.tpe = tpe 7 | } 8 | 9 | var optional: Boolean = false 10 | var readonly: Boolean = false 11 | var allowDefaults: Boolean = true 12 | var tpe: TypeRef = TypeRef.Any 13 | 14 | override def toString = s"$name: $tpe" + (if (optional) " = _" else "") 15 | 16 | override def equals(that: Any): Boolean = that match { 17 | case that: ParamSymbol => this.name == that.name && this.tpe == that.tpe 18 | case _ => false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/QualifiedName.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import scala.language.implicitConversions 4 | 5 | object QualifiedName { 6 | implicit def fromName(name: Name): QualifiedName = QualifiedName(name) 7 | 8 | val Root = QualifiedName() 9 | val scala = Root dot Name.scala 10 | val scala_js = scala dot Name.scalajs dot Name.js 11 | val java_lang = Root dot Name.java dot Name.lang 12 | 13 | val Array = scala_js dot Name("Array") 14 | val Dictionary = scala_js dot Name("Dictionary") 15 | val FunctionBase = scala_js dot Name("Function") 16 | def Function(arity: Int) = scala_js dot Name("Function" + arity) 17 | def Tuple(arity: Int) = scala_js dot Name("Tuple" + arity) 18 | val Union = scala_js dot Name("|") 19 | } 20 | 21 | case class QualifiedName(parts: Name*) { 22 | def isRoot = parts.isEmpty 23 | 24 | override def toString = if (isRoot) { 25 | "_root_" 26 | } else { 27 | parts.mkString(".") 28 | } 29 | 30 | def dot(name: Name) = QualifiedName(parts :+ name: _*) 31 | def init = QualifiedName(parts.init: _*) 32 | def last = parts.last 33 | } 34 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/Symbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class Symbol(val name: Name) { 4 | override def toString = s"${this.getClass.getSimpleName}($name)}" 5 | } 6 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/TypeAliasSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | import scala.collection.mutable 4 | 5 | class TypeAliasSymbol(nme: Name) extends Symbol(nme) { 6 | val tparams = new mutable.ListBuffer[TypeParamSymbol] 7 | var alias: TypeRef = TypeRef.Any 8 | 9 | override def toString = s"type $name" + (if (tparams.isEmpty) { "" } else { tparams.mkString("<", ", ", ">") }) 10 | } 11 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/TypeParamSymbol.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | class TypeParamSymbol(nme: Name, val upperBound: Option[TypeRef]) extends Symbol(nme) { 4 | override def toString = { 5 | nme.toString + upperBound.fold("")(bound => s" <: $bound") 6 | } 7 | 8 | override def equals(that: Any): Boolean = that match { 9 | case that: TypeParamSymbol => this.name == that.name && this.upperBound == that.upperBound 10 | case _ => false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/models/parse/sc/tree/TypeRef.scala: -------------------------------------------------------------------------------- 1 | package models.parse.sc.tree 2 | 3 | case class TypeRef(typeName: QualifiedName, targs: List[TypeRef] = Nil) { 4 | override def toString = s"$typeName[${targs.mkString(", ")}]" 5 | } 6 | 7 | object TypeRef { 8 | import QualifiedName.{ java_lang, scala, scala_js } 9 | 10 | val ScalaAny = TypeRef(scala dot Name("Any")) 11 | 12 | val Any = TypeRef(scala_js dot Name("Any")) 13 | val Dynamic = TypeRef(scala_js dot Name("Dynamic")) 14 | val Double = TypeRef(scala dot Name("Double")) 15 | val Boolean = TypeRef(scala dot Name("Boolean")) 16 | val String = TypeRef(java_lang dot Name("String")) 17 | val Object = TypeRef(scala_js dot Name("Object")) 18 | val Function = TypeRef(scala_js dot Name("Function")) 19 | val Unit = TypeRef(scala dot Name("Unit")) 20 | val Null = TypeRef(scala dot Name("Null")) 21 | 22 | object Union { 23 | def apply(left: TypeRef, right: TypeRef): TypeRef = TypeRef(QualifiedName.Union, List(left, right)) 24 | 25 | def unapply(typeRef: TypeRef): Option[(TypeRef, TypeRef)] = typeRef match { 26 | case TypeRef(QualifiedName.Union, List(left, right)) => Some((left, right)) 27 | case _ => None 28 | } 29 | } 30 | 31 | object Singleton { 32 | def apply(underlying: QualifiedName): TypeRef = TypeRef(QualifiedName(Name.SINGLETON), List(TypeRef(underlying))) 33 | 34 | def unapply(typeRef: TypeRef): Option[QualifiedName] = typeRef match { 35 | case TypeRef(QualifiedName(Name.SINGLETON), List(TypeRef(underlying, Nil))) => Some(underlying) 36 | case _ => None 37 | } 38 | } 39 | 40 | object Repeated { 41 | def apply(underlying: TypeRef): TypeRef = TypeRef(QualifiedName(Name.REPEATED), List(underlying)) 42 | 43 | def unapply(typeRef: TypeRef) = typeRef match { 44 | case TypeRef(QualifiedName(Name.REPEATED), List(underlying)) => Some(underlying) 45 | case _ => None 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/models/sandbox/SandboxTask.scala: -------------------------------------------------------------------------------- 1 | package models.sandbox 2 | 3 | import enumeratum._ 4 | import scala.concurrent.ExecutionContext.Implicits.global 5 | import utils.{ Application, Logging } 6 | 7 | import scala.concurrent.Future 8 | 9 | sealed abstract class SandboxTask(val id: String, val name: String, val description: String) extends EnumEntry with Logging { 10 | def run(app: Application): Future[SandboxTask.Result] = { 11 | log.info(s"Running sandbox task [$id]...") 12 | val startMs = System.currentTimeMillis 13 | val result = call(app).map { r => 14 | val res = SandboxTask.Result(this, "OK", r, (System.currentTimeMillis - startMs).toInt) 15 | log.info(s"Completed sandbox task [$id] with status [${res.status}] in [${res.elapsed}ms].") 16 | res 17 | } 18 | result 19 | } 20 | def call(app: Application): Future[String] 21 | override def toString = id 22 | } 23 | 24 | object SandboxTask extends Enum[SandboxTask] { 25 | case class Result(task: SandboxTask, status: String = "OK", result: String, elapsed: Int) 26 | 27 | case object Testbed extends SandboxTask("testbed", "Testbed", "A simple sandbox for messin' around.") { 28 | override def call(app: Application) = Future.successful("All good!") 29 | } 30 | 31 | override val values = findValues 32 | } 33 | -------------------------------------------------------------------------------- /app/services/file/FileService.scala: -------------------------------------------------------------------------------- 1 | package services.file 2 | 3 | import better.files._ 4 | 5 | object FileService { 6 | private[this] var dataDir: Option[File] = None 7 | 8 | def setRootDir(d: File) = { 9 | dataDir = Some(d) 10 | if (!d.exists) { 11 | d.createDirectory() 12 | } 13 | if (!d.isDirectory) { 14 | throw new IllegalStateException(s"Cannot load data directory [$d], as it is a file.") 15 | } 16 | } 17 | 18 | def getDir(name: String, createIfMissing: Boolean = true) = { 19 | val d = dataDir.getOrElse(throw new IllegalStateException("File service not initialized.")) / name 20 | if (createIfMissing && (!d.exists)) { 21 | d.createDirectory() 22 | } 23 | d 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/services/git/GitService.scala: -------------------------------------------------------------------------------- 1 | package services.git 2 | 3 | import better.files._ 4 | import services.file.FileService 5 | import utils.Logging 6 | 7 | object GitService extends Logging { 8 | def init(dir: File) = if ((dir / ".git").exists) { 9 | throw new IllegalStateException("Already initialized.") 10 | } else { 11 | call(dir, Seq("init")) 12 | } 13 | 14 | def reset(dir: File) = call(dir, Seq("reset", "--hard", "origin/master")) 15 | 16 | def status(dir: File) = call(dir, Seq("status", "--short", "--ignore-submodules")) 17 | 18 | def commitCount(dir: File) = { 19 | call(dir, Seq("log", "--pretty=oneline"))._2.split("\\n").toList match { 20 | case Nil => -1 21 | case h :: Nil if h.contains("does not have") => 0 22 | case h :: Nil if h.contains("or any of the parent") => -1 23 | case x => x.length 24 | } 25 | } 26 | 27 | def addRemote(dir: File) = if ((dir / ".git").exists) { 28 | call(dir, Seq("remote", "add", "origin", s"git@github.com:DefinitelyScala/${dir.name}.git")) 29 | } else { 30 | throw new IllegalStateException(s"No git repo available for [${dir.name}].") 31 | } 32 | 33 | private[this] val firstCommitFiles = Seq( 34 | ".gitignore", "build.sbt", "readme.md", "scalastyle-config.xml", 35 | "project/Projects.scala", "project/build.properties", "project/plugins.sbt") 36 | def firstCommit(dir: File) = { 37 | call(dir, Seq("add") ++ firstCommitFiles) 38 | call(dir, Seq("commit", "-m", "Initial project structure.")) 39 | call(dir, Seq("push", "origin", "master")) 40 | } 41 | 42 | def secondCommit(dir: File) = { 43 | call(dir, Seq("add", "src/*")) 44 | call(dir, Seq("commit", "-m", "Scala.js facade.")) 45 | call(dir, Seq("push", "origin", "master")) 46 | } 47 | 48 | private[this] val thirdCommitFiles = Seq(".travis.yml") 49 | def thirdCommit(dir: File) = { 50 | call(dir, Seq("add") ++ thirdCommitFiles) 51 | call(dir, Seq("commit", "-m", "TravisCI integration.")) 52 | call(dir, Seq("push", "origin", "master")) 53 | } 54 | 55 | def commit(dir: File, files: Seq[String], message: String) = { 56 | if (files.isEmpty) { 57 | call(dir, Seq("add", ".")) 58 | } else { 59 | files.foreach(f => call(dir, Seq("add", f))) 60 | } 61 | call(dir, Seq("commit", "-m", message)) 62 | } 63 | 64 | def push(dir: File) = call(dir, Seq("push", "origin", "master")) 65 | 66 | def cloneRepo(dir: File, key: String) = { 67 | call(dir, Seq("clone", s"git@github.com:DefinitelyScala/$key.git")) 68 | } 69 | 70 | private[this] def call(dir: File, cmd: Seq[String]) = if (dir.exists) { 71 | log.info(s"Calling [git] with arguments [${cmd.mkString(" ")}]") 72 | val f = FileService.getDir("logs") / "git" / (dir.name + ".log") 73 | if (f.exists) { 74 | f.delete() 75 | } 76 | val result = new ProcessBuilder().directory(dir.toJava).command("git" +: cmd: _*).redirectError(f.toJava).redirectOutput(f.toJava).start().waitFor() 77 | result -> f.contentAsString 78 | } else { 79 | -1 -> s"Missing directory [$dir]." 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/services/github/GithubService.scala: -------------------------------------------------------------------------------- 1 | package services.github 2 | 3 | import io.circe.Json 4 | import utils.JsonSerializers._ 5 | import play.api.libs.ws.{ WSAuthScheme, WSClient, WSRequest, WSResponse } 6 | import scala.concurrent.ExecutionContext.Implicits.global 7 | 8 | import scala.concurrent.Future 9 | import scala.util.control.NonFatal 10 | 11 | object GithubService { 12 | val baseUrl = "https://api.github.com/" 13 | val accessKey = Option(System.getProperty("GITHUB_KEY")).orElse(Option(System.getenv("GITHUB_KEY"))).getOrElse( 14 | throw new IllegalStateException("Please add a github key as an environment variable named [GITHUB_KEY].")) 15 | 16 | case class Repo(id: Int, name: String, url: String, description: String, forks: Int, stars: Int, watchers: Int, size: Int) { 17 | val key = name.stripPrefix("scala-js-") 18 | } 19 | 20 | def repoFromObj(repo: Map[String, Json]) = { 21 | val id = repo("id").asNumber.get.toInt.get 22 | val name = repo("name").asString.get 23 | val url = repo("html_url").asString.get 24 | val description = repo.get("description").map(_.asString.get).getOrElse("") 25 | val forks = repo("forks_count").asNumber.get.toInt.get 26 | val stars = repo("stargazers_count").asNumber.get.toInt.get 27 | val watchers = repo("watchers_count").asNumber.get.toInt.get 28 | val size = repo("size").asNumber.get.toInt.get 29 | GithubService.Repo(id, name, url, description, forks, stars, watchers, size) 30 | } 31 | } 32 | 33 | @javax.inject.Singleton 34 | case class GithubService @javax.inject.Inject() (ws: WSClient) { 35 | private[this] val pageSize = 100 36 | 37 | def test() = detail("scala-js-template").map { result => 38 | result.toString 39 | } 40 | 41 | def listRepos(includeTemplates: Boolean = false) = { 42 | fullList().map { repos => 43 | val filtered = if (includeTemplates) { 44 | repos 45 | } else { 46 | repos.filterNot(r => r.name == "scala-js-template" || r.name == "definitelyscala.com") 47 | } 48 | filtered.sortBy(_.name) 49 | } 50 | } 51 | 52 | private[this] def fullList(prior: Seq[GithubService.Repo] = Nil, page: Int = 1): Future[Seq[GithubService.Repo]] = { 53 | val r = req(s"orgs/DefinitelyScala/repos?page=$page&per_page=$pageSize") 54 | val ret = trap(r, r.get()) { rsp => 55 | getArray(rsp).map { 56 | case repo: Json => GithubService.repoFromObj(repo.asObject.get.toMap) 57 | case _ => throw new IllegalStateException() 58 | }.sortBy(_.name).reverse 59 | } 60 | ret.flatMap { 61 | case repos if repos.size < pageSize => Future.successful(prior ++ repos) 62 | case repos => fullList(prior ++ repos, page + 1) 63 | } 64 | } 65 | 66 | def detail(key: String) = { 67 | val withPrefix = if (key.startsWith("scala-js-")) { key } else { "scala-js-" + key } 68 | val r = req(s"repos/DefinitelyScala/$withPrefix") 69 | trap(r, r.get)(x => GithubService.repoFromObj(getObject(x).toMap)).map(Some(_)).recoverWith { 70 | case NonFatal(x) => Future.successful(None) 71 | } 72 | } 73 | 74 | def create(key: String, description: String) = { 75 | val json = Json.obj("name" -> key.asJson, "description" -> description.asJson, "has_wiki" -> false.asJson) 76 | val r = req("orgs/DefinitelyScala/repos") 77 | trap(r, r.post(json.spaces2)) { x => 78 | GithubService.repoFromObj(getObject(x).toMap) 79 | } 80 | } 81 | 82 | private[this] def getArray(rsp: WSResponse) = parseJson(rsp.body).right.get.asArray.get 83 | private[this] def getObject(rsp: WSResponse) = parseJson(rsp.body).right.get.asObject.get 84 | 85 | private[this] def req(page: String) = { 86 | val url = GithubService.baseUrl + page 87 | ws.url(url).withAuth("KyleU", GithubService.accessKey, WSAuthScheme.BASIC).withHttpHeaders( 88 | "User-Agent" -> "scala-js-typescript") 89 | } 90 | 91 | private[this] def trap[T](req: WSRequest, rsp: Future[WSResponse])(f: WSResponse => T) = rsp.map { response => 92 | try { 93 | if (response.status >= 200 && response.status < 300) { 94 | f(response) 95 | } else { 96 | throw new IllegalStateException(s"Received [${response.status}] response from [${req.method}] request to [${req.url}].") 97 | } 98 | } catch { 99 | case NonFatal(x) => 100 | val msg = s"Error encountered for [${req.url}]:\n${x.getClass.getSimpleName}: ${x.getMessage}\nResponse: ${response.body}" 101 | throw new IllegalStateException(msg) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/services/parse/ClassReferenceService.scala: -------------------------------------------------------------------------------- 1 | package services.parse 2 | 3 | import utils.Logging 4 | 5 | object ClassReferenceService extends Logging { 6 | private[this] val files = Seq( 7 | ("scala.scalajs.js", Seq("package.scala"), Seq("@js.native")), 8 | 9 | ("com.definitelyscala.jqueryui.JQuery", Seq("jqueryui/JQueryUI/"), Seq(" JQuery")), 10 | 11 | ("com.definitelyscala.less.LessStatic", Seq("less/Less/"), Seq("LessStatic")), 12 | 13 | ("com.definitelyscala.awssdk._", Seq( 14 | "/AutoScaling/", "/SQS/", "/SES/", "/sts/", "/sts/"), Seq("ClientConfig", "Credentials", "Tags", "BlockDeviceMapping", "StepAdjustment")), 15 | 16 | ("com.definitelyscala.pixijs._", Seq( 17 | "/accessibility", "/CanvasTinter", "/core", "/extras", "/extract", "/filters", "/glCore", "/GroupD8", "/interaction", "/loaders", 18 | "/mesh", "/particles", "/prepare", "/utils", "pixijs/package.scala"), Seq( 19 | "CanvasRenderer", "Container", "DisplayObject", " Filter", "IDecomposedDataUri", "IHitArea", 20 | " Matrix", "ObjectRenderer", "Point", " Texture", "[Texture", "WebGLRenderer", "WebGLState")), 21 | ("com.definitelyscala.pixijs.extras._", Seq("pixijs/package.scala"), Seq("@js.native")), 22 | ("com.definitelyscala.pixijs.glCore._", Seq("pixijs/package.scala"), Seq("@js.native")), 23 | 24 | ("com.definitelyscala.asciify._", Seq("Asciify.scala"), Seq("AsciifyCallback")), 25 | 26 | ("com.definitelyscala.react.React._", Seq("/react"), Seq("ReactNode", "Ref[T]", "CSSWideKeyword")), 27 | 28 | ("com.definitelyscala.phaser._", Seq("/Physics/", "/Particles/", "/Plugin/", "/Utils/", "/Filter/"), Seq( 29 | "Physics.", "Particles.", " Plugin", " Game", " Filter")), 30 | ("com.definitelyscala.phaserp2._", Seq("/Physics/P2"), Seq("p2.")), 31 | 32 | ("com.definitelyscala.materializecss.Materialize._", Seq("/Materialize"), Seq("options: CollapsibleOptions")), 33 | 34 | ("com.definitelyscala.node.NodeJS._", Seq("node/"), Seq("ReadWriteStream")), 35 | ("com.definitelyscala.node.crypto.Crypto._", Seq("node/"), Seq("Utf8AsciiBinaryEncoding", "HexBase64Latin1Encoding", "ECDHKeyFormat")), 36 | ("com.definitelyscala.node.NodeJS", Seq("node/"), Seq("NodeJS.")), 37 | ("com.definitelyscala.node.net", Seq("node/"), Seq("extends net.")), 38 | ("com.definitelyscala.node.events.{ internal => events }", Seq("node/"), Seq(" events.")), 39 | ("com.definitelyscala.node.http", Seq("node/"), Seq(" http.")), 40 | ("com.definitelyscala.node.net", Seq("node/"), Seq(" net.")), 41 | ("com.definitelyscala.node.readline", Seq("node/"), Seq(" readline.")), 42 | ("com.definitelyscala.node.stream.{ internal => stream }", Seq("node/"), Seq("extends stream.")), 43 | ("com.definitelyscala.node.tls", Seq("node/"), Seq(" tls.")), 44 | ("com.definitelyscala.node.ErrnoException", Seq("node/"), Seq("ErrnoException")), 45 | ("com.definitelyscala.node.WritableStream", Seq("node/"), Seq("WritableStream")), 46 | ("com.definitelyscala.node.path.ParsedPath", Seq("node/"), Seq("ParsedPath")), 47 | ("com.definitelyscala.node.v8.V8.DoesZapCodeSpaceFlag", Seq("node/"), Seq("DoesZapCodeSpaceFlag"))) 48 | 49 | private[this] val refs = Seq( 50 | "org.scalajs.dom.raw._" -> Seq( 51 | " HTMLElement", " Event", "[Event", " Element", "[Element", "HTMLImageElement", "HTMLCanvasElement", "HTMLVideoElement", 52 | "WebGLRenderingContext", "CanvasPattern", "WebGLBuffer", "CanvasRenderingContext2D", "XMLHttpRequest", "SVGPathElement", "StyleMedia", 53 | "SVGElement", "DataTransfer", " Node", "WebGLFramebuffer", "MouseEvent", "KeyboardEvent"), 54 | "com.definitelyscala.node.Buffer" -> Seq(": Buffer"), 55 | "scala.scalajs.js.|" -> Seq(" | "), 56 | "scala.scalajs.js.Date" -> Seq(": Date", " Date "), 57 | "org.scalajs.dom.raw.Blob" -> Seq(" Blob "), 58 | "org.scalajs.css.Css.AtRule" -> Seq(" AtRule"), 59 | "scala.scalajs.js.typedarray._" -> Seq(" ArrayBuffer", "Uint32Array", "Float32Array", "Uint16Array", "Uint8Array"), 60 | "scala.scalajs.js.Promise" -> Seq(" Promise")) 61 | 62 | def insertImports(path: String, content: Seq[String]) = { 63 | var importIdx = content.indexOf("import scala.scalajs.js") 64 | if (importIdx < 0) { 65 | importIdx = 0 66 | } 67 | val fileImports = importsForPath(path, content).map("import " + _) 68 | val contentImports = importsForContent(content).map("import " + _) 69 | content.take(importIdx + 1) ++ fileImports ++ contentImports ++ content.drop(importIdx + 1) 70 | } 71 | 72 | private[this] def importsForContent(content: Seq[String]) = refs.flatMap { ref => 73 | if (ref._2.exists(key => content.exists(_.contains(key)))) { 74 | Some(ref._1) 75 | } else { 76 | None 77 | } 78 | } 79 | 80 | private[this] def importsForPath(path: String, content: Seq[String]) = files.flatMap { file => 81 | val fileMatch = file._2.exists(key => path.contains(key)) 82 | if (fileMatch && file._3.exists(key => content.exists(_.contains(key)))) { 83 | Some(file._1) 84 | } else { 85 | None 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/services/parse/PrinterService.scala: -------------------------------------------------------------------------------- 1 | package services.parse 2 | 3 | import models.parse.{ Importer, ProjectDefinition } 4 | import models.parse.parser.tree.{ DeclTree, LineCommentDecl } 5 | import models.parse.sc.printer.{ Printer, PrinterFiles, PrinterFilesMulti } 6 | import models.parse.sc.transform.IgnoredPackages 7 | import services.project.ProjectService 8 | 9 | case class PrinterService(key: String, t: List[DeclTree]) { 10 | private[this] val ignoredPackages = IgnoredPackages.forKey(key) 11 | 12 | def export() = { 13 | val (proj, decls) = extractFrom(key, t) 14 | // exportSingle(key, proj.keyNormalized, decls) 15 | exportMulti(proj, decls) 16 | } 17 | 18 | private[this] def exportMulti(project: ProjectDefinition, decls: List[DeclTree]) = { 19 | import utils.JsonSerializers._ 20 | val outDir = ProjectService.outDirFor(key) 21 | val multi = PrinterFilesMulti(key, project.keyNormalized, outDir) 22 | val ret = printer(multi, decls) 23 | 24 | val outJson = outDir / "project.json" 25 | outJson.createIfNotExists() 26 | outJson.append(project.asJson.spaces2) 27 | ret 28 | } 29 | 30 | private[this] def extractFrom(key: String, t: List[DeclTree]) = { 31 | val comments = t.flatMap { 32 | case c: LineCommentDecl => Some(c.text.trim) 33 | case _ => None 34 | } 35 | val (nameLine, name, version) = comments.find(_.startsWith("Type definitions for")) match { 36 | case Some(l) => 37 | val str = l.substring("Type definitions for".length + 1).trim.split(' ').map(_.trim) 38 | val version = str.last 39 | if (version.exists(_.isDigit)) { 40 | (l, str.dropRight(1).mkString(" ").trim, str.last) 41 | } else { 42 | (l, str.mkString(" ").trim, "") 43 | } 44 | case None => ("UNKNOWN", key, "0.1") 45 | } 46 | val cleanName = if (name.isEmpty) { key } else { name } 47 | val (urlLine, url) = comments.find(_.startsWith("Project:")) match { 48 | case Some(l) => l -> l.substring("Project:".length + 1).trim 49 | case None => "" -> key 50 | } 51 | val (authorsLine, authors) = comments.find(_.startsWith("Definitions by:")) match { 52 | case Some(l) => l -> l.substring("Definitions by:".length).trim 53 | case _ => "" -> key 54 | } 55 | val buildVersion = "1.1.0" 56 | val defsLine = comments.find(_.startsWith("Definitions:")) match { 57 | case Some(l) => l 58 | case None => "" 59 | } 60 | val dependencies = comments.filter(_.contains(" 61 | dep.split('\"').toList match { 62 | case _ :: x :: _ :: Nil => ProjectDefinition.normalize(x) 63 | case _ => dep.split('\'').toList match { 64 | case _ :: x :: _ :: Nil => ProjectDefinition.normalize(x) 65 | case _ => throw new IllegalStateException(s"Invalid reference [$dep].") 66 | } 67 | } 68 | } 69 | 70 | val p = ProjectDefinition(key, cleanName, url, version, authors, buildVersion, dependencies) 71 | val trimmedLines = Seq(nameLine, urlLine, authorsLine, defsLine) 72 | 73 | val remaining = t.filter { 74 | case c: LineCommentDecl => !trimmedLines.contains(c.text.trim) 75 | case _ => true 76 | } 77 | 78 | p -> remaining 79 | } 80 | 81 | private[this] def printer(files: PrinterFiles, decls: List[DeclTree]) = { 82 | val pkg = Importer(key)(decls) 83 | new Printer(files, key, ignoredPackages).printSymbol(pkg, fancy = false) 84 | files.onComplete() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/services/parse/TypeScriptFiles.scala: -------------------------------------------------------------------------------- 1 | package services.parse 2 | 3 | import java.nio.charset.MalformedInputException 4 | 5 | import better.files._ 6 | import models.parse.ProjectDefinition 7 | 8 | object TypeScriptFiles { 9 | private[this] val source = "data" / "typescript" 10 | if (!source.exists) { 11 | source.createDirectory() 12 | } 13 | 14 | private[this] val originalFiles = "typescript" / "DefinitelyTyped" / "types" 15 | private[this] val overrideFiles = "typescript" / "DefinitelyScala" 16 | 17 | def copy() = { 18 | val original = originalFiles.list.filter(_.isDirectory).toSeq.map(_.name) 19 | val over = overrideFiles.list.filter(_.isRegularFile).toSeq.map(_.name.stripSuffix(".ts")).filterNot(_.startsWith(".")) 20 | val keys = (original ++ over).distinct.sorted 21 | 22 | source.delete(swallowIOExceptions = true) 23 | source.createDirectories() 24 | 25 | var skipped = 0 26 | 27 | keys.foreach { key => 28 | val normalized = ProjectDefinition.normalize(key) 29 | 30 | val src = if ((overrideFiles / s"$normalized.ts").exists) { 31 | overrideFiles / s"$normalized.ts" 32 | } else { 33 | originalFiles / key / "index.d.ts" 34 | } 35 | 36 | if (!src.exists) { 37 | throw new IllegalStateException(s"Cannot read [${src.path}].") 38 | } 39 | 40 | val out = source / s"$normalized.ts" 41 | if (out.exists) { 42 | skipped += 1 43 | out.delete() 44 | } 45 | 46 | val lines = try { 47 | src.lines 48 | } catch { 49 | case x: MalformedInputException => Nil // throw new IllegalStateException(s"Failed to read [${src.pathAsString}].", x) } 50 | } 51 | out.write(lines.mkString("\n")) 52 | } 53 | 54 | keys.size -> skipped 55 | } 56 | 57 | def list(q: Option[String]) = { 58 | source.list.filter(_.name.contains(q.getOrElse(""))).toSeq.map(_.name.stripSuffix(".ts")).sorted 59 | } 60 | 61 | def getContent(key: String) = { 62 | (source / (key + ".ts")).contentAsString 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/services/parse/TypeScriptImport.scala: -------------------------------------------------------------------------------- 1 | package services.parse 2 | 3 | import models.parse.parser.TSDefParser 4 | import models.parse.parser.tree.DeclTree 5 | 6 | import scala.util.parsing.input.CharSequenceReader 7 | 8 | object TypeScriptImport { 9 | def parse(s: String): Either[String, scala.List[DeclTree]] = { 10 | val parser = new TSDefParser() 11 | 12 | parser.parseDefinitions(new CharSequenceReader(s, 0)) match { 13 | case parser.Success(rawCode: List[models.parse.parser.tree.DeclTree], _) => Right(rawCode) 14 | 15 | case parser.NoSuccess(msg, next) => 16 | val m = s"Parse error at ${next.pos.toString}:" + "\n " + msg + "\n Position: " + next.pos.longString 17 | Left(m) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/services/project/ProjectDetailsService.scala: -------------------------------------------------------------------------------- 1 | package services.project 2 | 3 | import models.parse.ProjectDefinition 4 | import services.file.FileService 5 | import services.github.GithubService 6 | import services.parse.TypeScriptFiles 7 | import services.sbt.SbtHistoryService 8 | 9 | object ProjectDetailsService { 10 | case class Details(key: String, keyNormal: String, parsed: Boolean, project: Boolean, built: Boolean, repo: Boolean, github: Boolean) 11 | 12 | def getAll(q: Option[String], filter: Option[String], repos: Seq[GithubService.Repo] = Nil) = { 13 | val srcDirs = TypeScriptFiles.list(q) 14 | val outDirs = FileService.getDir("out").list.filter(_.isDirectory).filter(_.name.contains(q.getOrElse(""))).toSeq.map(_.name) 15 | val projectDirs = FileService.getDir("projects").list.filter(_.isDirectory).filter(_.name.contains(q.getOrElse("scala-js-" + ""))).toSeq 16 | val buildStatus = SbtHistoryService.statuses().toMap 17 | 18 | val keys = srcDirs.sorted.map(x => x -> ProjectDefinition.normalize(x)) 19 | 20 | val filteredKeys = filter match { 21 | case None => keys 22 | case Some("all") => keys 23 | case Some("parsed") => keys.filter(k => outDirs.contains(k._1)) 24 | case Some("project") => keys.filter(k => projectDirs.exists(d => d.name == ("scala-js-" + k._2))) 25 | case Some("built") => keys.filter(k => buildStatus.get(k._2).contains(true)) 26 | case Some("repo") => keys.filter(k => projectDirs.exists(d => d.name == ("scala-js-" + k._2) && (d / ".git").exists)) 27 | case Some("norepo") => keys.filter(k => buildStatus.get(k._2).contains(true) && projectDirs.exists(d => d.name == ("scala-js-" + k._2) && (!(d / ".git").exists))) 28 | case Some("published") => keys.filter(k => repos.exists(_.name == ("scala-js-" + k._2))) 29 | case Some(x) => throw new IllegalStateException(s"Invalid filter [$x].") 30 | } 31 | 32 | filteredKeys.map { key => 33 | val parsed = outDirs.contains(key._1) 34 | val projectDir = projectDirs.find(_.name == "scala-js-" + key._2) 35 | val project = projectDir.isDefined 36 | val built = buildStatus.getOrElse(key._2, false) 37 | val repo = projectDir.exists(x => (x / ".git").exists) 38 | val github = repos.exists(_.name == ("scala-js-" + models.parse.ProjectDefinition.normalize(key._2))) 39 | Details(key._1, key._2, parsed, project, built, repo, github) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/services/project/ProjectOutput.scala: -------------------------------------------------------------------------------- 1 | package services.project 2 | 3 | import better.files._ 4 | import models.parse.ProjectDefinition 5 | import utils.Logging 6 | 7 | case class ProjectOutput(project: ProjectDefinition, projectDir: File) extends Logging { 8 | def scalaRoot = projectDir / "src" / "main" / "scala" / "com" / "definitelyscala" / project.keyNormalized 9 | 10 | def exists() = projectDir.exists() 11 | 12 | def create(rebuild: Boolean) = { 13 | if (rebuild) { 14 | log.info(s"Creating project [${project.key}].") 15 | } else { 16 | log.info(s"Updating project [${project.key}].") 17 | } 18 | val dir = copyFiles(rebuild) 19 | replaceStrings(dir) 20 | val srcRoot = scalaRoot 21 | if (srcRoot.exists && !srcRoot.isDirectory) { 22 | throw new IllegalStateException(s"Invalid [$srcRoot].") 23 | } 24 | 25 | scalaRoot.createDirectories() 26 | scalaRoot 27 | } 28 | 29 | private[this] def copyFiles(rebuild: Boolean) = { 30 | val src = "util" / "scala-js-template" 31 | val dest = projectDir 32 | if (rebuild && dest.exists) { 33 | dest.delete() 34 | } 35 | dest.createIfNotExists(asDirectory = true) 36 | 37 | src.children.map { child => 38 | if (child.name != ".git") { 39 | child.copyTo(dest / child.name, overwrite = true) 40 | } 41 | }.toList 42 | 43 | (dest / ".DS_Store").delete(swallowIOExceptions = true) 44 | (dest / "readme.md").delete() 45 | (dest / "template.readme.md").renameTo("readme.md") 46 | dest 47 | } 48 | 49 | private[this] def replaceStrings(dir: File) = { 50 | val files = Seq(dir / "build.sbt", dir / "readme.md", dir / "project" / "Projects.scala") 51 | val replacements = project.asMap 52 | def replace(f: File) = { 53 | val oldContent = f.contentAsString 54 | val newContent = replacements.foldLeft(oldContent) { (content, r) => 55 | content.replaceAllLiterally("${" + r._1 + "}", r._2).replaceAllLiterally("// $" + r._1, r._2).replaceAllLiterally("$" + r._1, r._2) 56 | }.replaceAllLiterally("PROJNAME", replacements("keyNormalized")).replaceAllLiterally("/* PROJDEPS */", replacements("dependencies")) 57 | if (oldContent != newContent) { 58 | f.delete() 59 | f.write(newContent) 60 | } 61 | } 62 | 63 | files.foreach(replace) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/services/project/ProjectService.scala: -------------------------------------------------------------------------------- 1 | package services.project 2 | 3 | import models.parse.ProjectDefinition 4 | import services.file.FileService 5 | 6 | object ProjectService { 7 | def outDirFor(key: String) = { 8 | val out = FileService.getDir("out") 9 | out.children.find(x => ProjectDefinition.normalize(x.name) == key).getOrElse(out / key) 10 | } 11 | 12 | private[this] val dir = FileService.getDir("projects") 13 | 14 | def list(q: Option[String]) = dir.list.filter(_.isDirectory).filter(_.name.contains(q.getOrElse(""))).toSeq.sortBy(_.name) 15 | 16 | def projectDir(key: String) = { 17 | dir / ("scala-js-" + ProjectDefinition.normalize(key)) 18 | } 19 | } 20 | 21 | case class ProjectService(key: String) { 22 | val outDir = FileService.getDir("out") / key 23 | 24 | if (!outDir.exists) { 25 | throw new IllegalStateException(s"Missing out dir [$outDir].") 26 | } 27 | 28 | private[this] def updateProject(project: ProjectDefinition) = { 29 | val proj = ProjectOutput(project, ProjectService.projectDir(project.key)) 30 | val created = !proj.exists() 31 | val projectSrcDir = proj.create(rebuild = created) 32 | 33 | projectSrcDir.delete() 34 | projectSrcDir.createDirectory() 35 | 36 | outDir.copyTo(projectSrcDir) 37 | 38 | (projectSrcDir / "project.json").delete() 39 | created 40 | } 41 | 42 | def update() = updateProject(ProjectDefinition.fromJson(outDir)) 43 | } 44 | -------------------------------------------------------------------------------- /app/services/sbt/SbtHistoryService.scala: -------------------------------------------------------------------------------- 1 | package services.sbt 2 | 3 | import services.file.FileService 4 | import utils.DateUtils 5 | 6 | object SbtHistoryService { 7 | private[this] val root = FileService.getDir("logs") / "history" 8 | if (!root.exists) { 9 | root.createDirectories() 10 | } 11 | private[this] val logDir = FileService.getDir("logs") / "sbt" 12 | if (!logDir.exists) { 13 | logDir.createDirectories() 14 | } 15 | 16 | def list() = root.children.map(_.name.stripSuffix(".csv")).toSeq.sorted 17 | 18 | def statuses() = { 19 | val projects = logDir.list.filter(_.isRegularFile).toSeq 20 | projects.map { p => 21 | val content = p.contentAsString 22 | (p.name.stripPrefix("scala-js-").stripSuffix(".log"), !content.contains("[error]")) 23 | } 24 | } 25 | 26 | def status(key: String) = { 27 | val f = logDir / s"scala-js-$key.log" 28 | if (f.exists) { 29 | f 30 | } else { 31 | throw new IllegalStateException(s"No build history for [$key] (${f.path}).") 32 | } 33 | } 34 | 35 | def write() = { 36 | val file = root / (DateUtils.now.toString("yyyy-MM-dd HH:mm:ss") + ".csv") 37 | val data = statuses().sortBy(_._1) 38 | val content = data.map(x => x._1.stripPrefix("scala-js-").stripSuffix(".log") + "," + x._2).mkString("\n") 39 | file.write(content) 40 | } 41 | 42 | def read(key: String) = { 43 | val file = root / (key + ".csv") 44 | if (!file.exists) { 45 | throw new IllegalStateException(s"Missing file [${file.path}].") 46 | } 47 | file.lines.toSeq.filterNot(_.isEmpty).map { line => 48 | val split = line.split(',').toList 49 | split match { 50 | case one :: two :: Nil => one -> two.toBoolean 51 | case _ => throw new IllegalStateException(s"Invalid line [$line].") 52 | } 53 | } 54 | } 55 | 56 | def delete(key: String) = { 57 | val file = root / (key + ".csv") 58 | if (!file.exists) { 59 | throw new IllegalStateException(s"Missing file to delete [${file.path}].") 60 | } 61 | file.delete() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/services/sbt/SbtResultParser.scala: -------------------------------------------------------------------------------- 1 | package services.sbt 2 | 3 | import better.files._ 4 | 5 | object SbtResultParser { 6 | case class Error(content: String) 7 | 8 | case class Result(key: String, infoLines: Seq[(String, Int)], errorLines: Seq[(String, Int)], errors: Seq[Error]) { 9 | val success = errors.isEmpty 10 | } 11 | 12 | private[this] def linesFor(lines: Array[(String, Int)], tag: String) = { 13 | lines.filter(_._1.startsWith(tag)).map(x => x._1.stripPrefix(tag).replaceAllLiterally("^", "").trim -> x._2).filter(_._1.nonEmpty) 14 | } 15 | 16 | private[this] def parseErrors(lines: Array[(String, Int)]) = if (lines.isEmpty) { 17 | Array.empty[Error] 18 | } else { 19 | lines.zipWithIndex.flatMap { 20 | case ((line, lineNum), arrayIdx) => line match { 21 | case _ if line.contains(".scala") => 22 | val trimmed = line.substring(line.indexOf("/com") + 1) 23 | val others = lines.drop(arrayIdx + 1).takeWhile(x => (!x._1.contains(".scala")) && (!x._1.contains(" found"))) 24 | Some(Error(trimmed + "\n" + others.map(" " + _._1).mkString("\n"))) 25 | case _ => None 26 | } 27 | } 28 | } 29 | 30 | def parse(f: File) = { 31 | val key = f.name.stripPrefix("scala-js-").stripSuffix(".log") 32 | 33 | val lines = f.lines.toArray.zipWithIndex 34 | 35 | val infoLines = linesFor(lines, "[info] ") 36 | val errorLines = linesFor(lines, "[error] ") 37 | 38 | val errors = parseErrors(errorLines) 39 | Result(key, infoLines, errorLines, errors) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/services/sbt/SbtService.scala: -------------------------------------------------------------------------------- 1 | package services.sbt 2 | 3 | import better.files._ 4 | import services.file.FileService 5 | import utils.{ DateUtils, Logging } 6 | 7 | object SbtService extends Logging { 8 | def clean(dir: File) = if (dir.exists) { 9 | sbt(dir, "clean") 10 | } else { 11 | throw new IllegalStateException(s"No SBT project available for [${dir.name}].") 12 | } 13 | 14 | def format(dir: File) = if (dir.exists) { 15 | sbt(dir, "scalariformFormat") 16 | } else { 17 | throw new IllegalStateException(s"No SBT project available for [${dir.name}].") 18 | } 19 | 20 | def build(dir: File) = if (dir.exists) { 21 | sbt(dir, "+clean", "+compile", "+doc", "+publishLocal") 22 | } else { 23 | throw new IllegalStateException(s"No SBT project available for [${dir.name}].") 24 | } 25 | 26 | def publish(dir: File) = { 27 | if (dir.exists) { 28 | sbt(dir, "+publish") 29 | } else { 30 | throw new IllegalStateException(s"No SBT project available for [${dir.name}].") 31 | } 32 | } 33 | 34 | private[this] def sbt(dir: File, cmd: String*) = { 35 | call(dir, Seq("sbt", "-no-colors") ++ cmd) 36 | } 37 | 38 | private[this] def call(dir: File, cmd: Seq[String]) = { 39 | log.info(s"Running build for [${dir.name}] with arguments [${cmd.mkString(", ")}]...") 40 | val startMs = System.currentTimeMillis 41 | val logDir = FileService.getDir("logs") / "sbt" 42 | if (!logDir.exists) { 43 | logDir.createDirectory 44 | } 45 | val f = logDir / (dir.name + ".log") 46 | if (f.exists) { 47 | f.delete() 48 | } 49 | f.appendText(s"Scala.js Build Started [${DateUtils.niceDateTime(DateUtils.now)}]\n") 50 | val result = new ProcessBuilder().directory(dir.toJava).command(cmd: _*).redirectError(f.toJava).redirectOutput(f.toJava).start().waitFor() 51 | log.info(s"Build completed in [${System.currentTimeMillis - startMs}ms] with result [$result] for [${dir.name}].") 52 | result -> f.contentAsString 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/utils/Application.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import java.util.TimeZone 4 | 5 | import org.joda.time.DateTimeZone 6 | import play.api.Environment 7 | import play.api.inject.ApplicationLifecycle 8 | import play.api.libs.ws.WSClient 9 | import services.file.FileService 10 | 11 | import scala.concurrent.Future 12 | 13 | object Application { 14 | var initialized = false 15 | } 16 | 17 | @javax.inject.Singleton 18 | class Application @javax.inject.Inject() ( 19 | val config: Config, 20 | val lifecycle: ApplicationLifecycle, 21 | val playEnv: Environment, 22 | val ws: WSClient) extends Logging { 23 | if (Application.initialized) { 24 | log.info("Skipping initialization after failure.") 25 | } else { 26 | start() 27 | } 28 | 29 | private[this] def start() = { 30 | log.info(s"${Config.projectName} is starting.") 31 | Application.initialized = true 32 | 33 | DateTimeZone.setDefault(DateTimeZone.UTC) 34 | TimeZone.setDefault(TimeZone.getTimeZone("UTC")) 35 | 36 | lifecycle.addStopHook(() => Future.successful(stop())) 37 | 38 | FileService.setRootDir(config.dataDir) 39 | } 40 | 41 | private[this] def stop() = {} 42 | } 43 | -------------------------------------------------------------------------------- /app/utils/Config.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import play.api.{ Environment, Mode } 4 | 5 | object Config { 6 | val projectId = "scala-js-typescript" 7 | val projectName = "scala-js-typescript" 8 | val projectUrl = "https://github.com/KyleU/scala-js-typescript" 9 | val adminEmail = "scala-js-typescript@kyleu.com" 10 | val version = "0.1" 11 | val pageSize = 100 12 | } 13 | 14 | @javax.inject.Singleton 15 | class Config @javax.inject.Inject() (val cnf: play.api.Configuration, env: Environment) { 16 | val debug = env.mode == Mode.Dev 17 | val dataDir = { 18 | import better.files._ 19 | cnf.get[Option[String]]("data.directory").getOrElse("./data").toFile 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/utils/DateUtils.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import java.text.SimpleDateFormat 4 | 5 | import org.joda.time._ 6 | 7 | object DateUtils { 8 | private[this] val fmt = org.joda.time.format.ISODateTimeFormat.dateTime() 9 | 10 | implicit def localDateOrdering: Ordering[LocalDate] = Ordering.fromLessThan(_ isBefore _) 11 | implicit def localDateTimeOrdering: Ordering[LocalDateTime] = Ordering.fromLessThan(_ isBefore _) 12 | 13 | def today = DateTime.now(DateTimeZone.UTC).toLocalDate 14 | 15 | def now = DateTime.now(DateTimeZone.UTC).toLocalDateTime 16 | def nowMillis = toMillis(now) 17 | 18 | def toMillis(ldt: LocalDateTime) = ldt.toDateTime(DateTimeZone.UTC).getMillis 19 | def fromMillis(millis: Long) = new LocalDateTime(millis, DateTimeZone.UTC) 20 | 21 | def toIsoString(ldt: LocalDateTime) = fmt.print(ldt.toDateTime) 22 | 23 | def niceDate(d: LocalDate) = d.toString("EEEE, MMM dd, yyyy") 24 | def niceTime(d: LocalTime) = d.toString("HH:mm:ss") 25 | def niceDateTime(dt: LocalDateTime) = s"${niceDate(dt.toLocalDate)} ${niceTime(dt.toLocalTime)} UTC" 26 | 27 | private[this] val dFmt = new SimpleDateFormat("yyyy-MM-dd") 28 | def sqlDateFromString(s: String) = new java.sql.Date(dFmt.parse(s).getTime) 29 | 30 | private[this] val tFmt = new SimpleDateFormat("hh:mm:ss") 31 | def sqlTimeFromString(s: String) = new java.sql.Time(tFmt.parse(s).getTime) 32 | 33 | private[this] val dtFmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss") 34 | def sqlDateTimeFromString(s: String) = new java.sql.Timestamp(dtFmt.parse(s).getTime) 35 | } 36 | -------------------------------------------------------------------------------- /app/utils/JsonSerializers.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import java.time.{ LocalDate, LocalDateTime, LocalTime, ZonedDateTime } 4 | 5 | import io.circe.generic.extras.Configuration 6 | import io.circe.generic.extras.decoding.ConfiguredDecoder 7 | import io.circe.generic.extras.encoding.ConfiguredObjectEncoder 8 | import io.circe.java8.time._ 9 | import shapeless.Lazy 10 | 11 | import scala.language.implicitConversions 12 | 13 | object JsonSerializers { 14 | type Decoder[A] = io.circe.Decoder[A] 15 | type Encoder[A] = io.circe.Encoder[A] 16 | 17 | type Json = io.circe.Json 18 | 19 | implicit def encodeZonedDateTime: Encoder[ZonedDateTime] = io.circe.java8.time.encodeZonedDateTimeDefault 20 | implicit def encodeLocalDateTime: Encoder[LocalDateTime] = io.circe.java8.time.encodeLocalDateTimeDefault 21 | implicit def encodeLocalDate: Encoder[LocalDate] = io.circe.java8.time.encodeLocalDateDefault 22 | implicit def encodeLocalTime: Encoder[LocalTime] = io.circe.java8.time.encodeLocalTimeDefault 23 | 24 | implicit def decodeZonedDateTime: Decoder[ZonedDateTime] = io.circe.java8.time.decodeZonedDateTimeDefault 25 | implicit def decodeLocalDateTime: Decoder[LocalDateTime] = io.circe.java8.time.decodeLocalDateTimeDefault 26 | implicit def decodeLocalDate: Decoder[LocalDate] = io.circe.java8.time.decodeLocalDateDefault 27 | implicit def decodeLocalTime: Decoder[LocalTime] = io.circe.java8.time.decodeLocalTimeDefault 28 | 29 | implicit val circeConfiguration: Configuration = Configuration.default.withDefaults 30 | 31 | def deriveDecoder[A](implicit decode: Lazy[ConfiguredDecoder[A]]) = io.circe.generic.extras.semiauto.deriveDecoder[A] 32 | def deriveEncoder[A](implicit decode: Lazy[ConfiguredObjectEncoder[A]]) = io.circe.generic.extras.semiauto.deriveEncoder[A] 33 | def deriveFor[A](implicit decode: Lazy[ConfiguredDecoder[A]]) = io.circe.generic.extras.semiauto.deriveFor[A] 34 | 35 | implicit def encoderOps[A](a: A): io.circe.syntax.EncoderOps[A] = io.circe.syntax.EncoderOps[A](a) 36 | def parseJson(s: String) = io.circe.parser.parse(s) 37 | def decodeJson[A](s: String)(implicit decoder: Decoder[A]) = io.circe.parser.decode[A](s) 38 | 39 | def extract[T: Decoder](json: Json) = json.as[T] match { 40 | case Right(u) => u 41 | case Left(x) => throw x 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/utils/Logging.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import org.slf4j.LoggerFactory 4 | 5 | trait Logging { 6 | protected[this] val log = LoggerFactory.getLogger(s"${utils.Config.projectId}.${this.getClass.getSimpleName.replace("$", "")}") 7 | } 8 | -------------------------------------------------------------------------------- /app/utils/NumberUtils.scala: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | object NumberUtils { 4 | private[this] val numFormatter = java.text.NumberFormat.getNumberInstance(java.util.Locale.US) 5 | 6 | def withCommas(i: Int) = numFormatter.format(i.toLong) 7 | def withCommas(l: Long) = numFormatter.format(l) 8 | def withCommas(d: Double) = numFormatter.format(d) 9 | 10 | def toWords(i: Int, properCase: Boolean = false) = { 11 | val ret = i match { 12 | case 0 => "zero" 13 | case 1 => "one" 14 | case 2 => "two" 15 | case 3 => "three" 16 | case 4 => "four" 17 | case 5 => "five" 18 | case 6 => "six" 19 | case 7 => "seven" 20 | case 8 => "eight" 21 | case 9 => "nine" 22 | case 10 => "ten" 23 | case 11 => "eleven" 24 | case 12 => "twelve" 25 | case _ => i.toString 26 | } 27 | if (properCase) { 28 | ret.head.toUpper + ret.tail 29 | } else { 30 | ret 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/utils/web/ErrorHandler.scala: -------------------------------------------------------------------------------- 1 | package utils.web 2 | 3 | import javax.inject._ 4 | 5 | import play.api.http.DefaultHttpErrorHandler 6 | import play.api._ 7 | import play.api.mvc._ 8 | import play.api.routing.Router 9 | import utils.Logging 10 | import scala.concurrent._ 11 | 12 | class ErrorHandler @Inject() ( 13 | env: Environment, config: Configuration, sourceMapper: OptionalSourceMapper, router: Provider[Router]) extends DefaultHttpErrorHandler(env, config, sourceMapper, router) with Logging { 14 | 15 | override def onProdServerError(request: RequestHeader, ex: UsefulException) = Future.successful( 16 | Results.InternalServerError(views.html.error.serverError(request.path, Some(ex))(request.session, request.flash))) 17 | 18 | override def onClientError(request: RequestHeader, statusCode: Int, message: String) = Future.successful( 19 | Results.NotFound(views.html.error.notFound(request.path)(request.session, request.flash))) 20 | 21 | override protected def onBadRequest(request: RequestHeader, error: String) = Future.successful( 22 | Results.BadRequest(views.html.error.badRequest(request.path, error)(request.session, request.flash))) 23 | } 24 | -------------------------------------------------------------------------------- /app/utils/web/FormUtils.scala: -------------------------------------------------------------------------------- 1 | package utils.web 2 | 3 | import play.api.data.FormError 4 | import play.api.mvc.{ AnyContent, Request } 5 | 6 | object FormUtils { 7 | def getForm(request: Request[AnyContent]) = request.body.asFormUrlEncoded match { 8 | case Some(f) => f.mapValues(x => x.headOption.getOrElse(throw new IllegalStateException("Empty form element."))) 9 | case None => throw new IllegalStateException("Missing form post.") 10 | } 11 | 12 | def errorsToString(errors: Seq[FormError]) = errors.map(e => e.key + ": " + e.message).mkString(", ") 13 | } 14 | -------------------------------------------------------------------------------- /app/utils/web/LoggingFilter.scala: -------------------------------------------------------------------------------- 1 | package utils.web 2 | 3 | import javax.inject.Inject 4 | 5 | import akka.stream.Materializer 6 | import play.api.http.Status 7 | import scala.concurrent.ExecutionContext.Implicits.global 8 | import play.api.mvc._ 9 | import utils.Logging 10 | 11 | import scala.concurrent.Future 12 | 13 | class LoggingFilter @Inject() (override implicit val mat: Materializer) extends Filter with Logging { 14 | val prefix = "scala-js-typescript.requests." 15 | 16 | val knownStatuses = Seq( 17 | Status.OK, Status.BAD_REQUEST, Status.FORBIDDEN, Status.NOT_FOUND, 18 | Status.CREATED, Status.TEMPORARY_REDIRECT, Status.INTERNAL_SERVER_ERROR, Status.CONFLICT, 19 | Status.UNAUTHORIZED, Status.NOT_MODIFIED) 20 | 21 | def apply(nextFilter: RequestHeader => Future[Result])(request: RequestHeader): Future[Result] = { 22 | val startTime = System.currentTimeMillis 23 | 24 | nextFilter(request).transform( 25 | result => { 26 | if (request.path.startsWith("/assets")) { 27 | result 28 | } else { 29 | val endTime = System.currentTimeMillis 30 | val requestTime = endTime - startTime 31 | log.info(s"${result.header.status} (${requestTime}ms): ${request.method} ${request.uri}") 32 | result.withHeaders("X-Request-Time-Ms" -> requestTime.toString) 33 | } 34 | }, 35 | exception => exception) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/utils/web/RequestHandler.scala: -------------------------------------------------------------------------------- 1 | package utils.web 2 | 3 | import javax.inject.Inject 4 | import play.api.http._ 5 | import play.api.mvc.RequestHeader 6 | import play.api.routing.Router 7 | import utils.Logging 8 | 9 | class RequestHandler @Inject() ( 10 | errorHandler: HttpErrorHandler, 11 | configuration: HttpConfiguration, 12 | filters: HttpFilters, 13 | router: Router) extends DefaultHttpRequestHandler(router, errorHandler, configuration, filters) with Logging { 14 | 15 | override def routeRequest(request: RequestHeader) = { 16 | if (!Option(request.path).exists(_.startsWith("/assets"))) { 17 | log.info(s"Request from [${request.remoteAddress}]: ${request.toString()}") 18 | } 19 | super.routeRequest(request) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/utils/web/WebFilters.scala: -------------------------------------------------------------------------------- 1 | package utils.web 2 | 3 | import javax.inject.Inject 4 | 5 | import play.api.http.HttpFilters 6 | import play.filters.gzip.GzipFilter 7 | 8 | class WebFilters @Inject() (customLoggingFilter: LoggingFilter, gzipFilter: GzipFilter) extends HttpFilters { 9 | override def filters = Seq(customLoggingFilter, gzipFilter) 10 | } 11 | -------------------------------------------------------------------------------- /app/views/component/filterForm.scala.html: -------------------------------------------------------------------------------- 1 | @(q: Option[String], filter: Option[String], showOptions: Boolean = true) 2 |
3 |
4 |
5 | 6 |
7 | @if(showOptions) { 8 |
9 | @if(filter.contains("all") || filter.isEmpty) { 10 | 11 | } else { 12 | 13 | } 14 | 15 |
16 |
17 | @if(filter.contains("parsed")) { 18 | 19 | } else { 20 | 21 | } 22 | 23 |
24 |
25 | @if(filter.contains("project")) { 26 | 27 | } else { 28 | 29 | } 30 | 31 |
32 |
33 | @if(filter.contains("built")) { 34 | 35 | } else { 36 | 37 | } 38 | 39 |
40 |
41 | @if(filter.contains("repo")) { 42 | 43 | } else { 44 | 45 | } 46 | 47 |
48 |
49 | @if(filter.contains("published")) { 50 | 51 | } else { 52 | 53 | } 54 | 55 |
56 | } 57 |
58 |
59 | -------------------------------------------------------------------------------- /app/views/detail.scala.html: -------------------------------------------------------------------------------- 1 | @( 2 | key: String, 3 | details: models.parse.ProjectDefinition, 4 | out: better.files.File, 5 | project: better.files.File, 6 | hasRepo: Boolean, 7 | github: Option[services.github.GithubService.Repo], 8 | debug: Boolean 9 | )(implicit request: Request[AnyContent], session: Session, flash: Flash)@layout.simple(details.name) { 10 |
11 |
12 |
13 |
14 |
15 | 16 |
@key
17 |
18 |
19 |
@details.name (@details.version)
20 | 21 |
@details.authors
22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 |
37 |
38 |
Local Git Repo
39 | @if(hasRepo) { 40 |
Local repo ready.
41 | Details 42 | Reset 43 | } else { 44 |
No local repo.
45 | Create 46 | } 47 |
48 |
49 |
Github Repo
50 | @if(github.isDefined) { 51 | 52 | Details 53 | } else { 54 |
No Github repository available.
55 | Create 56 | } 57 |
58 |
59 |
60 |
61 |
62 | } 63 | -------------------------------------------------------------------------------- /app/views/error/badRequest.scala.html: -------------------------------------------------------------------------------- 1 | @(path: String, error: String)(implicit session: Session, flash: Flash)@layout.materialize("Page Not Found") { 2 |
3 |

@path

4 |
Bad Request: @error
5 |
6 | } 7 | -------------------------------------------------------------------------------- /app/views/error/notFound.scala.html: -------------------------------------------------------------------------------- 1 | @(path: String)(implicit session: Session, flash: Flash)@layout.materialize("Page Not Found") { 2 |
3 |

@path

4 |
Page Not Found
5 |
6 | } 7 | -------------------------------------------------------------------------------- /app/views/error/serverError.scala.html: -------------------------------------------------------------------------------- 1 | @(path: String, ex: Option[Throwable])(implicit session: Session, flash: Flash)@layout.materialize("Server Error") { 2 |
3 |

@path

4 |
Exception Encountered
5 | @ex.map { x => } 11 |
12 | } 13 | -------------------------------------------------------------------------------- /app/views/git/detail.scala.html: -------------------------------------------------------------------------------- 1 | @(key: String)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
@key
9 |
10 |
11 | 40 |
41 |
42 |
43 |
44 |
45 | } 46 | -------------------------------------------------------------------------------- /app/views/git/form.scala.html: -------------------------------------------------------------------------------- 1 | @()(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
Git Update
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | } 30 | -------------------------------------------------------------------------------- /app/views/git/result.scala.html: -------------------------------------------------------------------------------- 1 | @(key: String, code: Int, result: String, nextStep: Option[(String, Call)] = None)( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(key) { 4 |
5 |
6 |
7 |
8 |
9 | @nextStep.map { next => 10 |
11 | @next._1 12 |
13 | } 14 |
[@key] Git Result (@code)
15 |
16 |
17 |
@result
18 |
19 |
20 |
21 |
22 |
23 | } 24 | -------------------------------------------------------------------------------- /app/views/git/results.scala.html: -------------------------------------------------------------------------------- 1 | @(results: Seq[(String, Int, String)])(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
Git Results
9 |
10 | @results.map { result => 11 |
12 | 13 |
@result._3
14 |
15 | } 16 |
17 |
18 |
19 |
20 | } 21 | -------------------------------------------------------------------------------- /app/views/git/test.scala.html: -------------------------------------------------------------------------------- 1 | @(result: String)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
Git Test Results
9 |
10 |
11 |
@result
12 |
13 |
14 |
15 |
16 |
17 | } 18 | -------------------------------------------------------------------------------- /app/views/github/detail.scala.html: -------------------------------------------------------------------------------- 1 | @(repo: services.github.GithubService.Repo)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
@repo.name (@repo.id)
9 |
10 |
11 | @repo.url 12 |
13 |
14 |
15 |
16 |
17 | } 18 | -------------------------------------------------------------------------------- /app/views/github/list.scala.html: -------------------------------------------------------------------------------- 1 | @(repos: Seq[services.github.GithubService.Repo])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
7 |
8 |
9 | Merge All 10 |
11 |
@utils.NumberUtils.withCommas(repos.size) Github Repos
12 |
13 | @repos.map { repo => 14 |
15 |
16 | 17 | 18 | 19 |
20 | @repo.name 21 |
22 | } 23 |
24 |
25 |
26 | } 27 | -------------------------------------------------------------------------------- /app/views/github/test.scala.html: -------------------------------------------------------------------------------- 1 | @(result: String)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
Github Test Results
9 |
10 |
11 |
@result
12 |
13 |
14 |
15 |
16 |
17 | } 18 | -------------------------------------------------------------------------------- /app/views/history/compare.scala.html: -------------------------------------------------------------------------------- 1 | @(keys: Seq[String], lName: String, l: Map[String, Boolean], rName: String, r: Map[String, Boolean])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
Differences
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | @keys.map { key => 17 | @defining(l.get(key)) { lVal => 18 | @defining(r.get(key)) { rVal => 19 | @if(lVal != rVal) { 20 | 21 | 22 | 23 | 24 | 25 | } 26 | } 27 | } 28 | } 29 | 30 |
Project@lName@rName
@key@lVal.map(_.toString).getOrElse("-")@rVal.map(_.toString).getOrElse("-")
31 |
32 |
33 |
34 |
35 |
36 |
All Projects
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | @keys.map { key => 47 | 48 | 49 | 50 | 51 | 52 | } 53 | 54 |
Project@lName@rName
@key@l.get(key).map(_.toString).getOrElse("-")@r.get(key).map(_.toString).getOrElse("-")
55 |
56 |
57 | } 58 | -------------------------------------------------------------------------------- /app/views/history/detail.scala.html: -------------------------------------------------------------------------------- 1 | @(key: String, entries: Seq[(String, Boolean)])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
7 |
8 | 9 |
@utils.NumberUtils.withCommas(entries.size) Projects in [@key]
10 |

@entries.count(_._2) passing, @entries.count(!_._2) failing.

11 |
12 | @entries.map { entry => 13 |
14 |
@entry._2
15 | @entry._1 16 |
17 | } 18 |
19 |
20 |
21 | } 22 | -------------------------------------------------------------------------------- /app/views/history/list.scala.html: -------------------------------------------------------------------------------- 1 | @(histories: Seq[String])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
7 |
8 | 9 |
@utils.NumberUtils.withCommas(histories.size) SBT History Files
10 |
11 |
12 | @histories.map { history => 13 |
14 |
15 | 16 | 17 |
18 | @history 19 |
20 | } 21 |
22 | 23 |
24 |
25 |
26 |
27 |
28 | } 29 | -------------------------------------------------------------------------------- /app/views/home.scala.html: -------------------------------------------------------------------------------- 1 | @( 2 | q: Option[String], 3 | filter: Option[String], 4 | keys: Seq[(String, String)], 5 | debug: Boolean 6 | )(implicit request: Request[AnyContent], session: Session, flash: Flash)@layout.simple("Home") { 7 |
8 |
9 |
10 |
11 |
12 |
@utils.NumberUtils.withCommas(keys.size) Available Projects
13 |
14 |
15 | 16 | 17 |
18 |
19 |
TypeScript
20 | 21 | 22 |
23 |
24 |
Project
25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
Git
34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 |
Github
43 | 44 | 45 | 46 |
47 |
48 |
Publish
49 | 50 | 51 |
52 | 55 |
56 |
57 |
58 |
59 | } 60 | -------------------------------------------------------------------------------- /app/views/layout/basic.scala.html: -------------------------------------------------------------------------------- 1 | @( 2 | title: String, 3 | scripts: Seq[String] = Nil, 4 | stylesheets: Seq[String] = Nil 5 | )(content: Html)(implicit session: Session, flash: Flash) 6 | 7 | 8 | @title 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | @for(script <- scripts) {} 23 | @for(stylesheet <- stylesheets) {} 24 | 25 | @content 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/views/layout/materialize.scala.html: -------------------------------------------------------------------------------- 1 | @(title: String, scripts: Seq[String] = Nil, stylesheets: Seq[String] = Nil)(content: Html)(implicit session: Session, flash: Flash)@basic( 2 | title, 3 | scripts = Seq( 4 | controllers.routes.Assets.versioned("lib/jquery/jquery.js").url, 5 | controllers.routes.Assets.versioned("lib/materializecss/js/materialize.js").url 6 | ) ++ scripts, 7 | stylesheets = Seq( 8 | controllers.routes.Assets.versioned("lib/font-awesome/css/font-awesome.css").url, 9 | controllers.routes.Assets.versioned("lib/materializecss/css/materialize.css").url, 10 | controllers.routes.Assets.versioned(s"stylesheets/index.min.css").url 11 | ) ++ stylesheets 12 | )(content) 13 | -------------------------------------------------------------------------------- /app/views/layout/simple.scala.html: -------------------------------------------------------------------------------- 1 | @(title: String, mainDivClass: String = "static-container container", scripts: Seq[String] = Nil)(content: Html)( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.materialize(title, scripts = scripts, stylesheets = Seq(controllers.routes.Assets.versioned("stylesheets/index.min.css").url)) { 4 |
5 | 8 |
9 | 10 |
11 |
12 | @flash.get("error").map { err =>
@Html(err)
} 13 | @flash.get("success").map { success =>
@Html(success)
} 14 | @content 15 |
16 |
17 | } 18 | -------------------------------------------------------------------------------- /app/views/list.scala.html: -------------------------------------------------------------------------------- 1 | @( 2 | q: Option[String], 3 | filter: Option[String], 4 | details: Seq[services.project.ProjectDetailsService.Details], 5 | debug: Boolean 6 | )(implicit request: Request[AnyContent], session: Session, flash: Flash)@layout.simple("Project List") { 7 |
8 |
9 |
10 |
11 |
12 |
@utils.NumberUtils.withCommas(details.size) Available Projects
13 |
    14 |
  • @utils.NumberUtils.withCommas(details.count(_.parsed)) Parsed
  • 15 |
  • @utils.NumberUtils.withCommas(details.count(_.project)) Project
  • 16 |
  • @utils.NumberUtils.withCommas(details.count(_.built)) Built
  • 17 |
  • @utils.NumberUtils.withCommas(details.count(_.repo)) Repo
  • 18 |
  • @utils.NumberUtils.withCommas(details.count(_.github)) Github
  • 19 |
20 | @views.html.component.filterForm(q, filter) 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | @details.map { detail => 37 | 38 | 41 | 46 | 51 | 54 | 57 | 60 | 65 | 66 | } 67 | 68 |
KeyOutProjectBuildPublishRepoGithub
39 | @detail.key 40 | 42 | 43 | @if(detail.parsed) { } else { } 44 | 45 | 47 | 48 | @if(detail.project) { } else { } 49 | 50 | 52 | @if(detail.built) { } else { } 53 | 55 | ... 56 | 58 | @if(detail.repo) { } else { } 59 | @if(detail.github) { 61 | 62 | } else { 63 | 64 | }
69 |
70 |
71 |
72 |
73 |
74 | } 75 | -------------------------------------------------------------------------------- /app/views/metrics.scala.html: -------------------------------------------------------------------------------- 1 | @(json: String)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName + " Metrics") { 3 |
4 | @utils.Config.projectName Metrics 5 |
@json
6 |
7 | } 8 | -------------------------------------------------------------------------------- /app/views/parse/process.scala.html: -------------------------------------------------------------------------------- 1 | @( 2 | key: String, 3 | content: String, 4 | definitions: Option[Seq[models.parse.parser.tree.DeclTree]], 5 | definitionsJson: Option[String], 6 | output: Seq[String], 7 | debug: Boolean 8 | )(implicit request: Request[AnyContent], session: Session, flash: Flash)@layout.simple(key) { 9 |
10 |
11 |
    12 |
  • 13 |
    @key
    14 |
  • 15 |
  • 16 |
    Scala Output
    17 |
    @output.mkString("\n")
    18 |
  • 19 |
  • 20 |
    Parsed Tree
    21 |
    @definitions
    22 |
  • 23 |
  • 24 |
    Parsed Json
    25 |
    @definitionsJson
    26 |
  • 27 |
  • 28 |
    TypeScript Input
    29 |
    @content
    30 |
  • 31 |
32 |
33 |
34 | } 35 | -------------------------------------------------------------------------------- /app/views/parse/processAll.scala.html: -------------------------------------------------------------------------------- 1 | @(results: Seq[controllers.ParseController.Result], debug: Boolean)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
Processed @utils.NumberUtils.withCommas(results.size) Libraries
8 |
    9 | @results.map { result => 10 |
  • 11 |
    12 |
    @if(result.tree.isDefined) { 13 | 14 | } else { 15 | 16 | }
    17 | @result.key 18 |
    19 |
    @result.text
    20 |
  • 21 | } 22 |
23 |
24 |
25 |
26 |
27 | } 28 | -------------------------------------------------------------------------------- /app/views/problems.scala.html: -------------------------------------------------------------------------------- 1 | @(details: Seq[services.project.ProjectDetailsService.Details], debug: Boolean)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | 3 | @p(title: String, f: services.project.ProjectDetailsService.Details => Boolean) = { 4 | @defining(details.filter(f)) { probs => 5 |
6 | @if(probs.nonEmpty) {
@title
} 7 | @probs.map { detail => 8 | 9 | } 10 |
11 | } 12 | } 13 | 14 | @layout.simple("Problems") { 15 |
16 |
17 |
18 |
19 |
20 |
@utils.NumberUtils.withCommas(details.size) Available Projects
21 |
    22 |
  • @utils.NumberUtils.withCommas(details.count(_.parsed)) Parsed
  • 23 |
  • @utils.NumberUtils.withCommas(details.count(_.project)) Project
  • 24 |
  • @utils.NumberUtils.withCommas(details.count(_.built)) Built
  • 25 |
  • @utils.NumberUtils.withCommas(details.count(_.repo)) Repo
  • 26 |
  • @utils.NumberUtils.withCommas(details.count(_.github)) Github
  • 27 |
28 |
29 | @p("Built, no repo", d => d.built && (!d.repo)) 30 | @p("Parsed, no project", d => d.parsed && (!d.project)) 31 | @p("Not parsed", d => !d.parsed) 32 |
33 |
34 |
35 |
36 | } 37 | -------------------------------------------------------------------------------- /app/views/project/update.scala.html: -------------------------------------------------------------------------------- 1 | @(key: String, created: Boolean, debug: Boolean)( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(key) { 4 |
5 |
6 |
@key
7 |
Created: @created
8 |
9 |
10 | } 11 | -------------------------------------------------------------------------------- /app/views/project/updateAll.scala.html: -------------------------------------------------------------------------------- 1 | @(results: Seq[(String, Boolean)], debug: Boolean)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
Processed @utils.NumberUtils.withCommas(results.size) Libraries
8 |
    9 | @results.map { result => 10 |
  • 11 |
    12 |
    13 | @if(result._2) { 14 | 15 | } else { 16 | 17 | } 18 |
    19 | @result._1 20 |
    21 |
  • 22 | } 23 |
24 |
25 |
26 |
27 |
28 | } 29 | -------------------------------------------------------------------------------- /app/views/sandbox/list.scala.html: -------------------------------------------------------------------------------- 1 | @()(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple("Sandbox List") { 3 |
4 |
5 |
6 | Sandbox Actions 7 | 8 |
    9 | @models.sandbox.SandboxTask.values.map { s => 10 |
  • 11 | @s.name 12 |
    @s.description
    13 |
  • 14 | } 15 |
16 |
17 |
18 |
19 | } 20 | -------------------------------------------------------------------------------- /app/views/sandbox/metrics.scala.html: -------------------------------------------------------------------------------- 1 | @(json: String) 2 |
@json
3 | -------------------------------------------------------------------------------- /app/views/sandbox/run.scala.html: -------------------------------------------------------------------------------- 1 | @(s: models.sandbox.SandboxTask, result: models.sandbox.SandboxTask.Result)( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(title = s"${s.name} Result") { 4 |
5 |
6 |
7 |
8 |
@result.status (@{result.elapsed}ms)
9 | @s.name Result 10 |
@result.result
11 |
12 |
13 |
14 |
15 | } 16 | -------------------------------------------------------------------------------- /app/views/sbt/form.scala.html: -------------------------------------------------------------------------------- 1 | @(q: Option[String])(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
7 |
8 |
Build All
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | } 30 | -------------------------------------------------------------------------------- /app/views/sbt/list.scala.html: -------------------------------------------------------------------------------- 1 | @(q: Option[String], projects: Seq[(String, Boolean)])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
7 |
8 |
9 | @projects.count(_._2) OK, @projects.count(!_._2) Errors 10 |
11 |
@utils.NumberUtils.withCommas(projects.size) Build Results
12 |
13 | @projects.map { project => 14 | 26 | } 27 |
28 |
29 |
30 | } 31 | -------------------------------------------------------------------------------- /app/views/sbt/published.scala.html: -------------------------------------------------------------------------------- 1 | @(keys: Seq[String], repos: Set[String], m: Set[String], j: Set[String])( 2 | implicit request: Request[AnyContent], session: Session, flash: Flash 3 | )@layout.simple(utils.Config.projectName) { 4 |
5 |
6 |
7 |
8 |
9 | Publish All 10 |
11 | @utils.NumberUtils.withCommas(keys.size) Published Projects 12 |
13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @keys.map { key => 25 | 26 | 27 | 28 | 29 | 30 | 31 | } 32 | 33 |
KeyRepoMavenJCenter
@key@if(repos(key)) { } else { }@if(m(key)) { } else { }@if(j(key)) { } else { }
34 |
35 |
36 |
37 |
38 | } 39 | -------------------------------------------------------------------------------- /app/views/sbt/result.scala.html: -------------------------------------------------------------------------------- 1 | @(key: String, result: services.sbt.SbtResultParser.Result, output: String)(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(key) { 3 |
4 |
5 |
6 |
7 |
8 |
@key
9 | SBT Build Result 10 |
11 |
12 |
@result.infoLines.size [info] / @result.errorLines.size [error]
13 | @if(result.success) { 14 | Success 15 | } else { 16 | Error 17 | } 18 | @result.errors.map { err => 19 |
@err.content
20 | } 21 |
22 |
23 |
@output
24 |
25 |
26 |
27 |
28 |
29 | } 30 | -------------------------------------------------------------------------------- /app/views/sbt/results.scala.html: -------------------------------------------------------------------------------- 1 | @(results: Seq[(String, Int, String)])(implicit request: Request[AnyContent], session: Session, flash: Flash) 2 | @layout.simple(utils.Config.projectName) { 3 |
4 |
5 |
6 |
    7 |
  • 8 |
    SBT Build Results
    9 |
  • 10 | @results.map { result => 11 |
  • 12 |
    13 |
    @result._2
    14 | @result._1 15 |
    16 |
    @result._3
    17 |
  • 18 | } 19 |
20 |
21 |
22 | 23 | } 24 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | scapegoatVersion in ThisBuild := Dependencies.Utils.scapegoatVersion 2 | 3 | lazy val server = Server.server 4 | -------------------------------------------------------------------------------- /conf/application.conf: -------------------------------------------------------------------------------- 1 | pidfile.path = "/dev/null" 2 | data.directory = "./data" 3 | 4 | play { 5 | crypto.secret = "VnewsecretQWkLBpsJXvyIGbZmwIqckyleuleujwnQ72gPJvN7bCedtrgfIerthx" 6 | 7 | server { 8 | http.port = 5000 9 | https.port = 5443 10 | } 11 | 12 | http { 13 | requestHandler = "utils.web.RequestHandler" 14 | filters = "utils.web.WebFilters" 15 | errorHandler = "utils.web.ErrorHandler" 16 | cookies.strict = true 17 | } 18 | 19 | akka.actor-system = "scala-js-typescript" 20 | } 21 | 22 | akka { 23 | version = "2.5.16" 24 | loggers = ["akka.event.slf4j.Slf4jLogger"] 25 | loglevel = "DEBUG" 26 | log-dead-letters = on 27 | log-dead-letters-during-shutdown = off 28 | log-config-on-start = off 29 | jvm-exit-on-fatal-error = on 30 | 31 | actor { 32 | provider = "akka.actor.LocalActorRefProvider" 33 | } 34 | 35 | debug { 36 | receive = off 37 | autoreceive = off 38 | lifecycle = off 39 | fsm = off 40 | event-stream = off 41 | unhandled = on 42 | router-misconfiguration = on 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UTF-8 7 | %-5coloredLevel %d{HH:mm:ss.SSS} %cyan(%logger{15}): %msg%n%xException 8 | 9 | 10 | 11 | 12 | logs/scala-js-typescript.log 13 | 14 | logs/scala-js-typescript.%d{yyyy-MM-dd}.%i.log 15 | 16 | 50MB 17 | 18 | 356 19 | 20 | 21 | 22 | UTF-8 23 | [%level] %date from %logger in %thread %n%message%n%xException%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /conf/replacement/accounting.txt: -------------------------------------------------------------------------------- 1 | = 2 | var accounting: accounting.Static = js.native 3 | var accounting: Static = js.native 4 | - 5 | def formatMoney(numbers: js.Array[Double], symbol: String, precision: Double, thousand: String, decimal: String, format: String): js.Array[String] = js.native 6 | - 7 | def formatMoney(numbers: js.Array[Double], options: CurrencySettings[String] | CurrencySettings[CurrencyFormat]): js.Array[String] = js.native 8 | - 9 | def formatColumn(numbers: js.Array[js.Array[Double]], symbol: String, precision: Double, thousand: String, decimal: String, format: String): js.Array[js.Array[String]] = js.native 10 | - 11 | def formatColumn(numbers: js.Array[js.Array[Double]], options: CurrencySettings[String] | CurrencySettings[CurrencyFormat]): js.Array[js.Array[String]] = js.native 12 | - 13 | def formatNumber(number: js.Array[Double], precision: Double, thousand: String, decimal: String): js.Array[String] = js.native 14 | - 15 | def formatNumber(number: js.Array[Double], options: NumberSettings): js.Array[String] = js.native 16 | -------------------------------------------------------------------------------- /conf/replacement/ace.txt: -------------------------------------------------------------------------------- 1 | - 2 | def this(text: String = js.native) = this() 3 | = 4 | def this(text: js.Array[String] = js.native) = this() 5 | def this(text: (String | js.Array[String]) = js.native) = this() 6 | -------------------------------------------------------------------------------- /conf/replacement/alertify.txt: -------------------------------------------------------------------------------- 1 | = 2 | var alertify: alertify.IAlertifyStatic = js.native 3 | var alertify: IAlertifyStatic = js.native 4 | -------------------------------------------------------------------------------- /conf/replacement/algoliasearch.txt: -------------------------------------------------------------------------------- 1 | * 2 | "js.Tuple1[js.Any]" 3 | "js.Any" 4 | = 5 | def algoliasearch(applicationId: String, apiKey: String, options: algoliasearch.ClientOptions = js.native): algoliasearch.AlgoliaClient = js.native 6 | def algoliasearch(applicationId: String, apiKey: String, options: ClientOptions = js.native): AlgoliaClient = js.native 7 | -------------------------------------------------------------------------------- /conf/replacement/apexjs.txt: -------------------------------------------------------------------------------- 1 | = 2 | object js extends js.Object { 3 | object ApexJS extends js.Object { 4 | = 5 | def λ(fn: js.Function2[js.Any, AWSLambda.Context, Any]): js.Function3[js.Any, AWSLambda.Context, AWSLambda.Callback, Unit] = js.native 6 | def λ(fn: js.Function2[js.Any, com.definitelyscala.awslambda.Context, Any]): js.Function3[js.Any, com.definitelyscala.awslambda.Context, com.definitelyscala.awslambda.Awslambda.Callback, Unit] = js.native 7 | -------------------------------------------------------------------------------- /conf/replacement/arbiter.txt: -------------------------------------------------------------------------------- 1 | * 2 | "a/b/*" 3 | "a/b/..." 4 | -------------------------------------------------------------------------------- /conf/replacement/async.txt: -------------------------------------------------------------------------------- 1 | * 2 | "async.each.type" 3 | "js.Dynamic" 4 | * 5 | "async.eachLimit.type" 6 | "js.Dynamic" 7 | * 8 | "async.forEachOf.type" 9 | "js.Dynamic" 10 | * 11 | "async.forEachOfLimit.type" 12 | "js.Dynamic" 13 | * 14 | "async.map.type" 15 | "js.Dynamic" 16 | * 17 | "async.mapValues.type" 18 | "js.Dynamic" 19 | * 20 | "async.filter.type" 21 | "js.Dynamic" 22 | * 23 | "async.filterLimit.type" 24 | "js.Dynamic" 25 | * 26 | "async.reduce.type" 27 | "js.Dynamic" 28 | * 29 | "async.detect.type" 30 | "js.Dynamic" 31 | * 32 | "async.detectLimit.type" 33 | "js.Dynamic" 34 | * 35 | "async.every.type" 36 | "js.Dynamic" 37 | * 38 | "async..type" 39 | "js.Dynamic" 40 | * 41 | "async.some.type" 42 | "js.Dynamic" 43 | * 44 | "async.someSeries.type" 45 | "js.Dynamic" 46 | * 47 | "async.someLimit.type" 48 | "js.Dynamic" 49 | * 50 | "async.everytype" 51 | "js.Dynamic" 52 | * 53 | "async.everyLimit.type" 54 | "js.Dynamic" 55 | * 56 | "async.concat.type" 57 | "js.Dynamic" 58 | * 59 | "async.nextTick.type" 60 | "js.Dynamic" 61 | -------------------------------------------------------------------------------- /conf/replacement/atmosphere.txt: -------------------------------------------------------------------------------- 1 | = 2 | var atmosphere: Atmosphere.Atmosphere = js.native 3 | var atmosphere: Atmosphere = js.native 4 | -------------------------------------------------------------------------------- /conf/replacement/awssdk.txt: -------------------------------------------------------------------------------- 1 | = 2 | var Data: Buffer | String | Blob = js.native 3 | var Data: Array[_] | String | Blob = js.native 4 | = 5 | var Data: Buffer | String | Blob = js.native 6 | var Data: Array[_] | String | Blob = js.native 7 | = 8 | var SSECustomerKey: Buffer | String = js.native 9 | var SSECustomerKey: Array[_] | String = js.native 10 | = 11 | var SSECustomerKey: Buffer | String = js.native 12 | var SSECustomerKey: Array[_] | String = js.native 13 | = 14 | var Parameters: js.Array[CloudFormation.Parameter] = js.native 15 | var Parameters: js.Array[Parameter] = js.native 16 | = 17 | var Tags: js.Array[CloudFormation.Tag] = js.native 18 | var Tags: js.Array[Tag] = js.native 19 | = 20 | var config: ClientConfig = js.native 21 | var config: com.definitelyscala.awssdk.ClientConfig = js.native 22 | = 23 | class DynamoDB protected () extends js.Object { 24 | class DynamoDBObj protected () extends js.Object { 25 | = 26 | class CloudFormation protected () extends js.Object { 27 | class CloudFormationObj protected () extends js.Object { 28 | = 29 | class Lambda protected () extends js.Object { 30 | class LambdaObj protected () extends js.Object { 31 | = 32 | class AutoScaling protected () extends js.Object { 33 | class AutoScalingObj protected () extends js.Object { 34 | = 35 | class SQS protected () extends js.Object { 36 | class SQSObj protected () extends js.Object { 37 | = 38 | class SES protected () extends js.Object { 39 | class SESObj protected () extends js.Object { 40 | = 41 | trait AwsError extends Error { 42 | trait AwsError extends js.Error { 43 | * 44 | : _DDBDC_Keys 45 | : DynamoDB._DDBDC_Keys 46 | * 47 | : _DDBDC_KeyComparison 48 | : DynamoDB._DDBDC_KeyComparison 49 | -------------------------------------------------------------------------------- /conf/replacement/bcrypt.txt: -------------------------------------------------------------------------------- 1 | = 2 | def genSalt(callback: js.Function2[Error, String, Unit] = js.native): Promise[String] = js.native 3 | def genSalt(callback: js.Function2[Error, String, Unit]): Promise[String] = js.native 4 | -------------------------------------------------------------------------------- /conf/replacement/bigint.txt: -------------------------------------------------------------------------------- 1 | - 2 | def str2bigInt(s: String, b: Double, n: Double = js.native, m: Double = js.native): BigInt = js.native 3 | = 4 | def str2bigInt(s: String, b: String, n: Double = js.native, m: Double = js.native): BigInt = js.native 5 | def str2bigInt(s: String, b: (String | Double), n: Double = js.native, m: Double = js.native): BigInt = js.native 6 | -------------------------------------------------------------------------------- /conf/replacement/biginteger.txt: -------------------------------------------------------------------------------- 1 | - 2 | def valueOf(): Double = js.native 3 | -------------------------------------------------------------------------------- /conf/replacement/bootstrap.txt: -------------------------------------------------------------------------------- 1 | - 2 | * @param event a chart event 3 | = 4 | * @param the name of the color set 5 | * @param colorSetName the name of the color set 6 | = 7 | * @param an array of colors. 8 | * @param colorSetArray an array of colors. 9 | = 10 | * @param the information used by this culture 11 | * @param info the information used by this culture 12 | -------------------------------------------------------------------------------- /conf/replacement/calq.txt: -------------------------------------------------------------------------------- 1 | = 2 | trait Calq extends js.Object { 3 | trait CalqObj extends js.Object { 4 | = 5 | object Calq extends js.Object { 6 | object CalqObj extends js.Object { 7 | = 8 | var calq: Calq = js.native 9 | var calq: CalqObj = js.native 10 | -------------------------------------------------------------------------------- /conf/replacement/combokeys.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Combokeys extends js.Object { 3 | object CombokeysObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/css.txt: -------------------------------------------------------------------------------- 1 | = 2 | * @param {string} code - CSS code. 3 | * @param code - CSS code. 4 | = 5 | * @param {ParserOptions} options - CSS parser options. 6 | * @param options - CSS parser options. 7 | = 8 | * @param {Stylesheet} stylesheet - AST tree. 9 | * @param stylesheet - AST tree. 10 | = 11 | * @param {StringifyOptions} options - AST tree to string serializaiton options. 12 | * @param options - AST tree to string serializaiton options. 13 | -------------------------------------------------------------------------------- /conf/replacement/datgui.txt: -------------------------------------------------------------------------------- 1 | - 2 | def add(target: Object, propName: String, items: js.Array[String]): GUIController = js.native 3 | = 4 | def add(target: Object, propName: String, items: js.Array[Double]): GUIController = js.native 5 | def add(target: Object, propName: String, items: js.Array[(String | Double)]): GUIController = js.native 6 | -------------------------------------------------------------------------------- /conf/replacement/debug.txt: -------------------------------------------------------------------------------- 1 | = 2 | var debug: debug.IDebug = js.native 3 | var debug: com.definitelyscala.debug.debug.IDebug = js.native 4 | = 5 | def apply(namespace: String): debug.IDebugger = js.native 6 | def apply(namespace: String): com.definitelyscala.debug.debug.IDebugger = js.native 7 | -------------------------------------------------------------------------------- /conf/replacement/each.txt: -------------------------------------------------------------------------------- 1 | - 2 | def on(eventName: String, onError: js.Function1[Error, Unit]): Each = js.native 3 | -------------------------------------------------------------------------------- /conf/replacement/expectations.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Expectations extends js.Object { 3 | object ExpectationsObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/faker.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Faker extends js.Object { 3 | object FakerObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/flipsnap.txt: -------------------------------------------------------------------------------- 1 | - 2 | def addEventListener(`type`: String, listener: js.Function1[FlipsnapTouchMoveEvent, Any], useCapture: Boolean): Unit = js.native 3 | - 4 | def addEventListener(`type`: String, listener: js.Function1[FlipsnapTouchEndEvent, Any], useCapture: Boolean): Unit = js.native 5 | -------------------------------------------------------------------------------- /conf/replacement/gamepad.txt: -------------------------------------------------------------------------------- 1 | * 2 | "@readonly" 3 | "(readonly)" 4 | * 5 | " Gamepad." 6 | " " 7 | * 8 | "[Gamepad." 9 | "[" 10 | -------------------------------------------------------------------------------- /conf/replacement/github.txt: -------------------------------------------------------------------------------- 1 | = 2 | var Promise: Promise.type = js.native 3 | var Promise: js.Object = js.native 4 | -------------------------------------------------------------------------------- /conf/replacement/hashids.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Hashids extends js.Object { 3 | object HashidsObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/jquery.txt: -------------------------------------------------------------------------------- 1 | - 2 | def `then`(doneFilter: js.Function, failFilter: js.Function, progressFilter: js.Function): JQueryPromise[Unit] = js.native 3 | = 4 | * @param arguments An argument, or array of arguments, to pass to the callbacks in the list. 5 | * @param args An argument, or array of arguments, to pass to the callbacks in the list. 6 | - 7 | * @name toArray 8 | - 9 | * @alias toArray 10 | - 11 | * @param doneFilter A function that is called when the Deferred is resolved. 12 | - 13 | * @param failFilter An optional function that is called when the Deferred is rejected. 14 | -------------------------------------------------------------------------------- /conf/replacement/jqueryui.txt: -------------------------------------------------------------------------------- 1 | = 2 | var beforeShow: js.Function2[Element, js.Any, JQueryUI.DatepickerOptions] = js.native 3 | var beforeShow: js.Function2[Element, js.Any, DatepickerOptions] = js.native 4 | = 5 | var click: js.Function1[JQueryEventObject, Any] = js.native 6 | var click: js.Function1[js.Dynamic, Any] = js.native 7 | = 8 | def apply(event: JQueryEventObject, ui: SortableUIParams): Unit = js.native 9 | def apply(event: js.Dynamic, ui: SortableUIParams): Unit = js.native 10 | = 11 | var jqXHR: JQueryXHR = js.native 12 | var jqXHR: js.Dynamic = js.native 13 | = 14 | trait TabsEvent[UI] extends js.Object { 15 | trait TabsEvent[T] extends js.Object { 16 | = 17 | def apply(event: Event, ui: UI): Unit = js.native 18 | def apply(event: Event, ui: T): Unit = js.native 19 | * 20 | ": JQueryEasingFunction" 21 | ": js.Dynamic" 22 | * 23 | " JQueryUI." 24 | " " 25 | -------------------------------------------------------------------------------- /conf/replacement/less.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Less extends js.Object { 3 | object LessObj extends js.Object { 4 | * 5 | " Less." 6 | " " 7 | * 8 | "[Less." 9 | "[" 10 | -------------------------------------------------------------------------------- /conf/replacement/materializecss.txt: -------------------------------------------------------------------------------- 1 | = 2 | var data: js.Array[Materialize.ChipDataObject] = js.native 3 | var data: js.Array[ChipDataObject] = js.native 4 | = 5 | var Materialize: Materialize.Materialize = js.native 6 | var Materialize: com.definitelyscala.materializecss.Materialize.Materialize = js.native 7 | = 8 | def toast(message: String | JQuery, displayLength: Double, className: String = js.native, completeCallback: js.Function = js.native): Unit = js.native 9 | def toast(message: String | js.Dynamic, displayLength: Double, className: String = js.native, completeCallback: js.Function = js.native): Unit = js.native 10 | * 11 | "@name " 12 | "@param " 13 | * 14 | " Materialize." 15 | " " 16 | * 17 | ".Materialize." 18 | "." 19 | * 20 | "[Materialize." 21 | "[" 22 | -------------------------------------------------------------------------------- /conf/replacement/matterjs.txt: -------------------------------------------------------------------------------- 1 | * 2 | "@property " 3 | "property: " 4 | * 5 | "@method " 6 | "method: " 7 | * 8 | "@type " 9 | "type: " 10 | * 11 | "@default " 12 | "default: " 13 | - 14 | def on(obj: Engine, name: String, callback: js.Function1[IEventTimestamped[Runner], Unit]): Unit = js.native 15 | - 16 | def on(obj: Engine, name: String, callback: js.Function1[IEventCollision[Engine], Unit]): Unit = js.native 17 | - 18 | def on(obj: Engine, name: String, callback: js.Function1[IEventTimestamped[Render], Unit]): Unit = js.native 19 | - 20 | def on(obj: Engine, name: String, callback: js.Function1[IEventTimestamped[Engine], Unit]): Unit = js.native 21 | -------------------------------------------------------------------------------- /conf/replacement/mixpanel.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Mixpanel extends js.Object { 3 | object MixpanelObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/msgpack.txt: -------------------------------------------------------------------------------- 1 | = 2 | var msgpack: msgpack.MsgPackStatic = js.native 3 | var msgpackObj: com.definitelyscala.msgpack.msgpack.MsgPackStatic = js.native 4 | = 5 | object msgpack extends js.Object { 6 | object msgpackObj extends js.Object { 7 | -------------------------------------------------------------------------------- /conf/replacement/nedb.txt: -------------------------------------------------------------------------------- 1 | = 2 | class Nedb protected () extends js.Object { 3 | class NedbObj protected () extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/node.txt: -------------------------------------------------------------------------------- 1 | * 2 | "String | symbol" 3 | "String" 4 | * 5 | "NodeJS.Timer" 6 | "Timer" 7 | * 8 | "NodeJS.Domain" 9 | "Domain" 10 | * 11 | "NodeJS.ErrnoException" 12 | "ErrnoException" 13 | * 14 | "NodeJS.Process" 15 | "Process" 16 | * 17 | "NodeJS.Global" 18 | "Global" 19 | * 20 | "NodeJS.WritableStream" 21 | "WritableStream" 22 | * 23 | "NodeJS.ReadWriteStream" 24 | "ReadWriteStream" 25 | * 26 | "NodeJS.ReadableStream" 27 | "ReadableStream" 28 | = 29 | class Domain extends events.EventEmitter with Domain { 30 | class Domain extends events.EventEmitter { 31 | = 32 | class Stream extends internal { 33 | class Stream { 34 | - 35 | var ArrayBuffer: ArrayBuffer.type = js.native 36 | - 37 | var Array: Array.type = js.native 38 | - 39 | var Boolean: Boolean.type = js.native 40 | - 41 | var Date: Date.type = js.native 42 | - 43 | var Error: Error.type = js.native 44 | - 45 | var Float32Array: Float32Array.type = js.native 46 | - 47 | var Float64Array: Float64Array.type = js.native 48 | - 49 | var Function: Function.type = js.native 50 | - 51 | var Int16Array: Int16Array.type = js.native 52 | - 53 | var Int32Array: Int32Array.type = js.native 54 | - 55 | var Int8Array: Int8Array.type = js.native 56 | - 57 | var Math: Math.type = js.native 58 | - 59 | var Number: Number.type = js.native 60 | - 61 | var Object: Object.type = js.native 62 | - 63 | var String: String.type = js.native 64 | - 65 | var Uint16Array: Uint16Array.type = js.native 66 | - 67 | var Uint32Array: Uint32Array.type = js.native 68 | - 69 | var Uint8Array: Uint8Array.type = js.native 70 | - 71 | var Buffer: Buffer.type = js.native 72 | - 73 | var DataView: DataView.type = js.native 74 | - 75 | var EvalError: EvalError.type = js.native 76 | - 77 | var Infinity: Infinity.type = js.native 78 | - 79 | var Intl: Intl.type = js.native 80 | - 81 | var JSON: JSON.type = js.native 82 | - 83 | var Map: MapConstructor = js.native 84 | - 85 | var NaN: NaN.type = js.native 86 | - 87 | var RangeError: RangeError.type = js.native 88 | - 89 | var ReferenceError: ReferenceError.type = js.native 90 | - 91 | var RegExp: RegExp.type = js.native 92 | - 93 | var Set: SetConstructor = js.native 94 | - 95 | var SyntaxError: SyntaxError.type = js.native 96 | - 97 | var TypeError: TypeError.type = js.native 98 | - 99 | var URIError: URIError.type = js.native 100 | - 101 | var WeakMap: WeakMapConstructor = js.native 102 | - 103 | var WeakSet: WeakSetConstructor = js.native 104 | - 105 | var console: console.type = js.native 106 | - 107 | var decodeURI: decodeURI.type = js.native 108 | - 109 | var decodeURIComponent: decodeURIComponent.type = js.native 110 | - 111 | var encodeURI: encodeURI.type = js.native 112 | - 113 | var encodeURIComponent: encodeURIComponent.type = js.native 114 | - 115 | var eval: eval.type = js.native 116 | - 117 | var isFinite: isFinite.type = js.native 118 | - 119 | var isNaN: isNaN.type = js.native 120 | - 121 | var parseFloat: parseFloat.type = js.native 122 | - 123 | var parseInt: parseInt.type = js.native 124 | - 125 | var undefined: undefined.type = js.native 126 | - 127 | def readFileSync(filename: String, options: js.Any): String = js.native 128 | = 129 | def readFileSync(filename: String, options: js.Any = js.native): Buffer = js.native 130 | def readFileSync(filename: String, options: js.Any = js.native): String | Buffer = js.native 131 | -------------------------------------------------------------------------------- /conf/replacement/pad.txt: -------------------------------------------------------------------------------- 1 | = 2 | def pad(text: String, length: Double, options: js.Any = js.native): String = js.native 3 | def pad(text: String, length: Double, options: js.Any): String = js.native 4 | -------------------------------------------------------------------------------- /conf/replacement/phaser.txt: -------------------------------------------------------------------------------- 1 | * 2 | " Phaser." 3 | " " 4 | * 5 | "[Phaser." 6 | "[" 7 | * 8 | " PIXI." 9 | " com.definitelyscala.phaserpixi." 10 | * 11 | "[PIXI." 12 | "[com.definitelyscala.phaserpixi." 13 | * 14 | ": Physics.P2," 15 | ": Physics.P2Obj," 16 | = 17 | object Utils extends js.Object { 18 | object UtilsObj extends js.Object { 19 | = 20 | class Physics protected () extends js.Object { 21 | class PhysicsObj protected () extends js.Object { 22 | = 23 | object Physics extends js.Object { 24 | object PhysicsObj extends js.Object { 25 | = 26 | object AStar extends js.Object { 27 | object AStarObj extends js.Object { 28 | = 29 | object Arcade extends js.Object { 30 | object ArcadeObj extends js.Object { 31 | = 32 | class P2 protected () extends js.Object { 33 | class P2Obj protected () extends js.Object { 34 | = 35 | var physics: Physics = js.native 36 | var physics: PhysicsObj = js.native 37 | = 38 | var p2: Physics.P2 = js.native 39 | var p2: Physics.P2Obj = js.native 40 | = 41 | var world: Physics.P2 = js.native 42 | var world: Physics.P2Obj = js.native 43 | * 44 | "MSPointerEvent" 45 | "js.Object" 46 | -------------------------------------------------------------------------------- /conf/replacement/phaserpixi.txt: -------------------------------------------------------------------------------- 1 | - 2 | package pixi 3 | - 4 | var VERSION: CONST.VERSION.type = js.native 5 | - 6 | var PI_2: CONST.PI_2.type = js.native 7 | - 8 | var RAD_TO_DEG: CONST.RAD_TO_DEG.type = js.native 9 | - 10 | var DEG_TO_RAD: CONST.DEG_TO_RAD.type = js.native 11 | - 12 | var TEXT_STYLE_CHANGED: CONST.TEXT_STYLE_CHANGED.type = js.native 13 | - 14 | def off(event: String, fn: js.Function, context: js.Any = js.native): utils.EventEmitter = js.native 15 | - 16 | def off(event: String, fn: js.Function, context: js.Any = js.native): utils.EventEmitter = js.native 17 | - 18 | var gl: PIXI.glCore.type = js.native 19 | - 20 | def this(points: Point*) = this() 21 | = 22 | def this(points: Double*) = this() 23 | def this(points: (Point | Double)*) = this() 24 | = 25 | var extract: extract.CanvasExtract = js.native 26 | var extract: com.definitelyscala.pixijs.extract.PIXI.CanvasExtract = js.native 27 | = 28 | var extract: extract.WebGLExtract = js.native 29 | var extract: com.definitelyscala.pixijs.extract.PIXI.WebGLExtract = js.native 30 | = 31 | var uploadFunction: js.Function6[js.Array[PIXI.DisplayObject], Double, Double, js.Array[Double], Double, Double, Unit] = js.native 32 | var uploadFunction: js.Function6[js.Array[DisplayObject], Double, Double, js.Array[Double], Double, Double, Unit] = js.native 33 | = 34 | def apply(index: String): loaders.Resource = js.native 35 | def apply(index: String): Resource = js.native 36 | = 37 | def update(index: String, v: loaders.Resource): Unit = js.native 38 | def update(index: String, v: Resource): Unit = js.native 39 | = 40 | def load(cb: js.Function2[loaders.Loader, js.Any, Unit] = js.native): Loader = js.native 41 | def load(cb: js.Function2[Loader, js.Any, Unit] = js.native): Loader = js.native 42 | = 43 | type Strip = mesh.Mesh 44 | type Strip = com.definitelyscala.pixijs.mesh.PIXI.Mesh 45 | = 46 | type Rope = mesh.Rope 47 | type Rope = com.definitelyscala.pixijs.mesh.PIXI.Rope 48 | = 49 | type ParticleContainer = particles.ParticleContainer 50 | type ParticleContainer = com.definitelyscala.pixijs.particles.PIXI.ParticleContainer 51 | = 52 | var vaos: js.Array[glCore.VertexArrayObject] = js.native 53 | var vaos: js.Array[com.definitelyscala.pixijs.glCore.PIXI.VertexArrayObject] = js.native 54 | = 55 | class DisplayObject extends utils.EventEmitter with interaction.InteractiveTarget { 56 | class DisplayObject extends com.definitelyscala.pixijs.utils.PIXI.EventEmitter with com.definitelyscala.pixijs.interaction.InteractiveTarget { 57 | = 58 | object Pixi extends js.Object { 59 | object PixiObj extends js.Object { 60 | = 61 | var RENDERER_TYPE: CONST.RENDERER_TYPE.type = js.native 62 | var RENDERER_TYPE: js.Object = js.native 63 | = 64 | var BLEND_MODES: CONST.BLEND_MODES.type = js.native 65 | var BLEND_MODES: js.Object = js.native 66 | = 67 | var DRAW_MODES: CONST.DRAW_MODES.type = js.native 68 | var DRAW_MODES: js.Object = js.native 69 | = 70 | var SCALE_MODES: CONST.SCALE_MODES.type = js.native 71 | var SCALE_MODES: js.Object = js.native 72 | = 73 | var WRAP_MODES: CONST.WRAP_MODES.type = js.native 74 | var WRAP_MODES: js.Object = js.native 75 | = 76 | var TRANSFORM_MODE: CONST.TRANSFORM_MODE.type = js.native 77 | var TRANSFORM_MODE: js.Object = js.native 78 | = 79 | var PRECISION: CONST.PRECISION.type = js.native 80 | var PRECISION: js.Object = js.native 81 | = 82 | var GC_MODES: CONST.GC_MODES.type = js.native 83 | var GC_MODES: js.Object = js.native 84 | = 85 | var SHAPES: CONST.SHAPES.type = js.native 86 | var SHAPES: js.Object = js.native 87 | = 88 | var TEXT_GRADIENT: CONST.TEXT_GRADIENT.type = js.native 89 | var TEXT_GRADIENT: js.Object = js.native 90 | * 91 | " PIXI." 92 | " " 93 | * 94 | ".PIXI." 95 | "." 96 | * 97 | "Phaser.Game" 98 | "js.Object" 99 | * 100 | " interaction.InteractionEvent" 101 | " com.definitelyscala.pixijs.interaction.InteractionEvent" 102 | * 103 | " loaders.Loader" 104 | " com.definitelyscala.pixijs.loaders.Loader" 105 | * 106 | "= extras." 107 | "= com.definitelyscala.pixijs.extras." 108 | * 109 | " glCore." 110 | " com.definitelyscala.pixijs.glCore." 111 | * 112 | " utils.EventEmitter" 113 | " com.definitelyscala.pixijs.utils.EventEmitter" 114 | * 115 | " loaders.Resource" 116 | " Resource" 117 | * 118 | "`js.RegExp`" 119 | "js.RegExp" 120 | -------------------------------------------------------------------------------- /conf/replacement/pixijs.txt: -------------------------------------------------------------------------------- 1 | - 2 | package pixi 3 | - 4 | var VERSION: CONST.VERSION.type = js.native 5 | - 6 | var PI_2: CONST.PI_2.type = js.native 7 | - 8 | var RAD_TO_DEG: CONST.RAD_TO_DEG.type = js.native 9 | - 10 | var DEG_TO_RAD: CONST.DEG_TO_RAD.type = js.native 11 | - 12 | var TEXT_STYLE_CHANGED: CONST.TEXT_STYLE_CHANGED.type = js.native 13 | - 14 | def off(event: String, fn: js.Function, context: js.Any = js.native): utils.EventEmitter = js.native 15 | - 16 | def off(event: String, fn: js.Function, context: js.Any = js.native): utils.EventEmitter = js.native 17 | - 18 | var gl: PIXI.glCore.type = js.native 19 | - 20 | def this(points: Point*) = this() 21 | = 22 | def this(points: Double*) = this() 23 | def this(points: (Point | Double)*) = this() 24 | = 25 | var extract: extract.CanvasExtract = js.native 26 | var extract: com.definitelyscala.pixijs.extract.PIXI.CanvasExtract = js.native 27 | = 28 | var extract: extract.WebGLExtract = js.native 29 | var extract: com.definitelyscala.pixijs.extract.PIXI.WebGLExtract = js.native 30 | = 31 | var uploadFunction: js.Function6[js.Array[PIXI.DisplayObject], Double, Double, js.Array[Double], Double, Double, Unit] = js.native 32 | var uploadFunction: js.Function6[js.Array[DisplayObject], Double, Double, js.Array[Double], Double, Double, Unit] = js.native 33 | = 34 | def apply(index: String): loaders.Resource = js.native 35 | def apply(index: String): Resource = js.native 36 | = 37 | def update(index: String, v: loaders.Resource): Unit = js.native 38 | def update(index: String, v: Resource): Unit = js.native 39 | = 40 | def load(cb: js.Function2[loaders.Loader, js.Any, Unit] = js.native): Loader = js.native 41 | def load(cb: js.Function2[Loader, js.Any, Unit] = js.native): Loader = js.native 42 | = 43 | type Strip = mesh.Mesh 44 | type Strip = com.definitelyscala.pixijs.mesh.PIXI.Mesh 45 | = 46 | type Rope = mesh.Rope 47 | type Rope = com.definitelyscala.pixijs.mesh.PIXI.Rope 48 | = 49 | type ParticleContainer = particles.ParticleContainer 50 | type ParticleContainer = com.definitelyscala.pixijs.particles.PIXI.ParticleContainer 51 | = 52 | var vaos: js.Array[glCore.VertexArrayObject] = js.native 53 | var vaos: js.Array[com.definitelyscala.pixijs.glCore.PIXI.VertexArrayObject] = js.native 54 | = 55 | class DisplayObject extends utils.EventEmitter with interaction.InteractiveTarget { 56 | class DisplayObject extends com.definitelyscala.pixijs.utils.PIXI.EventEmitter with com.definitelyscala.pixijs.interaction.InteractiveTarget { 57 | = 58 | object Pixi extends js.Object { 59 | object PixiObj extends js.Object { 60 | = 61 | var RENDERER_TYPE: CONST.RENDERER_TYPE.type = js.native 62 | var RENDERER_TYPE: js.Object = js.native 63 | = 64 | var BLEND_MODES: CONST.BLEND_MODES.type = js.native 65 | var BLEND_MODES: js.Object = js.native 66 | = 67 | var DRAW_MODES: CONST.DRAW_MODES.type = js.native 68 | var DRAW_MODES: js.Object = js.native 69 | = 70 | var SCALE_MODES: CONST.SCALE_MODES.type = js.native 71 | var SCALE_MODES: js.Object = js.native 72 | = 73 | var WRAP_MODES: CONST.WRAP_MODES.type = js.native 74 | var WRAP_MODES: js.Object = js.native 75 | = 76 | var TRANSFORM_MODE: CONST.TRANSFORM_MODE.type = js.native 77 | var TRANSFORM_MODE: js.Object = js.native 78 | = 79 | var PRECISION: CONST.PRECISION.type = js.native 80 | var PRECISION: js.Object = js.native 81 | = 82 | var GC_MODES: CONST.GC_MODES.type = js.native 83 | var GC_MODES: js.Object = js.native 84 | = 85 | var SHAPES: CONST.SHAPES.type = js.native 86 | var SHAPES: js.Object = js.native 87 | = 88 | var TEXT_GRADIENT: CONST.TEXT_GRADIENT.type = js.native 89 | var TEXT_GRADIENT: js.Object = js.native 90 | * 91 | " PIXI." 92 | " " 93 | * 94 | ".PIXI." 95 | "." 96 | * 97 | " interaction.InteractionEvent" 98 | " com.definitelyscala.pixijs.interaction.InteractionEvent" 99 | * 100 | "loaders.Loader" 101 | " com.definitelyscala.pixijs.loaders.Loader" 102 | * 103 | "= extras." 104 | "= com.definitelyscala.pixijs.extras." 105 | * 106 | " glCore." 107 | " com.definitelyscala.pixijs.glCore." 108 | * 109 | " utils.EventEmitter" 110 | " com.definitelyscala.pixijs.utils.EventEmitter" 111 | * 112 | " loaders.Resource" 113 | " Resource" 114 | * 115 | "`js.RegExp`" 116 | "js.RegExp" 117 | -------------------------------------------------------------------------------- /conf/replacement/qwest.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Qwest extends js.Object { 3 | object QwestObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/react.txt: -------------------------------------------------------------------------------- 1 | * 2 | " React." 3 | " " 4 | * 5 | "Readonly[S]" 6 | "S" 7 | * 8 | "Readonly[P]" 9 | "P" 10 | * 11 | "Partial[P]" 12 | "P" 13 | = 14 | type ValidationMap[T] = `object` 15 | type ValidationMap[T] = js.Any 16 | = 17 | var foreignObject: SVGProps[SVGForeignObjectElement] = js.native 18 | var foreignObject: SVGProps[SVGElement] = js.native 19 | = 20 | def isValidElement[P](`object`: `object`): ReactElement[P] = js.native 21 | def isValidElement[P](`object`: js.Any): ReactElement[P] = js.native 22 | = 23 | trait EventHandler[E <: SyntheticEvent[js.Any]] extends js.Object { 24 | trait EventHandler[E <: SyntheticEvent[_]] extends js.Object { 25 | -------------------------------------------------------------------------------- /conf/replacement/redis.txt: -------------------------------------------------------------------------------- 1 | = 2 | trait RedisClient extends EventEmitter { 3 | trait RedisClient extends js.Object { 4 | = 5 | def createClient(unix_socket: String, options: ClientOpts = js.native): RedisClient = js.native 6 | def createClient(unix_socket: String, options: ClientOpts): RedisClient = js.native 7 | = 8 | def createClient(options: ClientOpts = js.native): RedisClient = js.native 9 | def createClient(options: ClientOpts): RedisClient = js.native 10 | = 11 | trait RedisClient extends NodeJS.EventEmitter { 12 | trait RedisClient extends js.Object { 13 | -------------------------------------------------------------------------------- /conf/replacement/resumablejs.txt: -------------------------------------------------------------------------------- 1 | - 2 | def on(event: String, callback: js.Function2[ResumableFile, DragEvent, Unit]): Unit = js.native 3 | - 4 | def on(event: String, callback: js.Function1[js.Array[ResumableFile], Unit]): Unit = js.native 5 | - 6 | def on(event: String, callback: js.Function2[ResumableFile, String, Unit]): Unit = js.native 7 | - 8 | def on(event: String, callback: js.Function2[String, ResumableFile, Unit]): Unit = js.native 9 | -------------------------------------------------------------------------------- /conf/replacement/title.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Title extends js.Object { 3 | object TitleObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/traverson.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Traverson extends js.Object { 3 | object TraversonObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/trim.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Trim extends js.Object { 3 | object TrimObj extends js.Object { 4 | -------------------------------------------------------------------------------- /conf/replacement/ts/react.ts.txt: -------------------------------------------------------------------------------- 1 | *ts 2 | " & Q" 3 | "" 4 | *ts 5 | " & T" 6 | "" 7 | = 8 | props?: Q, // should be Q & Attributes, but then Q is inferred as {} 9 | props?: Q, 10 | = 11 | props?: Q, // should be Q & ClassAttributes 12 | props?: Q, 13 | = 14 | props?: Q, // should be Q & Attributes 15 | props?: Q, 16 | = 17 | function isValidElement

(object: {}): object is ReactElement

; 18 | function isValidElement

(object: object): ReactElement

; 19 | = 20 | setState(f: (prevState: S, props: P) => Pick, callback?: () => any): void; 21 | setState(f: (prevState: S, props: P) => Pick, callback?: () => any): void; 22 | = 23 | setState(state: Pick, callback?: () => any): void; 24 | setState(state: Pick, callback?: () => any): void; 25 | 26 | = 27 | props: Readonly<{ children?: ReactNode }> & Readonly

; 28 | props: Readonly

; 29 | = 30 | (props: P & { children?: ReactNode }, context?: any): ReactElement; 31 | (props: P, context?: any): ReactElement; 32 | = 33 | C & 34 | C; 35 | - 36 | (new (props?: P, context?: any) => T) & 37 | - 38 | (new (props?: P, context?: any) => { props: P }); 39 | = 40 | type ValidationMap = { [K in keyof T]?: Validator }; 41 | type ValidationMap = object; 42 | -------------------------------------------------------------------------------- /conf/replacement/ts/sharepoint.ts.txt: -------------------------------------------------------------------------------- 1 | = 2 | throttle any>(fn: T, interval: number, shouldOverrideThrottle: boolean): T; 3 | throttle(fn: T, interval: number, shouldOverrideThrottle: boolean): T; 4 | - 5 | /** Has no permissions on the Web site. Not available through the user interface. */ 6 | - 7 | /** Do not use this */ 8 | - 9 | /** No change was made */ 10 | - 11 | /** Result is unknown */ 12 | = 13 | SetItem(strSearchTerm: string, objEntity: T): void; 14 | SetItem(strSearchTerm: string, objEntity: T): void; 15 | -------------------------------------------------------------------------------- /conf/replacement/xterm.txt: -------------------------------------------------------------------------------- 1 | = 2 | object Xterm extends js.Object { 3 | object XtermObj extends js.Object { 4 | -------------------------------------------------------------------------------- /project/Dependencies.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | 3 | object Dependencies { 4 | object Logging { 5 | val slf4jApi = "org.slf4j" % "slf4j-api" % "1.7.21" 6 | } 7 | 8 | object Play { 9 | private[this] val version = "2.6.19" 10 | val playLib = "com.typesafe.play" %% "play" % version 11 | val playFilters = play.sbt.PlayImport.filters 12 | val guice = play.sbt.PlayImport.guice 13 | val playWs = play.sbt.PlayImport.ws 14 | val playTest = "com.typesafe.play" %% "play-test" % version % "test" 15 | val playMailer = "com.typesafe.play" %% "play-mailer" % "5.0.0" 16 | } 17 | 18 | object Akka { 19 | private[this] val version = "2.5.16" 20 | val actor = "com.typesafe.akka" %% "akka-actor" % version 21 | val remote = "com.typesafe.akka" %% "akka-remote" % version 22 | val logging = "com.typesafe.akka" %% "akka-slf4j" % version 23 | val cluster = "com.typesafe.akka" %% "akka-cluster" % version 24 | val clusterMetrics = "com.typesafe.akka" %% "akka-cluster-metrics" % version 25 | val clusterTools = "com.typesafe.akka" %% "akka-cluster-tools" % version 26 | val testkit = "com.typesafe.akka" %% "akka-testkit" % version % "test" 27 | } 28 | 29 | object Serialization { 30 | val circeVersion = "0.9.3" 31 | val circeProjects = Seq("circe-core", "circe-generic", "circe-generic-extras", "circe-parser", "circe-java8") 32 | } 33 | 34 | object WebJars { 35 | val fontAwesome = "org.webjars" % "font-awesome" % "4.7.0" 36 | val jquery = "org.webjars" % "jquery" % "2.2.4" 37 | val materialize = "org.webjars" % "materializecss" % "0.100.2" 38 | } 39 | 40 | object Metrics { 41 | val version = "3.2.2" 42 | val metrics = "nl.grons" %% "metrics-scala" % "3.5.6" 43 | val jvm = "io.dropwizard.metrics" % "metrics-jvm" % version 44 | val ehcache = "io.dropwizard.metrics" % "metrics-ehcache" % version intransitive() 45 | val healthChecks = "io.dropwizard.metrics" % "metrics-healthchecks" % version intransitive() 46 | val json = "io.dropwizard.metrics" % "metrics-json" % version 47 | val jettyServlet = "org.eclipse.jetty" % "jetty-servlet" % "9.3.16.v20170120" 48 | val servlets = "io.dropwizard.metrics" % "metrics-servlets" % version intransitive() 49 | val graphite = "io.dropwizard.metrics" % "metrics-graphite" % version intransitive() 50 | } 51 | 52 | object Utils { 53 | val scapegoatVersion = "1.3.8" 54 | val enumeratumVersion = "1.5.17" 55 | 56 | val commonsIo = "commons-io" % "commons-io" % "2.6" 57 | val commonsLang = "org.apache.commons" % "commons-lang3" % "3.8" 58 | val enumeratum = "com.beachape" %% "enumeratum-circe" % enumeratumVersion 59 | val scalaGuice = "net.codingwell" %% "scala-guice" % "4.2.1" 60 | val betterFiles = "com.github.pathikrit" %% "better-files" % "3.6.0" 61 | val scopts = "com.github.scopt" %% "scopt" % "3.7.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /project/Packaging.scala: -------------------------------------------------------------------------------- 1 | import com.typesafe.sbt.packager.Keys._ 2 | import com.typesafe.sbt.packager.debian.DebianPlugin.autoImport.Debian 3 | import com.typesafe.sbt.packager.docker.DockerPlugin.autoImport.{ Docker, dockerExposedPorts, dockerExposedVolumes } 4 | import com.typesafe.sbt.packager.jdkpackager.JDKPackagerPlugin.autoImport.{ JDKPackager, jdkAppIcon, jdkPackagerBasename } 5 | import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport.{ Universal, useNativeZip } 6 | import com.typesafe.sbt.packager.windows 7 | import com.typesafe.sbt.packager.windows.WindowsPlugin.autoImport.Windows 8 | import sbt.Keys._ 9 | import sbt._ 10 | 11 | object Packaging { 12 | private[this] lazy val iconGlob = sys.props("os.name").toLowerCase match { 13 | case os if os.contains("mac") => "*.icns" 14 | case os if os.contains("win") => "*.ico" 15 | case _ => "*.png" 16 | } 17 | 18 | private[this] def isConf(x: (File, String)) = x._1.getAbsolutePath.contains("conf/") 19 | 20 | val settings = useNativeZip ++ Seq( 21 | topLevelDirectory in Universal := None, 22 | packageSummary := description.value, 23 | packageDescription := description.value, 24 | 25 | mappings in Universal := (mappings in Universal).value.filterNot(isConf), 26 | 27 | // Linux Settings 28 | packageDescription in Debian := s"${Shared.projectName} Debian Package", 29 | topLevelDirectory in Debian := Some(Shared.projectId + "-" + Shared.Versions.app), 30 | debianNativeBuildOptions in Debian := Seq("-Zgzip", "-z3"), 31 | debianPackageRecommends in Debian ++= Seq("openjdk-8-jre"), 32 | rpmVendor := Shared.projectName, 33 | linuxPackageMappings := linuxPackageMappings.value.filter(_.fileData.config != "false"), 34 | 35 | // Windows settings 36 | mappings in Windows := (mappings in Windows).value.filterNot(isConf), 37 | //makeBatScript := Some(file(s"./src/deploy/package/windows/${Shared.projectId}.bat")), 38 | topLevelDirectory in Windows := Some(Shared.projectName), 39 | wixProductId := "5fee44ae-0989-429b-9b1a-de8ec7dd9af5", 40 | wixProductUpgradeId := "6d353c6a-6f39-48f1-afa8-2c5eb726a8b8", 41 | wixProductLicense := None,//Some(file("src/deploy/package/windows/license.rtf")), 42 | wixFeatures := makeWindowsFeatures((mappings in Windows).value), 43 | 44 | // Docker 45 | dockerExposedPorts := Seq(4260, 4261, 4262, 4263), 46 | defaultLinuxInstallLocation in Docker := s"/opt/${Shared.projectId}", 47 | packageName in Docker := packageName.value, 48 | dockerExposedVolumes := Seq(s"/opt/${Shared.projectId}"), 49 | version in Docker := version.value, 50 | 51 | // JDK Packager 52 | jdkAppIcon := (sourceDirectory.value ** iconGlob).getPaths.headOption.map(file), 53 | jdkPackagerBasename := Shared.projectName, 54 | name in JDKPackager := Shared.projectName, 55 | 56 | javaOptions in Universal ++= Seq( 57 | "-J-Xmx2g", 58 | "-J-Xms256m", 59 | s"-Dproject=${Shared.projectId}" 60 | ) 61 | ) 62 | 63 | private[this] def makeWindowsFeatures(mappings: Seq[(File, String)]): Seq[windows.WindowsFeature] = { 64 | import windows._ 65 | 66 | val files = for { 67 | (file, name) <- mappings 68 | if !file.isDirectory 69 | } yield ComponentFile(name, editable = false) 70 | 71 | val corePackage = WindowsFeature( 72 | id = WixHelper.cleanStringForId(s"${Shared.projectId}_core").takeRight(38), // Must be no longer 73 | title = "Core Files", 74 | desc = s"Core files for ${Shared.projectName}.", 75 | absent = "disallow", 76 | components = files 77 | ) 78 | val addBinToPath = WindowsFeature( 79 | id = "AddBinToPath", 80 | title = "Update PATH", 81 | desc = "Update PATH environment variables (requires restart).", 82 | components = Seq(AddDirectoryToPath("bin")) 83 | ) 84 | // val menuLinks = WindowsFeature( 85 | // id = "AddConfigLinks", 86 | // title = "Start Menu Links", 87 | // desc = "Adds start menu shortcuts.", 88 | // components = Seq(AddShortCuts(Seq(s"bin\\${Shared.projectId}.bat"))) 89 | // ) 90 | 91 | Seq(corePackage, addBinToPath/* , menuLinks */) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /project/Server.scala: -------------------------------------------------------------------------------- 1 | import com.sksamuel.scapegoat.sbt.ScapegoatSbtPlugin.autoImport._ 2 | import com.typesafe.sbt.digest.Import._ 3 | import com.typesafe.sbt.gzip.Import._ 4 | import com.typesafe.sbt.jse.JsEngineImport.JsEngineKeys 5 | import com.typesafe.sbt.less.Import._ 6 | import com.typesafe.sbt.packager.Keys._ 7 | import com.typesafe.sbt.packager.archetypes.JavaAppPackaging 8 | import com.typesafe.sbt.packager.debian.DebianPlugin 9 | import com.typesafe.sbt.packager.docker.DockerPlugin 10 | import com.typesafe.sbt.packager.jdkpackager.JDKPackagerPlugin 11 | import com.typesafe.sbt.packager.linux.LinuxPlugin 12 | import com.typesafe.sbt.packager.rpm.RpmPlugin 13 | import com.typesafe.sbt.packager.universal.UniversalPlugin 14 | import com.typesafe.sbt.packager.windows.WindowsPlugin 15 | import com.typesafe.sbt.web.Import._ 16 | import com.typesafe.sbt.web.SbtWeb 17 | import play.routes.compiler.InjectedRoutesGenerator 18 | import play.sbt.PlayImport.PlayKeys 19 | import play.sbt.routes.RoutesKeys.routesGenerator 20 | import play.sbt.PlayImport.PlayKeys._ 21 | import sbt.Keys._ 22 | import sbt._ 23 | import sbtassembly.AssemblyPlugin.autoImport._ 24 | 25 | object Server { 26 | private[this] val dependencies = { 27 | import Dependencies._ 28 | Seq( 29 | Akka.actor, Akka.logging, Play.playFilters, Play.guice, Play.playWs, Utils.enumeratum, WebJars.jquery, WebJars.fontAwesome, WebJars.materialize, 30 | Utils.commonsIo, Utils.betterFiles, Utils.commonsLang, Utils.scalaGuice, Utils.scopts, Akka.testkit, Play.playTest 31 | ) ++ Dependencies.Serialization.circeProjects.map(c => "io.circe" %% c % Dependencies.Serialization.circeVersion) 32 | } 33 | 34 | private[this] lazy val serverSettings = Shared.commonSettings ++ Seq( 35 | name := Shared.projectId, 36 | maintainer := "scala-js-typescript ", 37 | description := "scala-js-typescript", 38 | 39 | resolvers += Resolver.jcenterRepo, 40 | libraryDependencies ++= dependencies, 41 | 42 | routesGenerator := InjectedRoutesGenerator, 43 | externalizeResources := false, 44 | 45 | // Sbt-Web 46 | JsEngineKeys.engineType := JsEngineKeys.EngineType.Node, 47 | pipelineStages := Seq(digest, gzip), 48 | includeFilter in (Assets, LessKeys.less) := "*.less", 49 | excludeFilter in (Assets, LessKeys.less) := "_*.less", 50 | LessKeys.compress in Assets := true, 51 | 52 | // Fat-Jar Assembly 53 | fullClasspath in assembly += Attributed.blank(PlayKeys.playPackageAssets.value), 54 | mainClass in assembly := Some(Shared.projectName), 55 | 56 | // Code Quality 57 | scapegoatIgnoredFiles := Seq(".*/Row.scala", ".*/Routes.scala", ".*/ReverseRoutes.scala", ".*/JavaScriptReverseRoutes.scala", ".*/*.template.scala") 58 | ) 59 | 60 | lazy val server = Project(id = Shared.projectId, base = file(".")).enablePlugins( 61 | SbtWeb, play.sbt.PlayScala, JavaAppPackaging, 62 | UniversalPlugin, LinuxPlugin, DebianPlugin, RpmPlugin, DockerPlugin, WindowsPlugin, JDKPackagerPlugin 63 | ).settings(serverSettings: _*).settings(Packaging.settings: _*) 64 | } 65 | -------------------------------------------------------------------------------- /project/Shared.scala: -------------------------------------------------------------------------------- 1 | import Dependencies._ 2 | import com.sksamuel.scapegoat.sbt.ScapegoatSbtPlugin.autoImport._ 3 | import com.typesafe.sbt.SbtScalariform.{ ScalariformKeys, scalariformSettings } 4 | import net.virtualvoid.sbt.graph.DependencyGraphSettings.graphSettings 5 | import sbt.Keys._ 6 | import sbt._ 7 | 8 | object Shared { 9 | val projectId = "scala-js-typescript" 10 | val projectName = "scala-js-typescript" 11 | 12 | object Versions { 13 | val app = "1.0.0" 14 | val scala = "2.12.6" 15 | } 16 | 17 | lazy val commonSettings = Seq( 18 | version := Shared.Versions.app, 19 | scalaVersion := Shared.Versions.scala, 20 | 21 | scalacOptions := Seq( 22 | "-target:jvm-1.8", "-encoding", "UTF-8", "-feature", "-deprecation", "-explaintypes", "-feature", "-unchecked", 23 | "–Xcheck-null", "-Xfatal-warnings", /* "-Xlint", */ "-Xcheckinit", "-Xfuture", "-Yrangepos", "-Ypartial-unification", 24 | "-Yno-adapted-args", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-nullary-override", "-Ywarn-numeric-widen", "-Ywarn-infer-any" 25 | ), 26 | scalacOptions in Test ++= Seq("-Yrangepos"), 27 | 28 | publishMavenStyle := false, 29 | 30 | // Prevent Scaladoc 31 | publishArtifact in (Compile, packageDoc) := false, 32 | publishArtifact in packageDoc := false, 33 | sources in (Compile,doc) := Seq.empty, 34 | 35 | // Code Quality 36 | scapegoatVersion := Utils.scapegoatVersion, 37 | scapegoatDisabledInspections := Seq("MethodNames", "MethodReturningAny", "DuplicateImport"), 38 | scapegoatIgnoredFiles := Seq(".*/JsonSerializers.scala"), 39 | ScalariformKeys.preferences := ScalariformKeys.preferences.value 40 | ) ++ graphSettings ++ scalariformSettings 41 | 42 | def withProjects(p: Project, includes: Seq[Project]) = includes.foldLeft(p) { (proj, inc) => 43 | proj.aggregate(inc).dependsOn(inc) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.2.1 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | scalacOptions ++= Seq( "-unchecked", "-deprecation" ) 2 | 3 | resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/" 4 | 5 | // The Play plugin 6 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.19") 7 | 8 | // SBT-Web plugins 9 | addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.2") 10 | 11 | addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.4") 12 | 13 | addSbtPlugin("com.typesafe.sbt" % "sbt-gzip" % "1.0.2") 14 | 15 | // App Packaging 16 | addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.9") 17 | 18 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7") 19 | 20 | // Dependency Resolution 21 | addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") 22 | 23 | // Code Quality 24 | addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0") // scalastyle 25 | 26 | addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.7") // scapegoat 27 | 28 | addSbtPlugin("com.orrsella" % "sbt-stats" % "1.0.7") // stats 29 | 30 | addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.0") // dependencyGraph 31 | 32 | addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.3.4") // dependencyUpdates 33 | 34 | addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.1") // scalariformFormat 35 | 36 | addSbtPlugin("com.github.xuwei-k" % "sbt-class-diagram" % "0.2.1") 37 | -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | #2b5797 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/images/ui/favicon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleu/scala-js-typescript/e77c1803a0d384d70ffac2438dcbb9706bfac33a/public/images/ui/favicon/favicon.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "scala-js-typescript", 4 | "icons": [ 5 | { 6 | "src": "\/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image\/png" 9 | }, 10 | { 11 | "src": "\/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image\/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "display": "standalone", 18 | "version": "1.0", 19 | "default_locale": "en" 20 | } 21 | -------------------------------------------------------------------------------- /util/ts-dump/cycles.ts: -------------------------------------------------------------------------------- 1 | function isCyclic (obj: any) { 2 | var seenObjects: any[] = []; 3 | 4 | function detect (obj: any) { 5 | if (obj && typeof obj === 'object') { 6 | if (seenObjects.indexOf(obj) !== -1) { 7 | return true; 8 | } 9 | seenObjects.push(obj); 10 | for (var key in obj) { 11 | if (obj.hasOwnProperty(key) && detect(obj[key])) { 12 | console.log(obj, 'cycle at ' + key); 13 | return true; 14 | } 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | return detect(obj); 21 | } 22 | 23 | export {isCyclic} 24 | -------------------------------------------------------------------------------- /util/ts-dump/index.ts: -------------------------------------------------------------------------------- 1 | import Project, {Node, ScriptTarget, printNode, ts} from "ts-simple-ast"; 2 | import {isCyclic} from "./cycles"; 3 | import {getProperties} from "./props"; 4 | 5 | const project = new Project({ 6 | tsConfigFilePath: "tsconfig.json", 7 | addFilesFromTsConfig: false, 8 | 9 | compilerOptions: { 10 | target: ScriptTarget.ES3 11 | } 12 | }); 13 | 14 | const sourceFile = project.addExistingSourceFile("tests/jQuery.d.ts"); 15 | 16 | function process(n: Node) { 17 | const ret = getProperties(n); 18 | includeChildren(n, ret); 19 | 20 | return ret; 21 | } 22 | 23 | function includeChildren(n: Node, ret: any) { 24 | switch(ret.kind) { 25 | case "": 26 | case "?": 27 | break; 28 | default: 29 | const kids = n.getChildren().map(process); 30 | if(kids.length != 0) { 31 | ret.children = kids; 32 | } 33 | } 34 | } 35 | 36 | const ret = sourceFile.getChildren().map((n, i, c) => process(n)); 37 | ret.forEach(isCyclic); 38 | console.info(JSON.stringify(ret, null, 2)); 39 | -------------------------------------------------------------------------------- /util/ts-dump/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-dump", 3 | "version": "1.0.0", 4 | "description": "Dumps TypeScript AST to JSON", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "dependencies": { 10 | "ts-simple-ast": "^16.0.0" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "author": "KyleU", 17 | "license": "Undecided" 18 | } 19 | -------------------------------------------------------------------------------- /util/ts-dump/props.ts: -------------------------------------------------------------------------------- 1 | import {Node, ts} from "ts-simple-ast"; 2 | 3 | function getProperties(n: Node) { 4 | var ret: any = {}; 5 | 6 | ret.kind = n.getKindName(); 7 | ret.start = n.getStart(false); 8 | ret.width = n.getWidth(); 9 | ret.comments = n.getLeadingCommentRanges().concat(n.getTrailingCommentRanges()).map(c => c.getText()); 10 | ret.childCount = n.getChildCount(); 11 | 12 | switch (ret.kind) { 13 | case "SyntaxList": 14 | processSyntax(n as Node, ret); 15 | break; 16 | case "ModuleDeclaration": 17 | processModule(n as Node, ret); 18 | break; 19 | default: 20 | ret.todo = ret.kind; 21 | } 22 | 23 | return ret; 24 | } 25 | 26 | function processSyntax(n: Node, ret: any) { 27 | ret.file = n.getSourceFile().getBaseName(); 28 | } 29 | 30 | function processModule(n: Node, ret: any) { 31 | ret.name = n.compilerNode.name.getText; 32 | } 33 | 34 | export {getProperties}; 35 | --------------------------------------------------------------------------------