├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── amd ├── README.md ├── app.css ├── app.ts ├── default.html ├── greeter.ts └── tsconfig.json ├── angular1 ├── .bowerrc ├── .gitignore ├── .jshintrc ├── .travis.yml ├── CONVERSION.md ├── LICENSE ├── README-JS.md ├── README.md ├── app │ ├── app.css │ ├── app.ts │ ├── components │ │ └── version │ │ │ ├── interpolate-filter.ts │ │ │ ├── interpolate-filter_test.ts │ │ │ ├── version-directive.ts │ │ │ ├── version-directive_test.ts │ │ │ ├── version.ts │ │ │ └── version_test.ts │ ├── index-async.html │ ├── index.html │ ├── tsconfig.json │ ├── typings │ │ ├── angularjs │ │ │ ├── angular-mocks.d.ts │ │ │ └── angular.d.ts │ │ ├── jasmine │ │ │ └── jasmine.d.ts │ │ ├── jquery │ │ │ └── jquery.d.ts │ │ ├── karma-jasmine │ │ │ └── karma-jasmine.d.ts │ │ ├── selenium-webdriver │ │ │ └── selenium-webdriver.d.ts │ │ └── tsd.d.ts │ ├── view1 │ │ ├── view1.html │ │ ├── view1.ts │ │ └── view1_test.ts │ └── view2 │ │ ├── view2.html │ │ ├── view2.ts │ │ └── view2_test.ts ├── bower.json ├── e2e-tests │ ├── protractor.conf.ts │ ├── scenarios.ts │ ├── tsconfig.json │ └── typings │ │ ├── angular-protractor │ │ └── angular-protractor.d.ts │ │ ├── angularjs │ │ ├── angular-mocks.d.ts │ │ └── angular.d.ts │ │ ├── jasmine │ │ └── jasmine.d.ts │ │ ├── jquery │ │ └── jquery.d.ts │ │ ├── karma-jasmine │ │ └── karma-jasmine.d.ts │ │ ├── selenium-webdriver │ │ └── selenium-webdriver.d.ts │ │ └── tsd.d.ts ├── karma.conf.js └── package.json ├── angular2 ├── .gitignore ├── README.md ├── app │ └── todo.ts ├── css │ ├── base.css │ └── bg.png ├── firebase │ ├── angularfire.d.ts │ ├── angularfire.js │ ├── firebase.d.ts │ └── firebase.js ├── index.html ├── package.json ├── todo.html └── tsconfig.json ├── async ├── .gitignore ├── README.md ├── bin │ └── ts-async-github-sample ├── gulpfile.js ├── jsconfig.json ├── package.json └── src │ └── lib │ ├── github.ts │ ├── index.ts │ ├── tsconfig.json │ ├── tsd.json │ ├── typings │ ├── node │ │ └── node.d.ts │ └── tsd.d.ts │ └── utils.ts ├── browserify ├── .gitignore ├── README.md ├── app.css ├── index.html ├── package.json ├── src │ ├── app.ts │ ├── node.d.ts │ └── timeReporter.ts └── tsconfig.json ├── buildall.cmd ├── d3 ├── README.md ├── d3.d.ts ├── data.ts ├── perf.html └── tsconfig.json ├── greeter ├── README.md ├── greeter.html ├── greeter.ts └── tsconfig.json ├── imageboard ├── ImageBoard.csproj ├── ImageBoardNodeProj.njsproj ├── ImageBoardNodeProj.sln ├── README.md ├── app.ts ├── db.ts ├── dump │ └── mydb │ │ ├── images.bson │ │ ├── images.metadata.json │ │ ├── users.bson │ │ └── users.metadata.json ├── package.json ├── public │ ├── javascripts │ │ └── fb.js │ └── stylesheets │ │ └── style.css ├── routes │ └── index.ts ├── tsconfig.json ├── tsd.json └── views │ ├── board.jade │ ├── image.jade │ ├── index.jade │ ├── layout.jade │ ├── newboard.jade │ ├── newpin.jade │ └── user.jade ├── interfaces ├── README.md ├── interfaces.ts └── tsconfig.json ├── jquery ├── README.md ├── package.json ├── parallax.html ├── parallax.ts ├── starfield.png └── tsconfig.json ├── js-and-ts ├── README.md ├── format.js ├── robot.ts └── tsconfig.json ├── jspm ├── .gitignore ├── README.md ├── index.html ├── jspm.config.js ├── package.json ├── src │ ├── app.ts │ ├── core-js.d.ts │ └── greeter.ts └── tsconfig.json ├── jsx ├── .gitignore ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── require-config.js ├── src │ ├── app.tsx │ └── greeter.tsx └── tsconfig.json ├── mankala ├── Base.ts ├── Driver.ts ├── Features.ts ├── Game.ts ├── Position.ts ├── README.md ├── geometry.ts ├── play.css ├── play.html └── tsconfig.json ├── node ├── .gitignore ├── README.md ├── index.ts ├── lorem.txt ├── package.json ├── src │ ├── APIClient.ts │ ├── APIServer.ts │ ├── HttpServer.ts │ ├── TcpServer.ts │ ├── Wikipedia.ts │ └── WordCounter.ts ├── tsconfig.json └── tslint.json ├── raytracer ├── README.md ├── raytracer.html ├── raytracer.ts └── tsconfig.json ├── react-flux-babel-karma ├── .gitignore ├── LICENSE ├── README.md ├── gulp │ ├── .eslintrc │ ├── clean.js │ ├── inject.js │ ├── staticFiles.js │ ├── tests.js │ └── webpack.js ├── gulpFile.js ├── karma.conf.js ├── package.json ├── src │ ├── actions │ │ └── GreetingActions.ts │ ├── components │ │ ├── App.tsx │ │ ├── Greeting.tsx │ │ └── WhoToGreet.tsx │ ├── dispatcher │ │ └── AppDispatcher.ts │ ├── index.html │ ├── main.tsx │ ├── stores │ │ ├── FluxStore.ts │ │ └── GreetingStore.ts │ └── types │ │ └── GreetingState.ts ├── test │ ├── components │ │ ├── App.tests.tsx │ │ ├── Greeting.tests.tsx │ │ └── WhoToGreet.tests.tsx │ ├── main.js │ └── stores │ │ └── GreetingStore.tests.ts ├── tsconfig.json └── webpack.config.js ├── simple ├── README.md ├── animals.ts └── tsconfig.json ├── systemjs ├── .gitignore ├── README.md ├── app.css ├── app.ts ├── greeter.ts ├── index.html ├── package.json └── tsconfig.json ├── todomvc ├── .gitignore ├── README.md ├── css │ ├── destroy.png │ └── todos.css ├── index.html ├── js │ └── todos.ts ├── package.json └── tsconfig.json ├── umd ├── .gitignore ├── README.md ├── browser │ ├── app.css │ └── app.ts ├── index.html ├── node │ ├── app.ts │ └── os.d.ts ├── package.json ├── shared │ └── timeReporter.ts └── tsconfig.json └── warship ├── README.md ├── default.html ├── img ├── bg.jpg └── bg2.jpg ├── jquery.d.ts ├── jqueryui.d.ts ├── styles.css ├── tsconfig.json └── warship.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform EOL normalization 2 | * text=auto 3 | 4 | # Custom 5 | *.ts text 6 | *.jade text 7 | *.md text 8 | *.js text 9 | *.cmd text eol=crlf 10 | *.sln text eol=crlf 11 | *.csproj text eol=crlf 12 | *.jsproj text eol=crlf 13 | *.njsproj text eol=crlf 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # Roslyn cache directories 20 | *.ide/ 21 | 22 | # MSTest test Results 23 | [Tt]est[Rr]esult*/ 24 | [Bb]uild[Ll]og.* 25 | 26 | #NUNIT 27 | *.VisualState.xml 28 | TestResult.xml 29 | 30 | # Build Results of an ATL Project 31 | [Dd]ebugPS/ 32 | [Rr]eleasePS/ 33 | dlldata.c 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opensdf 68 | *.sdf 69 | *.cachefile 70 | 71 | # Visual Studio profiler 72 | *.psess 73 | *.vsp 74 | *.vspx 75 | 76 | # TFS 2012 Local Workspace 77 | $tf/ 78 | 79 | # Guidance Automation Toolkit 80 | *.gpState 81 | 82 | # ReSharper is a .NET coding add-in 83 | _ReSharper*/ 84 | *.[Rr]e[Ss]harper 85 | *.DotSettings.user 86 | 87 | # JustCode is a .NET coding addin-in 88 | .JustCode 89 | 90 | # TeamCity is a build add-in 91 | _TeamCity* 92 | 93 | # DotCover is a Code Coverage Tool 94 | *.dotCover 95 | 96 | # NCrunch 97 | _NCrunch_* 98 | .*crunch*.local.xml 99 | 100 | # MightyMoose 101 | *.mm.* 102 | AutoTest.Net/ 103 | 104 | # Web workbench (sass) 105 | .sass-cache/ 106 | 107 | # Installshield output folder 108 | [Ee]xpress/ 109 | 110 | # DocProject is a documentation generator add-in 111 | DocProject/buildhelp/ 112 | DocProject/Help/*.HxT 113 | DocProject/Help/*.HxC 114 | DocProject/Help/*.hhc 115 | DocProject/Help/*.hhk 116 | DocProject/Help/*.hhp 117 | DocProject/Help/Html2 118 | DocProject/Help/html 119 | 120 | # Click-Once directory 121 | publish/ 122 | 123 | # Publish Web Output 124 | *.[Pp]ublish.xml 125 | *.azurePubxml 126 | ## TODO: Comment the next line if you want to checkin your 127 | ## web deploy settings but do note that will include unencrypted 128 | ## passwords 129 | #*.pubxml 130 | 131 | # NuGet Packages Directory 132 | packages/* 133 | ## TODO: If the tool you use requires repositories.config 134 | ## uncomment the next line 135 | #!packages/repositories.config 136 | 137 | # Enable "build/" folder in the NuGet Packages folder since 138 | # NuGet packages use it for MSBuild targets. 139 | # This line needs to be after the ignore of the build folder 140 | # (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | bower_components/ 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file 168 | # to a newer Visual Studio version. Backup files are not needed, 169 | # because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | *.mdf 177 | *.ldf 178 | 179 | # Business Intelligence projects 180 | *.rdl.data 181 | *.bim.layout 182 | *.bim_*.settings 183 | 184 | # Microsoft Fakes 185 | FakesAssemblies/ 186 | 187 | # LightSwitch generated files 188 | GeneratedArtifacts/ 189 | _Pvt_Extensions/ 190 | ModelManifest.xml 191 | 192 | node_modules/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | ## Contributing fixes to existing samples 4 | 5 | A bug must have an issue tracking it in the issue tracker that has been approved (labeled "help wanted") by the TypeScript team. 6 | Your pull request should include a link to the bug that you are fixing. 7 | If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort. 8 | 9 | ## Contributing new samples 10 | 11 | New samples may be accepted, but will need to first be approved (labeled "help wanted" by a TypeScript coordinator) in the suggestion issue. 12 | 13 | For new samples, please provide a detailed explanation of the intended sample, list of technologies or tools used, and an explanation of why existing samples are not sufficient and a new sample is needed. 14 | 15 | A sample is meant to showcase a specific technology or toolchain integration with TypeScript; it is not meant to be a template that users would use to get a project going. 16 | A sample should only include tools/technologies that serve the main technology it covers; for instance, a sample for a UI framework should not include a test framework integration. 17 | 18 | A sample should be well documented. 19 | Please include comments in code as well as content in the a `README.md` explaining why steps are being taken. 20 | Comments should also be included in build files if applicable. 21 | A good sample `README.md` should read like a walkthrough, guiding the reader through different steps of setting up and building the sample. 22 | See [TypeScript quick start samples](https://github.com/Microsoft/TypeScript-Handbook/tree/master/pages/quick-start) for guidance. 23 | 24 | A sample should be self-contained. 25 | [npm](https://www.npmjs.com/) is the recommended way of acquiring dependencies. 26 | [typings](https://github.com/typings/typings) is the recommended way of acquiring definition files. 27 | 28 | A sample should be IDE/editor-friendly. Please include a `tsconfig.json` file at the root. 29 | 30 | A sample should have no OS dependency. 31 | 32 | ## Legal 33 | 34 | You will need to complete a Contributor License Agreement (CLA). 35 | Briefly, this agreement testifies that you are granting us permission to use the submitted change according to the terms of the project's license, and that the work being submitted is under appropriate copyright. 36 | 37 | Please submit a Contributor License Agreement (CLA) before submitting a pull request. 38 | You may visit https://cla.microsoft.com to sign digitally. 39 | Alternatively, download the agreement ([Microsoft Contribution License Agreement.docx](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=822190) or [Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, and email it back to . 40 | Be sure to include your GitHub user name along with the agreement. Once we have received the signed CLA, we'll review the request. 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Samples 2 | 3 | Most of the samples here will assume that you have TypeScript installed. 4 | You can get TypeScript with Visual Studio, NuGet, or with npm: 5 | 6 | ```shell 7 | npm install -g typescript 8 | ``` 9 | 10 | To compile each sample, `cd` into the directory and use the `tsc` command to compile. 11 | `tsc` will use each directory's `tsconfig.json` to get specific compiler options. 12 | 13 | ##### [AMD Modules](amd/README.md) 14 | 15 | ##### [Angular Seed TypeScript](angular1/README.md) 16 | 17 | ##### [Angular 2 TypeScript](angular2/README.md) 18 | 19 | ##### [Async Functions](async/README.md) 20 | 21 | ##### [Browserify](browserify/README.md) 22 | 23 | ##### [D3](d3/README.md) 24 | 25 | ##### [React + Flux + Babel + Karma: The Secret Recipe](react-flux-babel-karma/README.md) 26 | 27 | ##### [Greeter](greeter/README.md) 28 | 29 | ##### [Image Board](imageboard/README.md) 30 | 31 | ##### [interfaces](interfaces/README.md) 32 | 33 | ##### [JQuery Parallax Starfield](jquery/README.md) 34 | 35 | ##### [JSPM](jspm/README.md) 36 | 37 | ##### [jsx-demo](jsx/README.md) 38 | 39 | ##### [Mankala](mankala/README.md) 40 | 41 | ##### [Node.js](node/README.md) 42 | 43 | ##### [Raytracer](raytracer/README.md) 44 | 45 | ##### [Simple](simple/README.md) 46 | 47 | ##### [SystemJS](systemjs/README.md) 48 | 49 | ##### [Todo MVC](todomvc/README.md) 50 | 51 | ##### [umd](umd/README.md) 52 | 53 | ##### [Warship Combat](warship/README.md) 54 | -------------------------------------------------------------------------------- /amd/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: AMD Modules 2 | 3 | ## Overview 4 | 5 | This sample shows a simple Typescript application using an AMD module. 6 | It uses [require.js](http://www.requirejs.org/) to load `app.js` once compiled from `app.ts` 7 | 8 | ## Running 9 | 10 | ``` 11 | tsc --sourcemap --module amd app.ts 12 | start default.html 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /amd/app.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-family: 'Segoe UI', sans-serif 4 | } 5 | 6 | span { 7 | font-style: italic 8 | } -------------------------------------------------------------------------------- /amd/app.ts: -------------------------------------------------------------------------------- 1 | import model = require("greeter") 2 | 3 | var el = document.getElementById('content'); 4 | var greeter = new model.Greeter(el); 5 | greeter.start(); 6 | -------------------------------------------------------------------------------- /amd/default.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | TypeScript HTML App 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 |

TypeScript HTML App

18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /amd/greeter.ts: -------------------------------------------------------------------------------- 1 | export class Greeter { 2 | element: HTMLElement; 3 | span: HTMLElement; 4 | timerToken: number; 5 | 6 | constructor (element: HTMLElement) { 7 | this.element = element; 8 | this.element.innerHTML += "The time is: "; 9 | this.span = document.createElement('span'); 10 | this.element.appendChild(this.span); 11 | this.span.innerHTML = new Date().toUTCString(); 12 | } 13 | 14 | start() { 15 | this.timerToken = setInterval(() => this.span.innerHTML = new Date().toUTCString(), 500); 16 | } 17 | 18 | stop() { 19 | clearInterval(this.timerToken); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /amd/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "amd", 4 | "sourceMap": true 5 | }, 6 | "files": [ 7 | "app.ts" 8 | ] 9 | } -------------------------------------------------------------------------------- /angular1/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } -------------------------------------------------------------------------------- /angular1/.gitignore: -------------------------------------------------------------------------------- 1 | logs/* 2 | !.gitkeep 3 | node_modules/ 4 | bower_components/ 5 | tmp 6 | .DS_Store 7 | .idea 8 | app/**/*.js 9 | e2e-tests/**/*.js -------------------------------------------------------------------------------- /angular1/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globalstrict": true, 3 | "globals": { 4 | "angular": false, 5 | "describe": false, 6 | "it": false, 7 | "expect": false, 8 | "beforeEach": false, 9 | "afterEach": false, 10 | "module": false, 11 | "inject": false 12 | } 13 | } -------------------------------------------------------------------------------- /angular1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | before_script: 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | - npm start > /dev/null & 9 | - npm run update-webdriver 10 | - sleep 1 # give server time to start 11 | 12 | script: 13 | - node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox 14 | - node_modules/.bin/protractor e2e-tests/protractor.conf.js --browser=firefox 15 | -------------------------------------------------------------------------------- /angular1/CONVERSION.md: -------------------------------------------------------------------------------- 1 | The following is the list of modifications made to change the JS project to a TS Project: 2 | * Moved original README.md to README-JS.md and added this README.md and CONVERSION.md 3 | * Installed TypeScript typings for angular and related libs `tsd install angular jquery jasmine karma-jasmine angular-mocks angular-protractor selenium-webdriver --save` 4 | * Added 2 `tsconfig.json` files, one for `app` and another for `e2e-tests`. Two files are needed because of different typings for each. 5 | * Renamed the `.js` files to `.ts`. 6 | * As a sample : Converted controller `View1` and `View2` *functions* to *classes* and added a type annotation to use these from tests in a type checked way. 7 | * Minor modifications of typings needed because of conflict in `jquery` vs. `protractor` : https://github.com/borisyankov/DefinitelyTyped/issues/2734. 8 | * Remove `$` from `jquery.d.ts` in `e2e-tests`. 9 | * Remove `protractor` def from `app`. 10 | 11 | You will notice that stuff like `angular`, `mocks` etc will light up with IntelliSense and you will get errors if you try to misuse these. 12 | -------------------------------------------------------------------------------- /angular1/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2014 Google, Inc. http://angularjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /angular1/README.md: -------------------------------------------------------------------------------- 1 | # Angular Seed TypeScript 2 | This is based on https://github.com/angular/angular-seed. If you are curious about how the conversion of the JS project was done to the TS project checkout [CONVERSION.md](./CONVERSION.md). 3 | 4 | ## Running 5 | The following are specific to TypeScript 6 | 7 | Setup TypeScript: 8 | ```bash 9 | npm install typescript -g 10 | npm install tsd -g 11 | ``` 12 | Start the TypeScript compiler in watch mode (either in the `app` folder or in the `e2e-tests` folder) and **leave it running**: 13 | 14 | ```bash 15 | # For app 16 | tsc --watch --p app 17 | # For e2e-tests 18 | tsc --watch --p e2e-tests 19 | ``` 20 | 21 | That's it. You have typescript setup and ready to go. Now you can follow the standard steps of the original Angular-Seed JavaScript project in a new window using [README-JS](./README-JS.md) starting at the [install dependencies](./README-JS.md#install-dependencies) section. 22 | 23 | **TIP**: *Abriged the remaining JS steps for a quick start:* 24 | ```bash 25 | npm install 26 | npm start 27 | ``` 28 | and visit : http://localhost:8000/app/ 29 | -------------------------------------------------------------------------------- /angular1/app/app.css: -------------------------------------------------------------------------------- 1 | /* app css stylesheet */ 2 | 3 | .menu { 4 | list-style: none; 5 | border-bottom: 0.1em solid black; 6 | margin-bottom: 2em; 7 | padding: 0 0 0.5em; 8 | } 9 | 10 | .menu:before { 11 | content: "["; 12 | } 13 | 14 | .menu:after { 15 | content: "]"; 16 | } 17 | 18 | .menu > li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /angular1/app/app.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Declare app level module which depends on views, and components 4 | angular.module('myApp', [ 5 | 'ngRoute', 6 | 'myApp.view1', 7 | 'myApp.view2', 8 | 'myApp.version' 9 | ]) 10 | .config(['$routeProvider', $routeProvider => { 11 | $routeProvider.otherwise({ redirectTo: '/view1' }); 12 | }]); 13 | -------------------------------------------------------------------------------- /angular1/app/components/version/interpolate-filter.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('myApp.version.interpolate-filter', []) 4 | .filter('interpolate', ['version', version => { 5 | return text => String(text).replace(/\%VERSION\%/mg, version); 6 | }]); 7 | -------------------------------------------------------------------------------- /angular1/app/components/version/interpolate-filter_test.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('myApp.version module', () => { 4 | beforeEach(module('myApp.version')); 5 | 6 | describe('interpolate filter', () => { 7 | beforeEach(module($provide => { 8 | $provide.value('version', 'TEST_VER'); 9 | })); 10 | 11 | it('should replace VERSION', inject(interpolateFilter => { 12 | expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after'); 13 | })); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /angular1/app/components/version/version-directive.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('myApp.version.version-directive', []) 4 | .directive('appVersion', ['version', version => { 5 | return (scope, element, attributes) => { 6 | element.text(version); 7 | }; 8 | }]); 9 | -------------------------------------------------------------------------------- /angular1/app/components/version/version-directive_test.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('myApp.version module', () => { 4 | beforeEach(module('myApp.version')); 5 | 6 | describe('app-version directive', () => { 7 | it('should print current version', () => { 8 | module($provide => { 9 | $provide.value('version', 'TEST_VER'); 10 | }); 11 | 12 | inject(($compile, $rootScope) => { 13 | let element = $compile('')($rootScope); 14 | expect(element.text()).toEqual('TEST_VER'); 15 | }); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /angular1/app/components/version/version.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('myApp.version', [ 4 | 'myApp.version.interpolate-filter', 5 | 'myApp.version.version-directive' 6 | ]) 7 | .value('version', '0.1'); 8 | -------------------------------------------------------------------------------- /angular1/app/components/version/version_test.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('myApp.version module', () => { 4 | beforeEach(module('myApp.version')); 5 | 6 | describe('version service', () => { 7 | it('should return current version', inject(version => { 8 | expect(version).toEqual('0.1'); 9 | })); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /angular1/app/index-async.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 44 | My AngularJS App 45 | 46 | 47 | 48 | 52 | 53 |
54 | 55 |
Angular seed app: v
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /angular1/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | My AngularJS App 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 26 | 27 |
28 | 29 |
Angular seed app: v
30 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /angular1/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /angular1/app/typings/karma-jasmine/karma-jasmine.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for karma-jasmine plugin 2 | // Project: https://github.com/karma-runner/karma-jasmine 3 | // Definitions by: Michel Salib 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare function ddescribe(description: string, specDefinitions: () => void): void; 9 | declare function iit(expectation: string, assertion: () => void): void; 10 | -------------------------------------------------------------------------------- /angular1/app/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | -------------------------------------------------------------------------------- /angular1/app/view1/view1.html: -------------------------------------------------------------------------------- 1 |

This is the partial for view 1.

2 | -------------------------------------------------------------------------------- /angular1/app/view1/view1.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class View1Controller { 4 | static $inject = []; 5 | } 6 | 7 | angular.module('myApp.view1', ['ngRoute']) 8 | .config(['$routeProvider', $routeProvider => { 9 | $routeProvider.when('/view1', { 10 | templateUrl: 'view1/view1.html', 11 | controller: 'View1Ctrl' 12 | }); 13 | }]) 14 | .controller('View1Ctrl', View1Controller); 15 | -------------------------------------------------------------------------------- /angular1/app/view1/view1_test.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('myApp.view1 module', () => { 4 | beforeEach(module('myApp.view1')); 5 | 6 | describe('view1 controller', () => { 7 | it('should be defined', inject($controller => { 8 | let view1Ctrl: View1Controller = $controller('View1Ctrl'); 9 | expect(view1Ctrl).toBeDefined(); 10 | })); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /angular1/app/view2/view2.html: -------------------------------------------------------------------------------- 1 |

This is the partial for view 2.

2 |

3 | Showing of 'interpolate' filter: 4 | {{ 'Current version is v%VERSION%.' | interpolate }} 5 |

6 | -------------------------------------------------------------------------------- /angular1/app/view2/view2.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class View2Controller { 4 | static $inject = []; 5 | } 6 | 7 | angular.module('myApp.view2', ['ngRoute']) 8 | .config(['$routeProvider', $routeProvider => { 9 | $routeProvider.when('/view2', { 10 | templateUrl: 'view2/view2.html', 11 | controller: 'View2Ctrl' 12 | }); 13 | }]) 14 | .controller('View2Ctrl', View2Controller); 15 | -------------------------------------------------------------------------------- /angular1/app/view2/view2_test.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('myApp.view2 module', () => { 4 | beforeEach(module('myApp.view2')); 5 | 6 | describe('view2 controller', () => { 7 | it('should be defined', inject($controller => { 8 | let view2Ctrl: View2Controller = $controller('View2Ctrl'); 9 | expect(view2Ctrl).toBeDefined(); 10 | })); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /angular1/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed", 3 | "description": "A starter project for AngularJS using TypeScript", 4 | "version": "0.0.0", 5 | "homepage": "https://github.com/Microsoft/TypeScriptSamples/angular1", 6 | "license": "MIT", 7 | "private": true, 8 | "dependencies": { 9 | "angular": "~1.4.0", 10 | "angular-route": "~1.4.0", 11 | "angular-loader": "~1.4.0", 12 | "angular-mocks": "~1.4.0", 13 | "html5-boilerplate": "~5.2.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /angular1/e2e-tests/protractor.conf.ts: -------------------------------------------------------------------------------- 1 | export var config = { 2 | allScriptsTimeout: 11000, 3 | 4 | specs: [ 5 | '*.js' 6 | ], 7 | 8 | capabilities: { 9 | 'browserName': 'chrome' 10 | }, 11 | 12 | baseUrl: 'http://localhost:8000/app/', 13 | 14 | framework: 'jasmine', 15 | 16 | jasmineNodeOpts: { 17 | defaultTimeoutInterval: 30000 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /angular1/e2e-tests/scenarios.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* https://github.com/angular/protractor/blob/master/docs/toc.md */ 4 | 5 | describe('my app', () => { 6 | it('should automatically redirect to /view1 when location hash/fragment is empty', () => { 7 | browser.get('index.html'); 8 | expect(browser.getLocationAbsUrl()).toMatch("/view1"); 9 | }); 10 | 11 | describe('view1', () => { 12 | beforeEach(() => { 13 | browser.get('index.html#/view1'); 14 | }); 15 | 16 | it('should render view1 when user navigates to /view1', () => { 17 | expect(element.all(by.css('[ng-view] p')).first().getText()).toMatch(/partial for view 1/); 18 | }); 19 | }); 20 | 21 | describe('view2', () => { 22 | beforeEach(() => { 23 | browser.get('index.html#/view2'); 24 | }); 25 | 26 | it('should render view2 when user navigates to /view2', () => { 27 | expect(element.all(by.css('[ng-view] p')).first().getText()).toMatch(/partial for view 2/); 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /angular1/e2e-tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "filesGlob": [ 3 | "../app/**/*.ts", 4 | "!../app/typings/**/*.ts", 5 | "./**/*.ts", 6 | "./typings/**/*.ts" 7 | ], 8 | "compilerOptions": { 9 | "module": "commonjs" 10 | }, 11 | "files": [ 12 | "../app/app.ts", 13 | "../app/components/version/interpolate-filter.ts", 14 | "../app/components/version/interpolate-filter_test.ts", 15 | "../app/components/version/version-directive.ts", 16 | "../app/components/version/version-directive_test.ts", 17 | "../app/components/version/version.ts", 18 | "../app/components/version/version_test.ts", 19 | "../app/view1/view1.ts", 20 | "../app/view1/view1_test.ts", 21 | "../app/view2/view2.ts", 22 | "../app/view2/view2_test.ts", 23 | "./protractor.conf.ts", 24 | "./scenarios.ts", 25 | "./typings/angular-protractor/angular-protractor.d.ts", 26 | "./typings/angularjs/angular-mocks.d.ts", 27 | "./typings/angularjs/angular.d.ts", 28 | "./typings/jasmine/jasmine.d.ts", 29 | "./typings/jquery/jquery.d.ts", 30 | "./typings/karma-jasmine/karma-jasmine.d.ts", 31 | "./typings/selenium-webdriver/selenium-webdriver.d.ts", 32 | "./typings/tsd.d.ts" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /angular1/e2e-tests/typings/karma-jasmine/karma-jasmine.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for karma-jasmine plugin 2 | // Project: https://github.com/karma-runner/karma-jasmine 3 | // Definitions by: Michel Salib 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare function ddescribe(description: string, specDefinitions: () => void): void; 9 | declare function iit(expectation: string, assertion: () => void): void; 10 | -------------------------------------------------------------------------------- /angular1/e2e-tests/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | -------------------------------------------------------------------------------- /angular1/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config){ 2 | config.set({ 3 | 4 | basePath : './', 5 | 6 | files : [ 7 | 'app/bower_components/angular/angular.js', 8 | 'app/bower_components/angular-route/angular-route.js', 9 | 'app/bower_components/angular-mocks/angular-mocks.js', 10 | 'app/components/**/*.js', 11 | 'app/view*/**/*.js' 12 | ], 13 | 14 | autoWatch : true, 15 | 16 | frameworks: ['jasmine'], 17 | 18 | browsers : ['Chrome'], 19 | 20 | plugins : [ 21 | 'karma-chrome-launcher', 22 | 'karma-firefox-launcher', 23 | 'karma-jasmine', 24 | 'karma-junit-reporter' 25 | ], 26 | 27 | junitReporter : { 28 | outputFile: 'test_out/unit.xml', 29 | suite: 'unit' 30 | } 31 | 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /angular1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed", 3 | "private": true, 4 | "version": "0.0.0", 5 | "description": "A starter project for AngularJS using TypeScript", 6 | "repository": "https://github.com/Microsoft/TypeScriptSamples/angular1", 7 | "license": "MIT", 8 | "devDependencies": { 9 | "bower": "^1.3.1", 10 | "http-server": "^0.6.1", 11 | "jasmine-core": "^2.3.4", 12 | "karma": "~0.12", 13 | "karma-chrome-launcher": "^0.1.12", 14 | "karma-firefox-launcher": "^0.1.6", 15 | "karma-jasmine": "^0.3.5", 16 | "karma-junit-reporter": "^0.2.2", 17 | "protractor": "^2.1.0", 18 | "shelljs": "^0.2.6" 19 | }, 20 | "scripts": { 21 | "postinstall": "bower install", 22 | 23 | "prestart": "npm install", 24 | "start": "http-server -a localhost -p 8000 -c-1", 25 | 26 | "pretest": "npm install", 27 | "test": "karma start karma.conf.js", 28 | "test-single-run": "karma start karma.conf.js --single-run", 29 | 30 | "preupdate-webdriver": "npm install", 31 | "update-webdriver": "webdriver-manager update", 32 | 33 | "preprotractor": "npm run update-webdriver", 34 | "protractor": "protractor e2e-tests/protractor.conf.js", 35 | 36 | "update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + sed(/sourceMappingURL=angular-loader.min.js.map/,'sourceMappingURL=bower_components/angular-loader/angular-loader.min.js.map','app/bower_components/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'app/index-async.html');\"" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /angular2/.gitignore: -------------------------------------------------------------------------------- 1 | todo.js 2 | node_modules -------------------------------------------------------------------------------- /angular2/README.md: -------------------------------------------------------------------------------- 1 | **Fetch dependencies:** 2 | ``` 3 | npm install 4 | ``` 5 | 6 | **Build and run (combines 'build' and 'run server' commands using the default port 8080)** 7 | ``` 8 | npm start 9 | ``` 10 | 11 | **Build** 12 | ``` 13 | node node_modules/typescript/lib/tsc.js 14 | ``` 15 | 16 | **Run server** 17 | ``` 18 | node node_modules/http-server/bin/http-server -p 8080 19 | ``` 20 | 21 | '-p' sets the port to use, default port is 8080. If it is taken pick any port that is free. 22 | After server is started open 'localhost:8080' in a browser. -------------------------------------------------------------------------------- /angular2/app/todo.ts: -------------------------------------------------------------------------------- 1 | import {Component, bootstrap, NgFor, provide} from 'angular2/angular2'; 2 | import {AngularFire, FirebaseArray} from '../firebase/angularfire'; 3 | 4 | @Component({ 5 | selector: 'todo-app', 6 | providers: [ 7 | AngularFire, 8 | provide(Firebase, { useValue: new Firebase('https://webapi.firebaseio-demo.com/test') }) 9 | ], 10 | directives: [NgFor], 11 | templateUrl: 'todo.html' 12 | }) 13 | class TodoApp { 14 | todoService: FirebaseArray; 15 | todoEdit: any; 16 | 17 | constructor(sync: AngularFire) { 18 | this.todoService = sync.asArray(); 19 | this.todoEdit = null; 20 | } 21 | enterTodo($event, newTodo) { 22 | if($event.which === 13) { // ENTER_KEY 23 | this.addTodo(newTodo.value); 24 | newTodo.value = ''; 25 | } 26 | } 27 | editTodo($event, todo) { 28 | this.todoEdit = todo; 29 | } 30 | doneEditing($event, todo) { 31 | var which = $event.which; 32 | var target = $event.target; 33 | if(which === 13) { 34 | todo.title = target.value; 35 | this.todoService.save(todo); 36 | this.todoEdit = null; 37 | } else if (which === 27) { 38 | this.todoEdit = null; 39 | target.value = todo.title; 40 | } 41 | } 42 | addTodo(newTitle) { 43 | this.todoService.add({ 44 | title: newTitle, 45 | completed: false 46 | }); 47 | } 48 | completeMe(todo) { 49 | todo.completed = !todo.completed; 50 | this.todoService.save(todo); 51 | } 52 | deleteMe(todo) { 53 | this.todoService.remove(todo); 54 | } 55 | toggleAll($event) { 56 | var isComplete = $event.target.checked; 57 | this.todoService.list.forEach((todo)=> { 58 | todo.completed = isComplete; 59 | this.todoService.save(todo); 60 | }); 61 | } 62 | clearCompleted() { 63 | var toClear = {}; 64 | this.todoService.list.forEach((todo) => { 65 | if(todo.completed) { 66 | toClear[todo._key] = null; 67 | } 68 | }); 69 | this.todoService.bulkUpdate(toClear); 70 | } 71 | 72 | } 73 | bootstrap(TodoApp); 74 | -------------------------------------------------------------------------------- /angular2/css/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/angular2/css/bg.png -------------------------------------------------------------------------------- /angular2/firebase/angularfire.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export declare class AngularFire { 4 | asArray(): FirebaseArray; 5 | } 6 | 7 | export interface FirebaseArray { 8 | getItem(recOrIndex: any): any 9 | getChild(recOrIndex: any): any; 10 | add(newData: any): void; 11 | remove(recOrIndex: any): void; 12 | save(recOrIndex: any): void; 13 | keyify(snap: any): any; 14 | created(snap: any): void; 15 | moved(snap: any): void; 16 | updated(snap: any): void; 17 | removed(snap: any): void; 18 | bulkUpdate(items: Object): void; 19 | spliceOut(key: any): void; 20 | indexFor(key: any): number; 21 | getRecord(key: any): any; 22 | list: any[]; 23 | } 24 | -------------------------------------------------------------------------------- /angular2/firebase/angularfire.js: -------------------------------------------------------------------------------- 1 | if (typeof __decorate !== "function") __decorate = function (decorators, target, key, desc) { 2 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); 3 | switch (arguments.length) { 4 | case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); 5 | case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); 6 | case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); 7 | } 8 | }; 9 | if (typeof __metadata !== "function") __metadata = function (k, v) { 10 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 11 | }; 12 | define(["require", "exports", 'angular2/angular2'], function (require, exports, angular2_1) { 13 | var AngularFire = (function () { 14 | function AngularFire(ref) { 15 | this.ref = ref; 16 | } 17 | AngularFire.prototype.asArray = function () { 18 | return new FirebaseArray(this.ref); 19 | }; 20 | AngularFire = __decorate([ 21 | angular2_1.Component(), 22 | __metadata('design:paramtypes', [(typeof Firebase !== 'undefined' && Firebase) || Object]) 23 | ], AngularFire); 24 | return AngularFire; 25 | })(); 26 | exports.AngularFire = AngularFire; 27 | /* 28 | FirebaseArray 29 | 30 | */ 31 | var FirebaseArray = (function () { 32 | function FirebaseArray(ref) { 33 | this.ref = ref; 34 | this.list = []; 35 | // listen for changes at the Firebase instance 36 | this.ref.on('child_added', this.created.bind(this), this.error); 37 | this.ref.on('child_moved', this.moved.bind(this), this.error); 38 | this.ref.on('child_changed', this.updated.bind(this), this.error); 39 | this.ref.on('child_removed', this.removed.bind(this), this.error); 40 | // determine when initial load is completed 41 | // ref.once('value', function() { resolve(null); }, resolve); 42 | } 43 | FirebaseArray.prototype.getItem = function (recOrIndex) { 44 | var item = recOrIndex; 45 | if (typeof (recOrIndex) === "number") { 46 | item = this.getRecord(recOrIndex); 47 | } 48 | return item; 49 | }; 50 | FirebaseArray.prototype.getChild = function (recOrIndex) { 51 | var item = this.getItem(recOrIndex); 52 | return this.ref.child(item._key); 53 | }; 54 | FirebaseArray.prototype.add = function (rec) { 55 | this.ref.push(rec); 56 | }; 57 | FirebaseArray.prototype.remove = function (recOrIndex) { 58 | this.getChild(recOrIndex).remove(); 59 | }; 60 | FirebaseArray.prototype.save = function (recOrIndex) { 61 | var item = this.getItem(recOrIndex); 62 | this.getChild(recOrIndex).update(item); 63 | }; 64 | FirebaseArray.prototype.keyify = function (snap) { 65 | var item = snap.val(); 66 | item._key = snap.key(); 67 | return item; 68 | }; 69 | FirebaseArray.prototype.created = function (snap) { 70 | var addedValue = this.keyify(snap); 71 | this.list.push(addedValue); 72 | }; 73 | FirebaseArray.prototype.moved = function (snap) { 74 | var key = snap.key(); 75 | this.spliceOut(key); 76 | }; 77 | FirebaseArray.prototype.updated = function (snap) { 78 | var key = snap.key(); 79 | var indexToUpdate = this.indexFor(key); 80 | this.list[indexToUpdate] = this.keyify(snap); 81 | }; 82 | FirebaseArray.prototype.removed = function (snap) { 83 | var key = snap.key(); 84 | this.spliceOut(key); 85 | }; 86 | FirebaseArray.prototype.bulkUpdate = function (items) { 87 | this.ref.update(items); 88 | }; 89 | FirebaseArray.prototype.spliceOut = function (key) { 90 | var i = this.indexFor(key); 91 | if (i > -1) { 92 | return this.list.splice(i, 1)[0]; 93 | } 94 | return null; 95 | }; 96 | FirebaseArray.prototype.indexFor = function (key) { 97 | var record = this.getRecord(key); 98 | return this.list.indexOf(record); 99 | }; 100 | FirebaseArray.prototype.getRecord = function (key) { 101 | return this.list.find(function (item) { return key === item._key; }); 102 | }; 103 | return FirebaseArray; 104 | })(); 105 | exports.FirebaseArray = FirebaseArray; 106 | }); 107 | -------------------------------------------------------------------------------- /angular2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ng2do 5 | 25 | 26 | 27 | 28 | 29 | 30 | Loading... 31 | 40 | 41 | -------------------------------------------------------------------------------- /angular2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-angular2", 3 | "version": "1.0.0", 4 | "description": "Angular 2/TypeScript demo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 8 | }, 9 | "dependencies": { 10 | "angular2": "2.0.0-alpha.44", 11 | "systemjs": "0.19.5", 12 | "http-server": "0.8.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^1.5.3" 16 | }, 17 | "scripts": { 18 | "start": "node node_modules/typescript/lib/tsc.js && node node_modules/http-server/bin/http-server -o" 19 | } 20 | } -------------------------------------------------------------------------------- /angular2/todo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 14 | 15 |
16 | 17 | 18 | 19 |
    20 | 21 |
  • 22 | 23 |
    25 | 26 | 29 | 30 | 31 | 32 | 33 |
    34 | 35 |
    36 | 37 | 41 | 42 |
    43 | 44 |
  • 45 |
46 | 47 |
48 | 49 |
50 | 51 |
52 | 63 | 64 |
65 | 66 |
67 | 68 |
69 |

Double-click to edit a todo

70 |

Created by David East

71 |
72 | -------------------------------------------------------------------------------- /angular2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "module": "commonjs", 6 | "target": "es5" 7 | }, 8 | "files": [ 9 | "app/todo.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /async/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | !src/lib/ 3 | .vscode/ -------------------------------------------------------------------------------- /async/README.md: -------------------------------------------------------------------------------- 1 | # Async Functions 2 | 3 | *Async Functions* are functions that can suspend their execution to wait for the completion of an 4 | asynchronous operation. This allows complex algorithms that require asynchronous control flow to 5 | be written sequentially. 6 | 7 | This sample uses *Async Functions* to query the GitHub API to view information about recent pull 8 | requests. 9 | 10 | This sample requires a minimum of NodeJS v4.0.0. 11 | 12 | **Fetch dependencies** 13 | ``` 14 | npm install 15 | ``` 16 | 17 | **Run** 18 | ``` 19 | npm test 20 | ``` 21 | 22 | **Environment variables** 23 | 24 | | Name | Description | 25 | |:------------------|:----------------------------------------------------------------------------| 26 | | GITHUB_TOKEN | The Authentication token to use for GitHub API Requests. (Optional) | 27 | | GITHUB_REPOSITORY | The GitHub repository to use for queries. (Default: "Microsoft/TypeScript") | -------------------------------------------------------------------------------- /async/bin/ts-async-github-sample: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require("../lib/index.js"); -------------------------------------------------------------------------------- /async/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp') 2 | , sourcemaps = require('gulp-sourcemaps') 3 | , ts = require('gulp-typescript') 4 | , typescript = require('typescript') 5 | , del = require('del') 6 | , merge = require('merge2') 7 | , path = require('path') 8 | , spawn = require('child_process').spawn; 9 | 10 | var lib = { 11 | project: ts.createProject('./src/lib/tsconfig.json', { typescript: typescript }), 12 | bin: "./bin/ts-async-github-sample", 13 | main: "./lib/github", 14 | base: "./src/lib/", 15 | dest: "./lib/", 16 | src: ["./src/lib/**/*.ts"], 17 | out: ["./lib/**/*"] 18 | }; 19 | 20 | gulp.task("clean:lib", clean(lib)); 21 | gulp.task("clean", ["clean:lib"]); 22 | gulp.task("build:lib", build(lib)); 23 | gulp.task("build", ["build:lib"]); 24 | gulp.task("test", ["build"], test(lib)); 25 | gulp.task("watch:lib", ["build:lib"], watch(src(lib), ["build:lib"])); 26 | gulp.task("watch", ["build", "test"], watch(src(lib), ["test"])); 27 | gulp.task("default", ["build"]); 28 | 29 | function src() { 30 | return Array.from(arguments).reduce(function (ar, opts) { 31 | return ar.concat(opts.src); 32 | }, []); 33 | } 34 | 35 | function clean(opts) { 36 | return function (done) { 37 | del(opts.out, done); 38 | }; 39 | } 40 | 41 | function build(opts) { 42 | return function () { 43 | var tee = gulp 44 | .src(opts.src, { base: opts.base }) 45 | .pipe(sourcemaps.init()) 46 | .pipe(ts(opts.project)); 47 | return merge([ 48 | tee.dts 49 | .pipe(gulp.dest(opts.dest)), 50 | tee.js 51 | .pipe(sourcemaps.write('.', { includeContent: false, sourceRoot: path.relative(opts.dest, opts.base) })) 52 | .pipe(gulp.dest(opts.dest)) 53 | ]); 54 | }; 55 | } 56 | 57 | function test(opts) { 58 | return function (done) { 59 | var args = [opts.bin]; 60 | console.log("Executing test..."); 61 | spawn(process.argv[0], args, { stdio: "inherit" }).on("exit", function (code) { 62 | done(code !== 0 ? "Error executing script." : undefined); 63 | }); 64 | }; 65 | } 66 | 67 | function watch(src, tasks) { 68 | return function () { 69 | return gulp.watch(src, tasks); 70 | } 71 | } -------------------------------------------------------------------------------- /async/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6" 4 | } 5 | } -------------------------------------------------------------------------------- /async/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-node-github-async-sample", 3 | "version": "1.0.0", 4 | "description": "Sample for Async Functions in NodeJS v4.0.0", 5 | "private": true, 6 | "main": "lib/github.js", 7 | "bin": { 8 | "sample": "./bin/ts-async-github-sample" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "del": "^2.0.2", 13 | "gulp": "^3.9.0", 14 | "gulp-sourcemaps": "^1.5.2", 15 | "gulp-typescript": "^2.9.0", 16 | "merge2": "^0.3.6", 17 | "typescript": "next" 18 | }, 19 | "scripts": { 20 | "test": "./node_modules/.bin/gulp test" 21 | }, 22 | "author": "Microsoft Corp.", 23 | "license": "Apache-2.0", 24 | "engines": { 25 | "node": ">=4.0.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /async/src/lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs" 5 | } 6 | } -------------------------------------------------------------------------------- /async/src/lib/tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "node/node.d.ts": { 9 | "commit": "32029fcb4e1a3ef8968711b545d77b584435729d" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /async/src/lib/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /// 3 | -------------------------------------------------------------------------------- /async/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | /*! ***************************************************************************** 2 | Copyright (c) Microsoft Corporation. All rights reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | this file except in compliance with the License. You may obtain a copy of the 5 | License at http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 8 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 9 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 10 | MERCHANTABLITY OR NON-INFRINGEMENT. 11 | 12 | See the Apache Version 2.0 License for specific language governing permissions 13 | and limitations under the License. 14 | ***************************************************************************** */ 15 | 16 | "use strict"; 17 | 18 | export class LazyPromise extends Promise { 19 | public static [Symbol.species] = Promise; 20 | 21 | private _resolve: (value: T | PromiseLike) => void; 22 | private _reject: (reason: any) => void; 23 | private _executor: (resolve: (value: T | PromiseLike) => void, reject: (reason: any) => void) => void; 24 | 25 | public constructor(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason: any) => void) => void) { 26 | let resolver: (value: T | PromiseLike) => void; 27 | let rejecter: (reason: any) => void; 28 | super((resolve, reject) => { resolver = resolve; rejecter = reject; }); 29 | this._resolve = resolver; 30 | this._reject = rejecter; 31 | this._executor = executor; 32 | } 33 | 34 | public then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise { 35 | this._lazyExecute(); 36 | return super.then(onfulfilled, onrejected); 37 | } 38 | 39 | private _lazyExecute() { 40 | if (this._executor) { 41 | let executor = this._executor, resolve = this._resolve, reject = this._reject; 42 | delete this._executor; 43 | delete this._resolve; 44 | delete this._reject; 45 | try { 46 | executor(resolve, reject); 47 | } 48 | catch (e) { 49 | reject(e); 50 | } 51 | } 52 | } 53 | } 54 | 55 | export function sleep(msec: number) { 56 | return new Promise(resolve => setTimeout(resolve, msec)); 57 | } 58 | 59 | export function formatMessage(text: string, firstLineWidth: number, remainingLinesWidth?: number) { 60 | if (remainingLinesWidth === undefined) remainingLinesWidth = firstLineWidth; 61 | let pattern = /(\r\n?|\n)|(\s)|(\S+)/g; 62 | let match: RegExpMatchArray; 63 | let lines: string[] = []; 64 | let line: string = ""; 65 | let leadingWhiteSpace: string = ""; 66 | let width = firstLineWidth; 67 | while (match = pattern.exec(text)) { 68 | if (match[1]) { 69 | lines.push(line); 70 | width = remainingLinesWidth; 71 | line = ""; 72 | leadingWhiteSpace = ""; 73 | } 74 | else if (match[2]) { 75 | leadingWhiteSpace += match[2]; 76 | } 77 | else if (match[3]) { 78 | let token = match[3]; 79 | let lineLengthWithWhitespace = line.length + leadingWhiteSpace.length; 80 | let lineLengthWithText = lineLengthWithWhitespace + token.length; 81 | if (token.length > width) { 82 | // If there is room, append the first chunk of the long line to the 83 | // current line. 84 | let offset = 0; 85 | if (lineLengthWithWhitespace < width) { 86 | let chunk = token.substr(offset, width - lineLengthWithWhitespace); 87 | line += leadingWhiteSpace + chunk; 88 | offset += chunk.length; 89 | } 90 | 91 | // Push the current line. 92 | if (line) { 93 | lines.push(line); 94 | width = remainingLinesWidth; 95 | line = ""; 96 | } 97 | 98 | leadingWhiteSpace = ""; 99 | 100 | // Append lines for each chunk longer than one line. 101 | while (token.length - offset > width) { 102 | lines.push(token.substr(offset, width)); 103 | width = remainingLinesWidth; 104 | offset += width; 105 | } 106 | 107 | // Append the remaining text to the current line. 108 | if (token.length - offset > 0) { 109 | line = token.substr(offset); 110 | } 111 | else { 112 | line = ""; 113 | } 114 | } 115 | else if (lineLengthWithText > width) { 116 | lines.push(line); 117 | width = remainingLinesWidth; 118 | line = token; 119 | leadingWhiteSpace = ""; 120 | } 121 | else { 122 | line += leadingWhiteSpace + token; 123 | leadingWhiteSpace = ""; 124 | } 125 | } 126 | } 127 | 128 | if (line) { 129 | lines.push(line); 130 | } 131 | 132 | return lines; 133 | } -------------------------------------------------------------------------------- /browserify/.gitignore: -------------------------------------------------------------------------------- 1 | *.js -------------------------------------------------------------------------------- /browserify/README.md: -------------------------------------------------------------------------------- 1 | **Install Browserify** 2 | 3 | ```shell 4 | npm install -g browserify 5 | ``` 6 | 7 | **Fetch dependencies** 8 | 9 | ```shell 10 | npm install 11 | ``` 12 | 13 | **Compile .ts files** 14 | 15 | Either enter the following command 16 | 17 | ```shell 18 | node node_modules/typescript/bin/tsc.js 19 | ``` 20 | 21 | or use the `tsc` script from our `package.json` with 22 | 23 | ```shell 24 | npm run tsc 25 | ``` 26 | 27 | **Run Browserify** 28 | 29 | Either enter the following command 30 | 31 | ```shell 32 | browserify src/app.js -o bundle.js -s app 33 | ``` 34 | 35 | or use the `browserify` script from our `package.json` with 36 | 37 | ```shell 38 | npm run browserify 39 | 40 | ``` 41 | 42 | **Start http-server** 43 | 44 | Either enter the following command 45 | 46 | ```shell 47 | node node_modules/http-server/bin/http-server -o 48 | ``` 49 | 50 | or use the `listen` script from our `package.json` with 51 | 52 | ``` 53 | npm run listen 54 | ``` 55 | 56 | By default http-server listens on port `8080`. 57 | If this port is taken, use '-p ####' to specify a free port, where `####` is the available port. 58 | 59 | **Shortcut for running all steps in a batch** 60 | 61 | ``` 62 | npm run all 63 | ``` -------------------------------------------------------------------------------- /browserify/app.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-family: 'Segoe UI', sans-serif 4 | } 5 | 6 | span { 7 | font-style: italic 8 | } -------------------------------------------------------------------------------- /browserify/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | TypeScript HTML App 7 | 8 | 9 | 10 | 11 |

Browserify/TypeScript sample

12 |
13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /browserify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-browserify", 3 | "version": "1.0.0", 4 | "description": "Browserify/TypeScript demo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 8 | }, 9 | "dependencies": { 10 | "http-server": "0.8.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^1.8.9" 14 | }, 15 | "scripts": { 16 | "tsc": "node node_modules/typescript/lib/tsc.js", 17 | "browserify": "browserify src/app.js -o bundle.js -s app", 18 | "listen": "node node_modules/http-server/bin/http-server", 19 | "all": "npm run tsc && npm run browserify && npm run listen" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /browserify/src/app.ts: -------------------------------------------------------------------------------- 1 | import { TimeReporter, Printer } from './timeReporter' 2 | import { EOL } from 'os'; 3 | 4 | 5 | export function start(printer: Printer) { 6 | let timeReporter = new TimeReporter(printer); 7 | timeReporter.start(); 8 | } -------------------------------------------------------------------------------- /browserify/src/node.d.ts: -------------------------------------------------------------------------------- 1 | declare module "os" { 2 | export var EOL: string; 3 | } 4 | 5 | declare module "util" { 6 | export function format(format: string, ...args: any[]): string; 7 | } 8 | -------------------------------------------------------------------------------- /browserify/src/timeReporter.ts: -------------------------------------------------------------------------------- 1 | import {format} from "util"; 2 | 3 | export type Printer = (s: string) => void; 4 | 5 | export class TimeReporter 6 | { 7 | timerToken: number; 8 | 9 | constructor (private printer: Printer) 10 | { 11 | this.reportDate(); 12 | } 13 | 14 | start() 15 | { 16 | this.timerToken = setInterval(() => this.reportDate(), 500); 17 | } 18 | 19 | stop() 20 | { 21 | clearTimeout(this.timerToken); 22 | } 23 | 24 | reportDate() { 25 | this.printer(format("Date is %s", new Date().toUTCString())); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /browserify/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "target": "es5" 5 | } 6 | } -------------------------------------------------------------------------------- /buildall.cmd: -------------------------------------------------------------------------------- 1 | @echo off & setlocal EnableDelayedExpansion 2 | 3 | if "%1"=="" ( 4 | goto :Help 5 | ) 6 | 7 | goto :Start 8 | 9 | 10 | :Help 11 | Echo ********************************************************** 12 | Echo Usage: 13 | Echo buildall.cmd tscPath 14 | Echo Example: 15 | Echo buildall c:\typescript\built\local\tsc.js 16 | Echo ********************************************************** 17 | goto :Done 18 | 19 | 20 | :Start 21 | set tscPath=%1 22 | set CURRENTDIR=%~dp0 23 | 24 | call :buildProject "amd" "--sourcemap --module amd %CURRENTDIR%amd\app.ts" 25 | call :buildProject "d3" "--sourcemap %CURRENTDIR%d3\data.ts" 26 | call :buildProject "greeter" "--sourcemap %CURRENTDIR%greeter\greeter.ts" 27 | call :buildProject "imageboard" "--sourcemap --module commonjs %CURRENTDIR%imageboard\app.ts" 28 | call :buildProject "interfaces" "--sourcemap %CURRENTDIR%interfaces\interfaces.ts" 29 | call :buildProject "jquery" "--sourcemap --target ES5 %CURRENTDIR%jquery\parallax.ts" 30 | call :buildProject "mankala" "Driver.ts --sourcemap -out %CURRENTDIR%mankalagame.js" 31 | call :buildProject "node" "--sourcemap --module commonjs %CURRENTDIR%node\HttpServer.ts" 32 | call :buildProject "node" "--sourcemap --module commonjs %CURRENTDIR%node\TcpServer.ts" 33 | call :buildProject "raytracer" "--sourcemap %CURRENTDIR%raytracer\raytracer.ts" 34 | call :buildProject "simple" "--sourcemap %CURRENTDIR%simple\animals.ts" 35 | call :buildProject "todomvc" "--sourcemap %CURRENTDIR%todomvc\js\todos.ts" 36 | call :buildProject "warship" "--sourcemap --target ES5 %CURRENTDIR%warship\warship.ts" 37 | 38 | goto :Done 39 | 40 | :buildProject 41 | pushd %CURRENTDIR%%~1 42 | echo Running %~1 using node... 43 | 44 | echo on 45 | call node "%tscPath%" %~2 46 | echo off 47 | 48 | if not %errorlevel%==0 ( 49 | echo Failed! 50 | ) else ( 51 | echo Done. 52 | ) 53 | 54 | echo Running %~1 using cscript... 55 | 56 | echo on 57 | call cscript /nologo "%tscPath%" %~2 58 | echo off 59 | 60 | if not %errorlevel%==0 ( 61 | echo Failed! 62 | ) else ( 63 | echo Done. 64 | ) 65 | 66 | popd 67 | goto :eof 68 | 69 | 70 | :Done 71 | ENDLOCAL -------------------------------------------------------------------------------- /d3/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: D3 2 | 3 | ## Overview 4 | 5 | D3 visualization 6 | - Use of the D3 wrapper 7 | - Use of modules and interfaces 8 | 9 | ## Running 10 | ``` 11 | tsc --sourcemap data.ts 12 | start perf.html 13 | ``` -------------------------------------------------------------------------------- /d3/perf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 37 | 38 | 39 |

Status

40 |
41 | 42 |

Compiler Performance

43 |
44 | 45 | -------------------------------------------------------------------------------- /d3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /greeter/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Greeter 2 | 3 | ## Overview 4 | 5 | This sample shows basic class definition and instantiation. 6 | 7 | ## Running 8 | ``` 9 | tsc --sourcemap greeter.ts 10 | start greeter.html 11 | ``` 12 | -------------------------------------------------------------------------------- /greeter/greeter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeScript Greeter 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /greeter/greeter.ts: -------------------------------------------------------------------------------- 1 | class Greeter { 2 | constructor(public greeting: string) { } 3 | greet() { 4 | return "

" + this.greeting + "

"; 5 | } 6 | }; 7 | 8 | var greeter = new Greeter("Hello, world!"); 9 | 10 | document.body.innerHTML = greeter.greet(); 11 | -------------------------------------------------------------------------------- /greeter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /imageboard/ImageBoard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 12.0 6 | 1.4 7 | 8 | 9 | Debug 10 | AnyCPU 11 | {BE268EA8-89D1-44DB-839D-FB007556CC97} 12 | Library 13 | false 14 | ClassLibrary 15 | v4.0 16 | 512 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | false 27 | true 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | false 37 | true 38 | 39 | 40 | ImageBoard 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | commonjs 83 | 84 | 85 | -------------------------------------------------------------------------------- /imageboard/ImageBoardNodeProj.njsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | 2.0 6 | {abeae01d-ced1-4453-9533-6f0ebb26b1a3} 7 | 8 | ShowAllFiles 9 | app.ts 10 | . 11 | . 12 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 13 | true 14 | CommonJS 15 | true 16 | 11.0 17 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 18 | 19 | 20 | True 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | False 74 | True 75 | 0 76 | / 77 | http://localhost:48022/ 78 | False 79 | True 80 | http://localhost:1337 81 | False 82 | 83 | 84 | 85 | 86 | 87 | 88 | CurrentPage 89 | True 90 | False 91 | False 92 | False 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | False 102 | False 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /imageboard/ImageBoardNodeProj.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22803.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "ImageBoardNodeProj", "ImageBoardNodeProj.njsproj", "{ABEAE01D-CED1-4453-9533-6F0EBB26B1A3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {ABEAE01D-CED1-4453-9533-6F0EBB26B1A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {ABEAE01D-CED1-4453-9533-6F0EBB26B1A3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {ABEAE01D-CED1-4453-9533-6F0EBB26B1A3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {ABEAE01D-CED1-4453-9533-6F0EBB26B1A3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /imageboard/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Image Board 2 | 3 | ## Overview 4 | 5 | This sample implements a complete Node.js application. 6 | Notable features: 7 | 8 | * Typed usage of express for server side MVC 9 | * Typed usage of mongodb for server side database 10 | * Typed usage of Node.js 11 | * Use of external typings from DefinitelyTyped 12 | * Visual Studio project file for working with the project 13 | 14 | ## Running 15 | 16 | Note: All commands entered need to be performed from within *this directory*. 17 | 18 | 1. Install MongoDB if necessary (see http://docs.mongodb.org/manual/installation/ ) 19 | 20 | 2. Ensure you have a clean directory to dedicate as to a database (e.g. `C:\imageboard` or `~/imageboard/`). 21 | 22 | 3. From *this repository's imageboard directory*, run the following command to launch the MongoDB process. 23 | ```shell 24 | /bin/mongod --dbpath 25 | ``` 26 | 27 | 4. From *this repository's imageboard directory*, restore the sample app data to MongoDB in another command prompt with the following command: 28 | ```shell 29 | /bin/mongorestore dump 30 | ``` 31 | 32 | 5. From this imageboard directory, install the app's node dependencies, tsd, and typings with the following commands: 33 | ```shell 34 | npm install 35 | npm install -g tsd 36 | tsd install 37 | ``` 38 | Some things to note: 39 | 40 | * `npm install` will install this project's node dependencies from `package.json`. 41 | * `tsd install` will retrieve `.d.ts` files from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). 42 | 43 | 6. Compile the app with the following command: 44 | ```shell 45 | tsc 46 | ``` 47 | The above command will use `tsconfig.json` to compile all necessary files. 48 | 49 | 7. Launch the Node process to serve the app using the following command: 50 | ```shell 51 | node app.js 52 | ``` 53 | 54 | 7. Open your favorite browser and navigating to `http://localhost:3000/` to access the app. 55 | -------------------------------------------------------------------------------- /imageboard/app.ts: -------------------------------------------------------------------------------- 1 | import * as http from "http"; 2 | import * as url from "url"; 3 | import * as express from "express"; 4 | import * as bodyParser from "body-parser"; 5 | import errorHandler = require("errorhandler"); 6 | import methodOverride = require("method-override"); 7 | 8 | import * as routes from "./routes/index"; 9 | import * as db from "./db"; 10 | 11 | var app = express(); 12 | 13 | // Configuration 14 | 15 | app.set('views', __dirname + '/views'); 16 | app.set('view engine', 'jade'); 17 | app.set('view options', { layout: false }); 18 | app.use(bodyParser.urlencoded({ extended: true })); 19 | app.use(bodyParser.json()); 20 | app.use(methodOverride()); 21 | app.use(express.static(__dirname + '/public')); 22 | 23 | var env = process.env.NODE_ENV || 'development'; 24 | if (env === 'development') { 25 | app.use(errorHandler()); 26 | } 27 | 28 | 29 | // Routes 30 | 31 | app.get('/', routes.index); 32 | 33 | app.get('/findImages', (req, res) => { 34 | console.log('getting images from' + req.query['url']); 35 | 36 | let req2 = http.get(url.parse(req.query['url']), urlMessage => { 37 | console.log("Got response: " + urlMessage.statusCode); 38 | 39 | let text = ""; 40 | 41 | urlMessage.on('data', (chunk: string) => { 42 | text += chunk; 43 | }); 44 | 45 | urlMessage.on('end', () => { 46 | console.log(text); 47 | const imageTagRegEx = /]+src=[\"\']([^\'\"]+)[\"\']/g; 48 | 49 | let match: RegExpMatchArray; 50 | let matches: string[] = []; 51 | while (match = imageTagRegEx.exec(text)) { 52 | matches.push(match[1]); 53 | } 54 | 55 | res.write(JSON.stringify(matches)); 56 | res.end(); 57 | }); 58 | 59 | }).on('error', function(a,e) { 60 | console.log("Got error: " + e.message); 61 | }); 62 | }); 63 | 64 | app.get('/user/:userid', (req, res) => { 65 | console.log('getting user ' + req.params.userid); 66 | db.getUser(req.params.userid, user => { 67 | res.render('user', { 68 | title: user._id, 69 | username: user._id, 70 | boards: user.boards 71 | }); 72 | }); 73 | }); 74 | 75 | app.get('/user/:userid/newboard', (req, res) => { 76 | res.render('newboard', { 77 | username: req.params.userid 78 | }); 79 | }); 80 | 81 | app.post('/user/:userid/newboard', (req, res) => { 82 | db.addBoard(req.params.userid, req.param('title'), req.param('description'), user => { 83 | res.redirect('/user/'+req.params.userid); 84 | }); 85 | }); 86 | 87 | app.get('/user/:userid/:boardid', (req, res) => { 88 | console.log('getting ' + req.params.userid + ", " + req.params.boardid); 89 | db.getUser(req.params.userid, user => { 90 | let board = user.boards.filter(board => decodeURIComponent(req.params.boardid) === board.title)[0]; 91 | 92 | if (board) { 93 | db.getImages(board.images, images => { 94 | res.render('board', { 95 | title: user._id, 96 | username: user._id, 97 | board: board, 98 | images: images 99 | }); 100 | }); 101 | } 102 | else { 103 | res.send(404, 'not found'); 104 | } 105 | }); 106 | }); 107 | 108 | app.get('/user/:userid/:boardid/newpin', (req, res) => { 109 | res.render('newpin', { 110 | username: req.params.userid, 111 | boardid: req.params.boardid 112 | }); 113 | }); 114 | 115 | app.post('/user/:userid/:boardid/newpin', (req, res) => { 116 | db.addPin(req.params.userid, req.params.boardid, req.param('imageUri'), req.param('link'), req.param('caption'), user => { 117 | res.redirect('/user/'+req.params.userid +"/" + req.params.boardid) 118 | }); 119 | }); 120 | 121 | app.get('/image/:imageid', (req, res) => { 122 | console.log('getting image ' + req.params.imageid); 123 | db.getImage(req.params.imageid, image => { 124 | res.render('image', { 125 | title: "image", 126 | image: image 127 | }); 128 | }); 129 | }); 130 | 131 | app.listen(3000, function(){ 132 | console.log("Demo Express server listening on port %d in %s mode", 3000, app.settings.env); 133 | }); 134 | 135 | export var App = app; -------------------------------------------------------------------------------- /imageboard/db.ts: -------------------------------------------------------------------------------- 1 | // Mongo 2 | import mongodb = require('mongodb'); 3 | 4 | var server = new mongodb.Server('localhost', 27017, {auto_reconnect: true}); 5 | var db = new mongodb.Db('mydb', server, { w: 1 }); 6 | db.open(function() {}); 7 | 8 | export interface User { 9 | _id: string; 10 | email: string; 11 | first_name: string; 12 | last_name: string; 13 | fbId: number; 14 | boards: Board[]; 15 | } 16 | 17 | export interface Board { 18 | title: string; 19 | description: string; 20 | images: mongodb.ObjectID[]; 21 | } 22 | 23 | export interface Image { 24 | _id: mongodb.ObjectID; 25 | user: string; 26 | caption: string; 27 | imageUri: string; 28 | link: string; 29 | board: string; 30 | comments: {text: string; user: string;}[]; 31 | } 32 | 33 | export function getUser(id: string, callback: (user: User) => void) { 34 | db.collection('users', function(error, users) { 35 | if(error) { console.error(error); return; } 36 | users.find({_id: id}).batchSize(10).nextObject(function(error, user) { 37 | if(error) { console.error(error); return; } 38 | callback(user); 39 | }); 40 | }); 41 | } 42 | 43 | export function getUsers(callback: (users: User[]) => void) { 44 | db.collection('users', function(error, users_collection) { 45 | if(error) { console.error(error); return; } 46 | users_collection.find({}, { '_id': 1 }).toArray(function(error, userobjs) { 47 | if(error) { console.error(error); return; } 48 | callback(userobjs); 49 | }); 50 | }); 51 | } 52 | 53 | export function getImage(imageId: string, callback: (image: Image) => void) { 54 | db.collection('images', function(error, images_collection) { 55 | if(error) { console.error(error); return; } 56 | images_collection.find({_id: new mongodb.ObjectID(imageId)}).batchSize(10).nextObject(function(error, image) { 57 | if(error) { console.error(error); return; } 58 | callback(image); 59 | }); 60 | }); 61 | } 62 | 63 | export function getImages(imageIds: mongodb.ObjectID[], callback: (images: Image[]) => void) { 64 | db.collection('images', function(error, images_collection) { 65 | if(error) { console.error(error); return; } 66 | images_collection.find({_id: {$in: imageIds}}).toArray(function(error, images) { 67 | callback(images); 68 | }); 69 | }); 70 | } 71 | 72 | export function addBoard(userid: any, title: string, description: string, callback: (user: User) => void) { 73 | db.collection('users', function(error, users) { 74 | if(error) { console.error(error); return; } 75 | users.update( 76 | {_id: userid}, 77 | {"$push": {boards: { title: title, description: description, images: []}}}, 78 | function(error, user) { 79 | if(error) { console.error(error); return; } 80 | callback(user); 81 | } 82 | ); 83 | }); 84 | } 85 | 86 | export function addPin(userid: string, boardid: string, imageUri: string, link: string, caption: string, callback: (user: User) => void) { 87 | db.collection('images', function(error, images_collection) { 88 | if(error) { console.error(error); return; } 89 | images_collection.insert({ 90 | user: userid, 91 | caption: caption, 92 | imageUri: imageUri, 93 | link: link, 94 | board: boardid, 95 | comments: [] 96 | }, function(error, image) { 97 | console.log(image); 98 | db.collection('users', function(error, users) { 99 | if(error) { console.error(error); return; } 100 | users.update( 101 | {_id: userid, "boards.title": boardid}, 102 | {"$push": {"boards.$.images": image[0]._id}}, 103 | function(error, user) { 104 | callback(user); 105 | } 106 | ); 107 | }) 108 | }) 109 | }) 110 | } 111 | -------------------------------------------------------------------------------- /imageboard/dump/mydb/images.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/imageboard/dump/mydb/images.bson -------------------------------------------------------------------------------- /imageboard/dump/mydb/images.metadata.json: -------------------------------------------------------------------------------- 1 | {indexes:[{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "mydb.images", "name" : "_id_" }]} -------------------------------------------------------------------------------- /imageboard/dump/mydb/users.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/imageboard/dump/mydb/users.bson -------------------------------------------------------------------------------- /imageboard/dump/mydb/users.metadata.json: -------------------------------------------------------------------------------- 1 | {indexes:[{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "mydb.users", "name" : "_id_" }]} -------------------------------------------------------------------------------- /imageboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imageboard-sample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "express": "^4.13.3", 7 | "body-parser": "^1.14.1", 8 | "errorhandler": "^1.4.2", 9 | "method-override": "^2.3.5", 10 | "ejs": ">= 0.5.0", 11 | "jade": ">= 1.11.0", 12 | "mongodb": ">= 1.4.29" 13 | } 14 | } -------------------------------------------------------------------------------- /imageboard/public/javascripts/fb.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // initialize the library with the API key 5 | FB.init({ appId: '349900301735115' }); 6 | 7 | // fetch the status on load 8 | FB.getLoginStatus(handleSessionResponse2); 9 | 10 | $('#login').bind('click', function () { 11 | FB.login(handleSessionResponse); 12 | }); 13 | 14 | $('#logout').bind('click', function () { 15 | FB.logout(handleSessionResponse); 16 | }); 17 | 18 | function handleSessionResponse2() { } 19 | // handle a session response from any of the auth related calls 20 | function handleSessionResponse() { 21 | FB.api('/me', function (response) { 22 | console.dir(response); 23 | //$('#user-info').html(response.id + ' - ' + response.name); 24 | }); 25 | FB.api('/me/picture', function (response) { 26 | console.dir(response); 27 | var img = document.createElement('img'); 28 | img.src = response; 29 | document.body.appendChild(img); 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /imageboard/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | html { background-color: #f9f9f9; margin: 0; padding: 0; } 2 | body { margin: 0 auto; padding: 0; font-family:"Segoe UI","HelveticaNeue-Light", sans-serif; font-weight:200;} 3 | h1, h2, p, summary, footer, li { line-height: 170%; } 4 | h1, h2 { border-bottom: 1px solid #aaa; font-family:"Segoe UI Light","HelveticaNeue-UltraLight", sans-serif; font-weight:100; } 5 | h2 { font-size: 16pt; } 6 | p { margin: 1em 20px 0 20px; } 7 | ul { margin-top: 1em; } 8 | #footer { font-style: italic; color: #999; text-align: center; padding: 1em 0 2em 0; margin-top: 1em; font-size: 80%; } 9 | em { letter-spacing: 1px; } 10 | li { margin-left: 1em; } 11 | 12 | #container 13 | { 14 | padding: 50px; 15 | } 16 | 17 | a 18 | { 19 | font-weight: bold; 20 | text-decoration: none; 21 | color: #777777; 22 | } 23 | 24 | img.small 25 | { 26 | border:0; 27 | width: 200px; 28 | } 29 | 30 | img.large 31 | { 32 | border:0; 33 | display: block; 34 | margin-left: auto; 35 | margin-right: auto 36 | } 37 | 38 | 39 | .image 40 | { 41 | margin: 10px; 42 | padding: 5px; 43 | word-wrap: break-word; 44 | border-style: solid; 45 | border-width: 1px; 46 | border-color: #bbbbbb; 47 | background-color: #ffffff; 48 | 49 | } 50 | 51 | .imagebox 52 | { 53 | margin: 10px; 54 | } 55 | 56 | .commentbox 57 | { 58 | margin: 5px -5px -5px -5px; 59 | padding: 5px; 60 | background-color: #eeeeee; 61 | } 62 | 63 | .primarysource 64 | { 65 | font-size: 80%; 66 | } 67 | 68 | .title 69 | { 70 | font-size: 2.5rem; 71 | } 72 | 73 | form 74 | { 75 | font-size: 18px; 76 | } 77 | 78 | .inputtitle 79 | { 80 | display:block; 81 | float: left; 82 | width: 100px; 83 | } 84 | 85 | input[type="text"], textarea 86 | { 87 | padding: 6px 12px; 88 | line-height: 1.4; 89 | border: 1px solid #A4A2A2; 90 | border-radius: 6px; 91 | } 92 | 93 | 94 | input.button 95 | { 96 | padding: 6px 12px; 97 | line-height: 1.4; 98 | border: 1px solid #A4A2A2; 99 | border-radius: 6px; 100 | background-color: #ab2222; 101 | color: #ffffff; 102 | } -------------------------------------------------------------------------------- /imageboard/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express = require("express") 2 | import db = require("../db") 3 | 4 | export function index(req: express.Request, res: express.Response) { 5 | db.getUsers(function(users) { 6 | console.dir(users); 7 | res.render('index', { title: 'ImageBoard', users: users }) 8 | }); 9 | }; -------------------------------------------------------------------------------- /imageboard/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "sourceMap": true 5 | }, 6 | "files": [ 7 | "./typings/tsd.d.ts", 8 | "./routes/index.ts", 9 | "./db.ts", 10 | "./app.ts" 11 | ] 12 | } -------------------------------------------------------------------------------- /imageboard/tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "mime/mime.d.ts": { 9 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 10 | }, 11 | "serve-static/serve-static.d.ts": { 12 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 13 | }, 14 | "express/express.d.ts": { 15 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 16 | }, 17 | "mongodb/mongodb.d.ts": { 18 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 19 | }, 20 | "node/node.d.ts": { 21 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 22 | }, 23 | "method-override/method-override.d.ts": { 24 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 25 | }, 26 | "errorhandler/errorhandler.d.ts": { 27 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 28 | }, 29 | "body-parser/body-parser.d.ts": { 30 | "commit": "fc341765ebbb04b7109981a25dced01f488f4d94" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /imageboard/views/board.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1 #{board.title} by 5 | a(href= "/user/"+username)!= username 6 | div.board 7 | h4.description= board.description 8 | #board.images 9 | - each image in images 10 | div.image.grid_3 11 | div.imagebox 12 | div 13 | a(href= "/image/"+image._id.toString()) 14 | img.small(src= image.imageUri) 15 | =image.caption 16 | div.primarysource 17 | a(href= image.link)!= /http:\/\/([^\/]*)\//.exec(image.link)[1] 18 | div.commentbox 19 | - each comment in image.comments 20 | div.comment 21 | a(href= "/user/"+comment.user) 22 | b= comment.user 23 |   #{comment.text} 24 | .grid_12 25 | br 26 | a(href= "/user/"+username+"/"+board.title+"/newpin") Add a new pin... -------------------------------------------------------------------------------- /imageboard/views/image.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1 Posted by #{image.user} 5 | div.image.grid_9 6 | div.imagebox 7 | div 8 | img.large(src= image.imageUri) 9 | =image.caption 10 | div.commentbox 11 | - each comment in image.comments 12 | div.comment 13 | a(href= "/user/"+comment.user) 14 | b= comment.user 15 |   #{comment.text} -------------------------------------------------------------------------------- /imageboard/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1= title 5 | p Welcome to #{title} 6 | 7 | ul 8 | - each user in users 9 | li 10 | a(href= "/user/"+user._id) 11 | b= user._id -------------------------------------------------------------------------------- /imageboard/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title ImageBoard 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | #header.container_12 8 | #fb-root 9 | script(src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js') 10 | script(src='http://connect.facebook.net/en_US/all.js') 11 | script(src='/javascripts/fb.js') 12 | #container.container_12!= body 13 | block mainContent 14 | -------------------------------------------------------------------------------- /imageboard/views/newboard.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1 Create a new board for 5 | a(href= "/user/"+username)!= username 6 | form( method="post") 7 | div 8 | br 9 | div 10 | span.inputtitle Title : 11 | input(type="text", name="title", id="editArticleTitle") 12 | br 13 | div 14 | span.inputtitle Description : 15 | textarea( name="description", rows=10, cols=16, id="editArticleBody") 16 | br 17 | #editArticleSubmit 18 | input.button(type="submit", value="Save board") -------------------------------------------------------------------------------- /imageboard/views/newpin.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1 Pin new image to 5 | a(href= "/user/"+username)!= username 6 | 's board 7 | a(href= "/user/"+username+"/"+boardid)!= boardid 8 | form( method="post") 9 | div 10 | br 11 | div 12 | span.inputtitle Image url: 13 | input(type="text", name="imageUri") 14 | br 15 | div 16 | span.inputtitle Link : 17 | input(type="text", name="link") 18 | br 19 | div 20 | span.inputtitle Caption : 21 | textarea( name="caption", rows=10, cols=16) 22 | br 23 | #editArticleSubmit 24 | input.button(type="submit", value="Save pin") -------------------------------------------------------------------------------- /imageboard/views/user.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block mainContent 4 | h1 #{username}'s ImageBoard 5 | #boards 6 | - each board in boards 7 | div.board 8 | br 9 | div.title 10 | a(href= "/user/"+username+"/"+board.title)!= board.title 11 | div.description= board.description 12 | br 13 | a(href= "/user/"+username+"/newboard") Add a new board... -------------------------------------------------------------------------------- /interfaces/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Simple 2 | 3 | ## Overview 4 | 5 | Simple use of classes and inheritance: 6 | - Interface: A simple interface that defines the interface for something that can drive. 7 | - Class: An implementation of a car. 8 | 9 | ## Keep Playing 10 | 11 | Want to experiment? Try adding a second interface: Flyable. Implement it in a Helicopter class, then write a FlyingCar class that implements both Drivable and Flyable! 12 | ``` 13 | interface Flyable { ... } 14 | class Helicopter implements Flyable { ... } 15 | class FlyingCar implements Drivable, Flyable { ... } 16 | ``` 17 | ## Running 18 | `tsc --sourcemap interfaces.ts` 19 | -------------------------------------------------------------------------------- /interfaces/interfaces.ts: -------------------------------------------------------------------------------- 1 | interface Drivable { 2 | 3 | // Starts the car's ignition so that it can drive. 4 | start(): void; 5 | // Attempt to drive a distance. Returns true or false based on whether or not the drive was successful. 6 | drive(distance: number): boolean; 7 | // Give the distance from the start. 8 | getPosition(): number; 9 | } 10 | 11 | class Car implements Drivable { 12 | private _isRunning: boolean; 13 | private _distanceFromStart: number; 14 | 15 | constructor() { 16 | this._isRunning = false; 17 | this._distanceFromStart = 0; 18 | } 19 | 20 | /** 21 | * Starts the car's ignition so that it can drive. 22 | */ 23 | public start() { 24 | this._isRunning = true; 25 | } 26 | 27 | /** 28 | * Attempt to drive a distance. Returns true or false based on whether or not the drive was successful. 29 | * 30 | * @param {number} distance The distance attempting to cover 31 | * 32 | * @returns {boolean} Whether or not the drive was successful 33 | */ 34 | public drive(distance: number): boolean { 35 | if (this._isRunning) { 36 | this._distanceFromStart += distance; 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | /** 43 | * Gives the distance from starting position 44 | * 45 | * @returns {number} Distance from starting position; 46 | */ 47 | public getPosition(): number { 48 | return this._distanceFromStart; 49 | } 50 | } 51 | 52 | // Want to experiment? Try adding a second interface: Flyable. Implement it in a Helicopter class, then write a FlyingCar class that implements both Drivable and Flyable! -------------------------------------------------------------------------------- /interfaces/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /jquery/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: JQuery Parallax Starfield 2 | 3 | ## Overview 4 | 5 | This sample shows a simple jQuery application in TypeScript using a jQuery TypeScript typing. 6 | 7 | ## Usage 8 | 9 | For best results, scroll the window using the scrollbar. 10 | 11 | ## Running 12 | ``` 13 | npm install 14 | tsc 15 | open parallax.html 16 | ``` 17 | -------------------------------------------------------------------------------- /jquery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "1.0.0", 4 | "description": "jQuery Typescript Demo", 5 | "scripts":{ 6 | "tsc": "tsc" 7 | }, 8 | "dependencies": { 9 | "jquery": "^3.1.1" 10 | }, 11 | "devDependencies": { 12 | "@types/jquery": "^2.0.40", 13 | "typescript": "^2.1.6" 14 | }, 15 | "type": "git", 16 | "url": "https://github.com/Microsoft/TypeScriptSamples.git", 17 | "license": "MIT" 18 | } -------------------------------------------------------------------------------- /jquery/parallax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 61 | 62 | 63 |
64 |
65 |   66 |
67 |
68 |   69 |
70 |
71 |   72 |
73 |
74 |   75 |
76 |
77 |   78 |
79 |
80 | 81 | 82 | 83 | 90 | 91 | -------------------------------------------------------------------------------- /jquery/parallax.ts: -------------------------------------------------------------------------------- 1 | module Parallax { 2 | export class ParallaxContainer { 3 | private content: HTMLElement; 4 | private perspective: number; 5 | private surface: ParallaxSurface[]; 6 | 7 | /** 8 | * Creates a Container for a Parallax 9 | * 10 | * @param {HTMLElement} scrollableContent The container that will be parallaxed 11 | * @param {perspective} perspective The ratio of how much back content should be scrolled relative to forward content. For example, if this value is 0.5, and there are 2 surfaces, 12 | * the front-most surface would be scrolled normally, and the surface behind it would be scrolled half as much. 13 | */ 14 | constructor(scrollableContent: HTMLElement, 15 | perspective: number) { 16 | this.perspective = perspective; 17 | this.surface = []; 18 | this.content = scrollableContent; 19 | 20 | $(scrollableContent).scroll((event: JQueryEventObject) => { 21 | this.onContainerScroll(event); 22 | }); 23 | } 24 | 25 | private onContainerScroll(e: JQueryEventObject): void { 26 | var currentScrollPos = $(this.content).scrollTop(); 27 | var currentParallax = 1; 28 | for (var i = 0; i < this.surface.length; i++) { 29 | var surface = this.surface[i]; 30 | var offset = -(currentScrollPos * currentParallax); 31 | surface.currentY = offset; 32 | currentParallax *= this.perspective; 33 | } 34 | } 35 | 36 | addSurface(surface: ParallaxSurface): void { 37 | this.surface.push(surface); 38 | } 39 | } 40 | 41 | export class ParallaxSurface { 42 | private content: HTMLElement; 43 | 44 | constructor(surfaceContents: HTMLElement) { 45 | this.content = surfaceContents; 46 | } 47 | 48 | get currentY(): number { 49 | return -$(this.content).css('margin-top'); 50 | } 51 | 52 | set currentY(value: number) { 53 | $(this.content).css({ marginTop: value }); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /jquery/starfield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/jquery/starfield.png -------------------------------------------------------------------------------- /jquery/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "sourceMap": true 5 | } 6 | } -------------------------------------------------------------------------------- /js-and-ts/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Mixing TypeScript and JavaScript 2 | 3 | ## Overview 4 | 5 | A sample of how to use the `allowJS` option to use both JavaScript and TypeScript together. 6 | A simple text formatter is provided, written in JavaScript. This formatter is then used 7 | within a TypeScript class to format a computation. 8 | 9 | To run this sample, you must have `node` installed. You can also use `ts-node` to run this directly 10 | without a compilation from TypeScript to JavaScript. 11 | 12 | ## Running 13 | 14 | ```bash 15 | $ tsc robot.ts` 16 | $ node robot.js` 17 | ``` -------------------------------------------------------------------------------- /js-and-ts/format.js: -------------------------------------------------------------------------------- 1 | const surroundWithStars = (value) => { 2 | const valueLength = value.toString().length; 3 | const topBottomBorder = '*'.repeat(valueLength + 2); 4 | 5 | return topBottomBorder 6 | + "\n" 7 | + '*' + value.toString() + '*' 8 | + "\n" 9 | + topBottomBorder; 10 | } 11 | 12 | module.exports.Formatter = { surroundWithStars }; 13 | 14 | -------------------------------------------------------------------------------- /js-and-ts/robot.ts: -------------------------------------------------------------------------------- 1 | // This import wouldn't be possible without the allowJS option in tsconfig 2 | import { Formatter } from './format.js'; 3 | 4 | interface Robot { 5 | name: String; 6 | currentComputation: Number; 7 | } 8 | 9 | class Robot { 10 | constructor(public name: String) { 11 | this.name = name; 12 | this.currentComputation = 0; 13 | } 14 | 15 | // Given a mathematical operation, return a value based on the value passed, 16 | // the operation and the number 10 17 | compute(operation, value) { 18 | let computedValue = 0; 19 | switch(operation) { 20 | case '+': 21 | computedValue = value + 10; 22 | break; 23 | case '-': 24 | computedValue = value - 10; 25 | break; 26 | case '/': 27 | computedValue = value / 10; 28 | break; 29 | case '*': 30 | computedValue = value * 10; 31 | break; 32 | default: 33 | console.log("Does not compute!!") 34 | } 35 | this.currentComputation = computedValue; 36 | } 37 | 38 | // Using an external JS module, format the computed value from our robot 39 | displayCurrentComputation() { 40 | console.log(Formatter.surroundWithStars(this.currentComputation)); 41 | } 42 | } 43 | 44 | const hal = new Robot('Hal'); 45 | hal.compute('+', 32); 46 | hal.displayCurrentComputation(); -------------------------------------------------------------------------------- /js-and-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./built", 4 | "sourceMap": true, 5 | "allowJs": true, 6 | "target": "es6" 7 | }, 8 | "include": [ 9 | "./**/*" 10 | ] 11 | } -------------------------------------------------------------------------------- /jspm/.gitignore: -------------------------------------------------------------------------------- 1 | jspm_packages -------------------------------------------------------------------------------- /jspm/README.md: -------------------------------------------------------------------------------- 1 | **Setup jspm and install jspm dependencies** 2 | ``` 3 | npm install -g jspm@beta 4 | jspm install 5 | jspm dl-loader --edge 6 | ``` 7 | 8 | **run:** 9 | - install http-server package via 10 | ``` 11 | npm install -g http-server 12 | ``` 13 | - run server (if port 8080 it taken, pick any port that is free) 14 | ``` 15 | http-server -p 8080 16 | ``` 17 | -------------------------------------------------------------------------------- /jspm/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Jspm sample 4 | 5 | 6 | 7 | 8 |
9 | 15 | 16 | -------------------------------------------------------------------------------- /jspm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "jspm": { 3 | "dependencies": { 4 | "core-js": "npm:core-js@^2.4.0" 5 | }, 6 | "devDependencies": { 7 | "assert": "npm:jspm-nodelibs-assert@^0.2.0", 8 | "buffer": "npm:jspm-nodelibs-buffer@^0.2.0", 9 | "child_process": "npm:jspm-nodelibs-child_process@^0.2.0", 10 | "constants": "npm:jspm-nodelibs-constants@^0.2.0", 11 | "crypto": "npm:jspm-nodelibs-crypto@^0.2.0", 12 | "events": "npm:jspm-nodelibs-events@^0.2.0", 13 | "module": "npm:jspm-nodelibs-module@^0.2.0", 14 | "net": "npm:jspm-nodelibs-net@^0.2.0", 15 | "os": "npm:jspm-nodelibs-os@^0.2.0", 16 | "plugin-typescript": "github:frankwallis/plugin-typescript@^5.3.3", 17 | "stream": "npm:jspm-nodelibs-stream@^0.2.0", 18 | "string_decoder": "npm:jspm-nodelibs-string_decoder@^0.2.0", 19 | "util": "npm:jspm-nodelibs-util@^0.2.0", 20 | "vm": "npm:jspm-nodelibs-vm@^0.2.0" 21 | }, 22 | "peerDependencies": { 23 | "fs": "npm:jspm-nodelibs-fs@^0.2.0", 24 | "path": "npm:jspm-nodelibs-path@^0.2.0", 25 | "process": "npm:jspm-nodelibs-process@^0.2.0" 26 | }, 27 | "overrides": { 28 | "npm:inherits@2.0.3": { 29 | "ignore": [ 30 | "test.js" 31 | ] 32 | }, 33 | "npm:typescript@2.1.4": { 34 | "browser": {}, 35 | "map": { 36 | "buffer": "@empty", 37 | "child_process": "@empty", 38 | "fs": "@empty", 39 | "path": "@empty", 40 | "process": "@empty", 41 | "readline": "@empty" 42 | }, 43 | "dependencies": { 44 | "source-map-support": "*" 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /jspm/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Greeter } from "./greeter"; 2 | 3 | export function main(el: HTMLElement): void { 4 | let greeter = new Greeter(el); 5 | greeter.start(); 6 | } -------------------------------------------------------------------------------- /jspm/src/greeter.ts: -------------------------------------------------------------------------------- 1 | import repeat from "core-js/fn/string/repeat"; 2 | 3 | export class Greeter { 4 | element: HTMLElement; 5 | span: HTMLElement; 6 | timerToken: number; 7 | 8 | constructor(element: HTMLElement) { 9 | this.element = element; 10 | this.element.innerText += "The time is: "; 11 | this.span = document.createElement('span'); 12 | this.element.appendChild(this.span); 13 | this.span.innerText = new Date().toUTCString(); 14 | } 15 | 16 | start() { 17 | this.timerToken = setInterval(() => this.span.innerText = `"${repeat(new Date().toUTCString() + " ", 2)}"`, 500); 18 | } 19 | 20 | stop() { 21 | clearTimeout(this.timerToken); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jspm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "system", 4 | "sourceMap": true 5 | }, 6 | "exclude": [ 7 | "jspm_packages" 8 | ] 9 | } -------------------------------------------------------------------------------- /jsx/.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | node_modules/* 3 | -------------------------------------------------------------------------------- /jsx/README.md: -------------------------------------------------------------------------------- 1 | # jsx-demo 2 | 3 | ## Overview 4 | A demo project for showing off JSX in TypeScript 5 | 6 | ## Install dependencies 7 | ``` 8 | npm install 9 | ``` 10 | 11 | ## Compile 12 | ``` 13 | npm run build 14 | ``` 15 | 16 | ## Start http server 17 | ``` 18 | npm start 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /jsx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSX and TypeScript 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /jsx/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsx-demo", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "jquery": { 8 | "version": "3.3.1", 9 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", 10 | "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /jsx/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsx-demo", 3 | "version": "0.0.1", 4 | "description": "JSX in TypeScript Demo Project", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "node node_modules/typescript/bin/tsc", 9 | "start": "node node_modules/http-server/bin/http-server -o" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 14 | }, 15 | "keywords": [ 16 | "jsx", 17 | "tsx", 18 | "typescript", 19 | "ts", 20 | "react" 21 | ], 22 | "author": "Ryan Cavanaugh (Microsoft)", 23 | "license": "Apache", 24 | "bugs": { 25 | "url": "https://github.com/Microsoft/TypeScriptSamples/issues" 26 | }, 27 | "homepage": "https://github.com/Microsoft/TypeScriptSamples", 28 | "devDependencies": { 29 | "typescript": "latest", 30 | "http-server": "0.8.0", 31 | "@types/react-dom": "^15", 32 | "@types/react": "^15" 33 | }, 34 | "dependencies": { 35 | "react": "^15.6.1", 36 | "react-dom": "^15.6.1", 37 | "requirejs": "^2.1.20" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /jsx/require-config.js: -------------------------------------------------------------------------------- 1 | requirejs.config({ 2 | paths: { 3 | "react": ['/node_modules/react/dist/react'], 4 | "react-dom": ['/node_modules/react-dom/dist/react-dom'], 5 | "jquery": ['/node_modules/jquery/dist/jquery'] 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /jsx/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import {Greeter as Greetifier, GreeterProps as GreeterProps} from 'greeter'; 4 | 5 | function getRandomGreeting() { 6 | switch (Math.floor(Math.random() * 4)) { 7 | case 0: return 'Hello'; 8 | case 1: return 'Howdy'; 9 | case 2: return 'Greetings to you'; 10 | case 3: return 'Hail'; 11 | } 12 | } 13 | 14 | (() => { 15 | let props: GreeterProps = { 16 | whomToGreet: 'world!', 17 | }; 18 | 19 | ReactDOM.render(, $('#output').get(0)); 20 | })(); 21 | 22 | -------------------------------------------------------------------------------- /jsx/src/greeter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface GreeterProps extends React.Props { 4 | whomToGreet: string; 5 | greeting?: string | (() => string); 6 | } 7 | 8 | export class Greeter extends React.Component { 9 | render() { 10 | let g = this.props.greeting; 11 | 12 | let greeting = 'Hello'; 13 | 14 | if (typeof g === 'string') { 15 | greeting = g; 16 | } 17 | else if (g) { 18 | greeting = g(); 19 | } 20 | 21 | return
{greeting}, {this.props.whomToGreet}
; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jsx/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "outDir": "bin", 5 | "module": "amd" 6 | }, 7 | "exclude": [ 8 | "node_modules" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /mankala/Base.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Base { 4 | export interface IList { 5 | isHead: boolean; 6 | next: IList; 7 | prev: IList; 8 | data: T; 9 | insertAfter(entry: IList): IList; 10 | insertBefore(entry: IList): IList; 11 | empty(): boolean; 12 | } 13 | 14 | export class List implements IList { 15 | next: IList; 16 | prev: IList; 17 | 18 | constructor(public isHead: boolean, public data: T) { } 19 | 20 | empty(): boolean { 21 | return this.next == this; 22 | } 23 | 24 | insertAfter(entry: IList): IList { 25 | entry.next = this.next; 26 | entry.prev = this; 27 | this.next = entry; 28 | entry.next.prev = entry; 29 | return (entry); 30 | } 31 | 32 | insertBefore(entry: IList): IList { 33 | this.prev.next = entry; 34 | entry.next = this; 35 | entry.prev = this.prev; 36 | this.prev = entry; 37 | return entry; 38 | } 39 | } 40 | 41 | export function listMakeEntry(data: T): IList { 42 | var entry: List = new List(false, data); 43 | entry.prev = entry; 44 | entry.next = entry; 45 | return entry; 46 | } 47 | 48 | export function listMakeHead(): IList { 49 | var entry: List = new List(true, null); 50 | entry.prev = entry; 51 | entry.next = entry; 52 | return entry; 53 | } 54 | 55 | export function listRemove(entry: IList): IList { 56 | if (entry == null) { 57 | return null; 58 | } 59 | else if (entry.isHead) { 60 | return null; 61 | } 62 | else { 63 | entry.next.prev = entry.prev; 64 | entry.prev.next = entry.next; 65 | } 66 | return (entry); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /mankala/Driver.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | 7 | if (!this.document) { 8 | var game = new Mankala.Game(); 9 | game.test(); 10 | } 11 | -------------------------------------------------------------------------------- /mankala/Features.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Mankala { 4 | export class Features { 5 | public turnContinues = false; 6 | public seedStoredCount = 0; 7 | public capturedCount = 0; 8 | public spaceCaptured = NoSpace; 9 | 10 | public clear() { 11 | this.turnContinues = false; 12 | this.seedStoredCount = 0; 13 | this.capturedCount = 0; 14 | this.spaceCaptured = NoSpace; 15 | } 16 | 17 | public toString() { 18 | var stringBuilder = ""; 19 | if (this.turnContinues) { 20 | stringBuilder += " turn continues,"; 21 | } 22 | stringBuilder += " stores " + this.seedStoredCount; 23 | if (this.capturedCount > 0) { 24 | stringBuilder += " captures " + this.capturedCount + " from space " + this.spaceCaptured; 25 | } 26 | return stringBuilder; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mankala/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Mankala 2 | 3 | ## Overview 4 | 5 | This sample implements the game logic for the Mankala board game. The following 6 | features of TypeScript are highlighted: 7 | - Multi-file compilation: The sample is compiled from several separate files 8 | - SVG: Geometry 9 | - Class inheritance: Rectangle and Square in geometry.ts 10 | - Command line: The game driver can be run as a command-line app using cscript 11 | 12 | 13 | ## Running 14 | 15 | ``` 16 | tsc Driver.ts --sourcemap -out game.js 17 | cscript game.js 18 | ``` 19 | 20 | For web execution use play.html. 21 | 22 | -------------------------------------------------------------------------------- /mankala/geometry.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Mankala { 4 | export class Rectangle { 5 | 6 | constructor (public x: number, public y: number, 7 | public width: number, public height: number) { } 8 | 9 | public square() { 10 | var len = this.width; 11 | var adj = 0; 12 | if (len > this.height) { 13 | len = this.height; 14 | adj = (this.width - len) / 2; 15 | return new Square(this.x + adj, this.y, len); 16 | } else { 17 | adj = (this.height - len) / 2; 18 | return new Square(this.x, this.y + adj, len); 19 | } 20 | } 21 | 22 | public inner(factor: number) { 23 | var iw = factor * this.width; 24 | var ih = factor * this.height; 25 | var ix = this.x + ((this.width - iw) / 2); 26 | var iy = this.y + ((this.height - ih) / 2); 27 | return (new Rectangle(ix, iy, iw, ih)); 28 | } 29 | 30 | public proportionalSplitHoriz(...proportionalWidths: number[]) { 31 | var totalPropWidth = 0; 32 | var i:number; 33 | 34 | for (i = 0; i < proportionalWidths.length; i++) { 35 | totalPropWidth += proportionalWidths[i]; 36 | } 37 | 38 | var totalWidth = 0; 39 | var widths: number[] = []; 40 | for (i = 0; i < proportionalWidths.length; i++) { 41 | widths[i] = (proportionalWidths[i] / totalPropWidth) * this.width; 42 | totalWidth += widths[i]; 43 | } 44 | 45 | var extraWidth = this.width - totalWidth; 46 | /* Add back round-off error equally to all rectangles */ 47 | i = 0; 48 | while (extraWidth > 0) { 49 | widths[i]++; 50 | extraWidth--; 51 | if ((++i) == widths.length) { 52 | i = 0; 53 | } 54 | } 55 | var rects: Rectangle[] = []; 56 | var curX = this.x; 57 | for (i = 0; i < widths.length; i++) { 58 | rects[i] = new Rectangle(curX, this.y, widths[i], this.height); 59 | curX += widths[i]; 60 | } 61 | return rects; 62 | } 63 | 64 | private proportionalSplitVert(...proportionalHeights: number[]): Rectangle[]{ 65 | var totalPropHeight = 0; 66 | var i: number; 67 | 68 | for (i = 0; i < proportionalHeights.length; i++) { 69 | totalPropHeight += proportionalHeights[i]; 70 | } 71 | 72 | var totalHeight = 0; 73 | var heights: number[] = []; 74 | for (i = 0; i < proportionalHeights.length; i++) { 75 | heights[i] = (proportionalHeights[i] / totalPropHeight) * this.height; 76 | totalHeight += heights[i]; 77 | } 78 | 79 | var extraHeight = this.height - totalHeight; 80 | /* Add back round-off error equally to all rectangles */ 81 | i = 0; 82 | while (extraHeight > 0) { 83 | heights[i]++; 84 | extraHeight--; 85 | if ((++i) == heights.length) { 86 | i = 0; 87 | } 88 | } 89 | var rects: Rectangle[] = []; 90 | var curY = this.y; 91 | for (i = 0; i < heights.length; i++) { 92 | rects[i] = new Rectangle(this.x, curY, this.width, heights[i]); 93 | curY += heights[i]; 94 | } 95 | return rects; 96 | } 97 | 98 | public subDivideHoriz(n: number) { 99 | var rects: Rectangle[] = []; 100 | 101 | var tileWidth = this.width / n; 102 | var rem = this.width % n; 103 | var tileX = this.x; 104 | for (var i = 0; i < n; i++) { 105 | rects[i] = new Rectangle(tileX, this.y, tileWidth, this.height); 106 | if (rem > 0) { 107 | rects[i].width++; 108 | rem--; 109 | } 110 | tileX += rects[i].width; 111 | } 112 | return rects; 113 | } 114 | 115 | public subDivideVert(n: number) { 116 | var rects: Rectangle[] = []; 117 | var tileHeight = this.height / n; 118 | var rem = this.height % n; 119 | var tileY = this.y; 120 | for (var i = 0; i < n; i++) { 121 | rects[i] = new Rectangle(this.x, tileY, this.width, tileHeight); 122 | if (rem > 0) { 123 | rects[i].height++; 124 | rem--; 125 | } 126 | tileY += rects[i].height; 127 | } 128 | return rects; 129 | } 130 | } 131 | 132 | export class Square extends Rectangle { 133 | len: number; 134 | 135 | constructor(x: number, y: number, len: number) { 136 | super(x, y, len, len); 137 | this.len = len; 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /mankala/play.css: -------------------------------------------------------------------------------- 1 | .hscore { 2 | font-size: 14px; 3 | font-weight: bold; 4 | color: brown; 5 | } 6 | 7 | .cscore { 8 | font-size: 14px; 9 | font-weight: bold; 10 | color: saddlebrown; 11 | } -------------------------------------------------------------------------------- /mankala/play.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mankala 7 | 8 | 9 | 10 | 11 | 12 |
Human: 0
13 |
Computer: 0
14 | 15 | 16 | -------------------------------------------------------------------------------- /mankala/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "outFile": "game.js" 5 | } 6 | } -------------------------------------------------------------------------------- /node/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /node/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Node.js 2 | ## Overview 3 | 4 | This sample implements a very basic [node.js](https://nodejs.org/) application using TypeScript. 5 | 6 | ## Running 7 | First of all, install all dependencies with: 8 | ```bash 9 | npm install 10 | ``` 11 | 12 | Then, you can run each of the listed [examples](#examples) with the following command from the this project root folder: 13 | ```bash 14 | ts-node ./examples/example-name.ts 15 | ``` 16 | 17 | To run the HTTPS server example, just: 18 | ```bash 19 | ts-node ./examples/HttpServer.ts 20 | ``` 21 | 22 | This examples are running through [ts-node](https://github.com/TypeStrong/ts-node), which is not recommended in production environments. You can also build those examples with: 23 | ```bash 24 | npm run build 25 | ``` 26 | 27 | And then running the compiled JavaScript (JS) example file with: 28 | ```bash 29 | node ./dist/example-name.js 30 | ``` 31 | 32 | ## Examples 33 | * [TcpServer](./src/TcpServer.ts) - a simple TCP server 34 | * [HttpServer](./src/HttpServer.ts) - a simple HTTPS server 35 | * [API Client](./src/APIClient.ts) - client that sends a "ping" 36 | * [API Server](./src/APIServer.ts) - server the receives that "ping" and responds with a "pong" 37 | * [Word counter](./src/WordCounter.ts) - shows how many of the desired words are presented in a file 38 | * [Wikipedia Search](./src/Wikipedia.ts) - searches the [Wikipedia](https://en.wikipedia.org/w/api.php?) website 39 | 40 | **note**: due to HTTP/HTTPS distinct way of handle localhost requests, in the examples HTTP is used instead of HTTPS because is a more easy way to set it up. 41 | 42 | ## Standards 43 | A modified version of the [Microsoft Linter Standards](https://github.com/Microsoft/tslint-microsoft-contrib) is used. Please be mindful that they are here to help you out improve you code. 44 | 45 | ## Git Hooks 46 | Due to [Husky](https://github.com/typicode/husky) integration, before any push to this Github repository, [TSLint](https://github.com/palantir/tslint) will run and then point out all the fixes that needs to be done to follow the set of code [standards](#standards); if nothing needs to be corrected, you then can push it :) 47 | -------------------------------------------------------------------------------- /node/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Just running the command line program. 3 | */ 4 | import { ChildProcess, exec } from 'child_process'; 5 | 6 | const main: Function = (): ChildProcess => { 7 | let command: string = `ts-node ./src/${process.argv[3]}.ts`; 8 | 9 | if (process.argv[2] === 'js') { 10 | exec('tsc'); 11 | 12 | command = `node ./dist/${process.argv[3]}.js`; 13 | } 14 | 15 | return exec(command); 16 | }; 17 | 18 | main(); 19 | -------------------------------------------------------------------------------- /node/lorem.txt: -------------------------------------------------------------------------------- 1 | "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?" 2 | -------------------------------------------------------------------------------- /node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node", 3 | "version": "1.0.0", 4 | "description": "Node examples using TypeScript", 5 | "scripts": { 6 | "build": "tsc", 7 | "lint": "tslint --config tslint.json --project ." 8 | }, 9 | "contributors": [ 10 | { 11 | "name": "Mohamed Hegazy", 12 | "url": "https://github.com/mhegazy" 13 | }, 14 | { 15 | "name": "Lucas de Almeida Carotta", 16 | "url": "https://github.com/Fazendaaa" 17 | } 18 | ], 19 | "devDependencies": { 20 | "@types/node": "^10.11.4", 21 | "ts-node": "^7.0.1", 22 | "tslint": "^5.11.0", 23 | "tslint-microsoft-contrib": "^5.2.1", 24 | "typescript": "^3.1.1" 25 | }, 26 | "husky": { 27 | "hooks": { 28 | "pre-push": "npm run lint" 29 | } 30 | }, 31 | "dependencies": {} 32 | } 33 | -------------------------------------------------------------------------------- /node/src/APIClient.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * API client example. 3 | */ 4 | import { IncomingMessage, request } from 'http'; 5 | 6 | const handleResponse = (resolve: (data: string) => void, reject: (data: Error) => void, response: IncomingMessage): void => { 7 | let chunk = ''; 8 | const { statusCode } = response; 9 | 10 | if (statusCode !== 200) { 11 | reject(new Error('Server error')); 12 | } 13 | 14 | response.setEncoding('utf8') 15 | .on('error', reject) 16 | .on('uncaughtException', reject) 17 | .on('data', (data: string) => chunk += data) 18 | .on('end', () => { resolve(chunk); }); 19 | }; 20 | 21 | const ping = async (): Promise => new Promise((resolve: (data: string) => void, reject: (data: Error) => void) => { 22 | const post = request({ 23 | path: '/', 24 | port: 8080, 25 | method: 'GET', 26 | hostname: 'localhost', 27 | headers: { 28 | 'Content-Type': 'text/plain' 29 | } 30 | }); 31 | const curriedHandleResponse = ((response: IncomingMessage) => { handleResponse(resolve, reject, response); }); 32 | 33 | post.write('ping'); 34 | post.on('response', curriedHandleResponse); 35 | post.on('error', () => { reject(new Error('Request error')); }); 36 | post.end(); 37 | }); 38 | 39 | ping().then(console.log).catch(console.error); 40 | -------------------------------------------------------------------------------- /node/src/APIServer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * API example server. 3 | */ 4 | import { createServer, IncomingMessage, ServerResponse } from 'http'; 5 | 6 | const server = createServer((sent: IncomingMessage, res: ServerResponse) => { 7 | const body = []; 8 | 9 | sent.on('data', (data: Buffer) => body.push(data)); 10 | sent.on('error', (err) => { console.error(err); }); 11 | sent.on('end', () => { 12 | const message = Buffer.concat(body).toString(); 13 | 14 | console.log(message); 15 | }); 16 | 17 | res.writeHead(200, { 'Content-Type': 'text/plain' }); 18 | res.end('pong'); 19 | }); 20 | 21 | server.listen(8080, 'localhost', () => { console.log('Server running at https://localhost:8080/'); }); 22 | -------------------------------------------------------------------------------- /node/src/HttpServer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * HTTPS server example. 3 | */ 4 | import { createServer, IncomingMessage, ServerResponse } from 'http'; 5 | 6 | const host = 'localhost'; 7 | const port = 1337; 8 | 9 | const server = createServer((_: IncomingMessage, res: ServerResponse) => { 10 | res.writeHead(200, { 'Content-Type': 'text/plain' }); 11 | res.end('Hello World\n'); 12 | }); 13 | 14 | server.listen(port, host, () => { console.log(`Server running at ${host}:${port}`); }); 15 | -------------------------------------------------------------------------------- /node/src/TcpServer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TCP server example. 3 | */ 4 | import { createServer, Socket } from 'net'; 5 | 6 | const host = 'localhost'; 7 | const port = 1337; 8 | 9 | const server = createServer((socket: Socket) => { 10 | socket.write('Echo server\r\n'); 11 | socket.pipe(socket); 12 | }); 13 | 14 | server.listen(port, host, () => { console.log(`Server running at ${host}:${port}`); }); 15 | -------------------------------------------------------------------------------- /node/src/Wikipedia.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Searches Wikipedia database 3 | */ 4 | import { IncomingMessage } from 'http'; 5 | import { request } from 'https'; 6 | 7 | const response = (res: IncomingMessage) => { 8 | const { statusCode } = res; 9 | let chunk = ''; 10 | 11 | if (statusCode !== 200) { 12 | console.error(new Error(`[Request status ${statusCode}] Not accepted`)); 13 | } else { 14 | res.on('error', console.error) 15 | .on('uncaughtException', console.error) 16 | .on('data', (data: string) => chunk += data) 17 | .on('end', () => { 18 | const result = JSON.parse(chunk); 19 | 20 | console.log(result); 21 | }); 22 | } 23 | }; 24 | 25 | const search = 'microsoft'; 26 | const query = `action=query&format=json&list=search&srsearch=${encodeURI(search)}`; 27 | const path = `/w/api.php?${query}`; 28 | const options = { 29 | path, 30 | method: 'GET', 31 | hostname: 'en.wikipedia.org', 32 | headers: { 33 | Accept: 'application/json', 34 | 'Content-Type': 'text/html' 35 | } 36 | }; 37 | const wikipedia = request(options); 38 | 39 | wikipedia.on('error', console.error) 40 | .on('response', response) 41 | .end(); 42 | -------------------------------------------------------------------------------- /node/src/WordCounter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Reads file then shows how many matching occurrences of a word is found 3 | */ 4 | import { readFileSync } from 'fs'; 5 | import { join } from 'path'; 6 | 7 | const path = join(__dirname, '../lorem.txt'); 8 | const ipsum = readFileSync(path, { encoding: 'utf8' }); 9 | const word = 'ut'; 10 | const re = new RegExp(word, 'gm'); 11 | const matching = ipsum.match(re); 12 | 13 | console.log(`Number of occurrences of the \"${word}\" word is: ${matching.length}`); 14 | -------------------------------------------------------------------------------- /node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./dist", /* Redirect output structure to the directory. */ 15 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | "strictNullChecks": true, /* Enable strict null checks. */ 27 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | 38 | /* Module Resolution Options */ 39 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 40 | "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 46 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | 49 | /* Source Map Options */ 50 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 51 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 52 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 53 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 54 | 55 | /* Experimental Options */ 56 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 57 | "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 58 | }, 59 | "exclude": [ 60 | "./index.ts" 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /node/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint-microsoft-contrib" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "typedef": false, 9 | "no-console": false 10 | }, 11 | "rulesDirectory": [] 12 | } 13 | -------------------------------------------------------------------------------- /raytracer/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Raytracer 2 | 3 | ## Overview 4 | 5 | This sample shows a raytracer implementation in TypeScript. 6 | 7 | ## Running 8 | ``` 9 | tsc --sourcemap raytracer.ts 10 | start raytracer.html 11 | ``` 12 | -------------------------------------------------------------------------------- /raytracer/raytracer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Raytracer 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /raytracer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /react-flux-babel-karma/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | dist/ 25 | 26 | # Visual Studo 2015 cache/options directory 27 | .vs/ 28 | 29 | # MSTest test Results 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | 33 | # NUNIT 34 | *.VisualState.xml 35 | TestResult.xml 36 | 37 | # JUnit test results 38 | test-results 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding addin-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | # TODO: Comment the next line if you want to checkin your web deploy settings 137 | # but database connection strings (with potential passwords) will be unencrypted 138 | *.pubxml 139 | *.publishproj 140 | 141 | # NuGet Packages 142 | *.nupkg 143 | # The packages folder can be ignored because of Package Restore 144 | **/packages/* 145 | # except build/, which is used as an MSBuild target. 146 | !**/packages/build/ 147 | # Uncomment if necessary however generally it will be regenerated when needed 148 | #!**/packages/repositories.config 149 | 150 | # Windows Azure Build Output 151 | csx/ 152 | *.build.csdef 153 | 154 | # Windows Store app package directory 155 | AppPackages/ 156 | 157 | # Others 158 | *.[Cc]ache 159 | ClientBin/ 160 | [Ss]tyle[Cc]op.* 161 | ~$* 162 | *~ 163 | *.dbmdl 164 | *.dbproj.schemaview 165 | *.pfx 166 | *.publishsettings 167 | node_modules/ 168 | bower_components/ 169 | typings/ 170 | 171 | # RIA/Silverlight projects 172 | Generated_Code/ 173 | 174 | # Backup & report files from converting an old project file 175 | # to a newer Visual Studio version. Backup files are not needed, 176 | # because we have git ;-) 177 | _UpgradeReport_Files/ 178 | Backup*/ 179 | UpgradeLog*.XML 180 | UpgradeLog*.htm 181 | 182 | # SQL Server files 183 | *.mdf 184 | *.ldf 185 | 186 | # Business Intelligence projects 187 | *.rdl.data 188 | *.bim.layout 189 | *.bim_*.settings 190 | 191 | # Microsoft Fakes 192 | FakesAssemblies/ 193 | 194 | # Node.js Tools for Visual Studio 195 | .ntvs_analysis.dat 196 | 197 | # Visual Studio 6 build log 198 | *.plg 199 | 200 | # Visual Studio 6 workspace options file 201 | *.opt 202 | -------------------------------------------------------------------------------- /react-flux-babel-karma/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 John Reilly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /react-flux-babel-karma/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript, Babel, React, and Karma Sample 2 | 3 | ## Getting started 4 | 5 | You'll need [node / npm](https://nodejs.org/) installed. To get up and running just enter: 6 | 7 | ``` 8 | npm install 9 | npm run serve 10 | ``` 11 | 12 | This will: 13 | 14 | 1. Download the npm packages you need (including the type definitions from DefinitelyTyped) 15 | 2. Compile the code and serve it up at [http://localhost:8080](http://localhost:8080) 16 | 17 | Now you need dev tools. There's a world of choice out there; there's [Atom](https://atom.io/), there's [VS Code](https://www.visualstudio.com/en-us/products/code-vs.aspx), there's [Sublime](http://www.sublimetext.com/). There's even something called [Visual Studio](http://www.visualstudio.com). It's all your choice really. 18 | 19 | For myself I've been using Atom combined with the mighty [atom-typescript package](https://atom.io/packages/atom-typescript). I advise you to give it a go. You won't look back. 20 | 21 | ## I want to have an ASP.Net project and use Visual Studio + IIS Express to serve this instead 22 | 23 | If you drop this code into an empty Visual Studio ASP.Net project should should be good to go. You'll need this section in your `web.config` to ensure Visual Studio serves from the `dist` directory: 24 | 25 | ``` 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ``` 39 | 40 | And rather than running `npm run serve` you'll want to use `npm run watch`. (This builds / watches your code / runs tests etc but does **not** spin up a web server.) 41 | 42 | Finally you'll want to set the following TypeScript options for your project 43 | 44 | - ECMAScript Version: ECMAScript 6 45 | - JSX compilation in TSX files: Preserve 46 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "commonjs": true, 5 | }, 6 | "rules": { 7 | "camelcase": 2, 8 | "comma-spacing": 1, 9 | "consistent-return": 2, 10 | "curly": [ 2, "all" ], 11 | "dot-notation": [ 12 | 2, 13 | { "allowKeywords": true } 14 | ], 15 | "eol-last": 2, 16 | "eqeqeq": 2, 17 | "keyword-spacing": 2, 18 | "new-cap": 2, 19 | "new-parens": 2, 20 | "no-alert": 2, 21 | "no-array-constructor": 2, 22 | "no-caller": 2, 23 | "no-catch-shadow": 2, 24 | "no-eval": 2, 25 | "no-extend-native": 2, 26 | "no-extra-bind": 2, 27 | "no-extra-parens": [ 2, "functions" ], 28 | "no-implied-eval": 2, 29 | "no-iterator": 2, 30 | "no-labels": 2, 31 | "no-label-var": 2, 32 | "no-lone-blocks": 2, 33 | "no-loop-func": 2, 34 | "no-multi-str": 2, 35 | "no-native-reassign": 2, 36 | "no-new": 2, 37 | "no-new-func": 2, 38 | "no-new-object": 2, 39 | "no-new-wrappers": 2, 40 | "no-octal-escape": 2, 41 | "no-proto": 2, 42 | "no-return-assign": 2, 43 | "no-script-url": 2, 44 | "no-sequences": 2, 45 | "no-shadow": 2, 46 | "no-shadow-restricted-names": 2, 47 | "no-spaced-func": 2, 48 | "no-trailing-spaces": 1, 49 | "no-undef-init": 2, 50 | "no-unused-expressions": 2, 51 | "no-use-before-define": [ 2, "nofunc" ], 52 | "no-with": 2, 53 | "quotes": [ 1, "single" ], 54 | "semi": 2, 55 | "semi-spacing": [ 56 | 2, 57 | { 58 | "before": false, 59 | "after": true 60 | } 61 | ], 62 | "space-infix-ops": 2, 63 | "space-unary-ops": [ 64 | 2, 65 | { 66 | "words": true, 67 | "nonwords": false 68 | } 69 | ], 70 | "strict": [ 2, "global" ], 71 | "yoda": [ 2, "never" ] 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/clean.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var del = require('del'); 4 | var gutil = require('gulp-util'); 5 | var fs = require('fs'); 6 | 7 | function run(done) { 8 | fs.stat('./dist', function(err){ 9 | if (err) { 10 | // Never existed 11 | done(); 12 | } 13 | else { 14 | del(['./dist'], { force: true }) 15 | .then(function(paths) { 16 | gutil.log('Deleted files/folders:\n', paths.join('\n')); 17 | done(); 18 | }) 19 | .catch(function(error) { 20 | gutil.log('Problem deleting:\n', error); 21 | done(); 22 | }); 23 | } 24 | }); 25 | } 26 | 27 | module.exports = { 28 | run: function(done) { return run(done); } 29 | }; 30 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/inject.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var inject = require('gulp-inject'); 5 | var glob = require('glob'); 6 | 7 | function injectIndex(options) { 8 | function run() { 9 | var target = gulp.src('./src/index.html'); 10 | var sources = gulp.src([ 11 | //'./dist/styles/main*.css', 12 | './dist/scripts/vendor*.js', 13 | './dist/scripts/main*.js' 14 | ], { read: false }); 15 | 16 | return target 17 | .pipe(inject(sources, { ignorePath: '/dist/', addRootSlash: false, removeTags: true })) 18 | .pipe(gulp.dest('./dist')); 19 | } 20 | 21 | var jsCssGlob = 'dist/**/*.{js,css}'; 22 | 23 | function checkForInitialFilesThenRun() { 24 | glob(jsCssGlob, function (er, files) { 25 | var filesWeNeed = ['dist/scripts/main', 'dist/scripts/vendor'/*, 'dist/styles/main'*/]; 26 | 27 | function fileIsPresent(fileWeNeed) { 28 | return files.some(function(file) { 29 | return file.indexOf(fileWeNeed) !== -1; 30 | }); 31 | } 32 | 33 | if (filesWeNeed.every(fileIsPresent)) { 34 | run('initial build'); 35 | } else { 36 | checkForInitialFilesThenRun(); 37 | } 38 | }); 39 | } 40 | 41 | checkForInitialFilesThenRun(); 42 | 43 | if (options.shouldWatch) { 44 | gulp.watch(jsCssGlob, function(evt) { 45 | if (evt.path && evt.type === 'changed') { 46 | run(evt.path); 47 | } 48 | }); 49 | } 50 | } 51 | 52 | module.exports = { 53 | build: function() { return injectIndex({ shouldWatch: false }); }, 54 | watch: function() { return injectIndex({ shouldWatch: true }); } 55 | }; 56 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/staticFiles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var cache = require('gulp-cached'); 5 | 6 | var targets = [ 7 | { description: 'INDEX', src: './src/index.html', dest: './dist' } 8 | ]; 9 | 10 | function copy(options) { 11 | function run(target) { 12 | gulp.src(target.src) 13 | .pipe(cache(target.description)) 14 | .pipe(gulp.dest(target.dest)); 15 | } 16 | 17 | function watch(target) { 18 | gulp.watch(target.src, function() { run(target); }); 19 | } 20 | 21 | targets.forEach(run); 22 | 23 | if (options.shouldWatch) { 24 | targets.forEach(watch); 25 | } 26 | } 27 | 28 | module.exports = { 29 | build: function() { return copy({ shouldWatch: false }); }, 30 | watch: function() { return copy({ shouldWatch: true }); } 31 | }; 32 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Server = require('karma').Server; 4 | var path = require('path'); 5 | var gutil = require('gulp-util'); 6 | 7 | function runTests(options) { 8 | // Documentation: https://karma-runner.github.io/0.13/dev/public-api.html 9 | var karmaConfig = { 10 | configFile: path.join(__dirname, '../karma.conf.js'), 11 | singleRun: !options.shouldWatch, 12 | 13 | plugins: ['karma-webpack', 'karma-jasmine', 'karma-mocha-reporter', 'karma-sourcemap-loader', 'karma-phantomjs-launcher'], 14 | reporters: ['mocha'] 15 | }; 16 | 17 | if (options.done) { 18 | karmaConfig.plugins.push('karma-junit-reporter'); 19 | karmaConfig.reporters.push('junit'); 20 | } else { 21 | karmaConfig.plugins.push('karma-notify-reporter'); 22 | karmaConfig.reporters.push('notify'); 23 | } 24 | 25 | new Server(karmaConfig, karmaCompleted).start(); 26 | 27 | function karmaCompleted(exitCode) { 28 | if (options.done) { 29 | if (exitCode === 1) { 30 | gutil.log('Karma: tests failed with code ' + exitCode); 31 | } else { 32 | gutil.log('Karma completed!'); 33 | } 34 | options.done(); 35 | } 36 | else { 37 | process.exit(exitCode); 38 | } 39 | } 40 | } 41 | 42 | module.exports = { 43 | run: function(done) { return runTests({ shouldWatch: false, done: done }); }, 44 | watch: function() { return runTests({ shouldWatch: true }); } 45 | }; 46 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulp/webpack.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var gutil = require('gulp-util'); 5 | var webpack = require('webpack'); 6 | var WebpackNotifierPlugin = require('webpack-notifier'); 7 | var failPlugin = require('webpack-fail-plugin'); 8 | var webpackConfig = require('../webpack.config.js'); 9 | var packageJson = require('../package.json'); 10 | 11 | function buildProduction(done) { 12 | // modify some webpack config options 13 | var myProdConfig = webpackConfig; 14 | myProdConfig.output.filename = '[name].[hash].js'; 15 | 16 | myProdConfig.plugins = myProdConfig.plugins.concat( 17 | new webpack.DefinePlugin({ 18 | 'process.env': { 19 | 'NODE_ENV': JSON.stringify('production') 20 | } 21 | }), 22 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.[hash].js' }), 23 | new webpack.optimize.UglifyJsPlugin({ 24 | compress: { 25 | warnings: true 26 | } 27 | }), 28 | failPlugin 29 | ); 30 | 31 | // run webpack 32 | webpack(myProdConfig, function (err, stats) { 33 | if (err) { throw new gutil.PluginError('webpack:build', err); } 34 | gutil.log('[webpack:build]', stats.toString({ 35 | colors: true 36 | })); 37 | 38 | if (done) { done(); } 39 | }); 40 | } 41 | 42 | function createDevCompiler() { 43 | // modify some webpack config options 44 | var myDevConfig = webpackConfig; 45 | myDevConfig.devtool = 'inline-source-map'; 46 | 47 | myDevConfig.plugins = myDevConfig.plugins.concat( 48 | new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.js' }), 49 | new WebpackNotifierPlugin({ title: 'Webpack build', excludeWarnings: true }) 50 | ); 51 | 52 | // create a single instance of the compiler to allow caching 53 | return webpack(myDevConfig); 54 | } 55 | 56 | function build() { 57 | return new Promise(function (resolve, reject) { 58 | buildProduction(function (err) { 59 | if (err) { 60 | reject(err); 61 | } else { 62 | resolve('webpack built'); 63 | } 64 | }); 65 | }); 66 | } 67 | 68 | function watch() { 69 | var firstBuildDone = false; 70 | 71 | return new Promise(function (resolve, reject) { 72 | var devCompiler = createDevCompiler(); 73 | devCompiler.watch({ // watch options: 74 | aggregateTimeout: 300 // wait so long for more changes 75 | }, function (err, stats) { 76 | if (err) { 77 | if (!firstBuildDone) { 78 | firstBuildDone = true; 79 | reject(err); 80 | } 81 | throw new gutil.PluginError('webpack:build-dev', err); 82 | } else { 83 | if (!firstBuildDone) { 84 | firstBuildDone = true; 85 | resolve('webpack built'); 86 | } 87 | } 88 | 89 | gutil.log('[webpack:build-dev]', stats.toString({ 90 | chunks: false, 91 | colors: true 92 | })); 93 | }); 94 | }); 95 | } 96 | 97 | module.exports = { 98 | build: function () { return build(); }, 99 | watch: function () { return watch(); } 100 | }; 101 | -------------------------------------------------------------------------------- /react-flux-babel-karma/gulpFile.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var, strict, prefer-arrow-callback */ 2 | 'use strict'; 3 | 4 | var gulp = require('gulp'); 5 | var gutil = require('gulp-util'); 6 | var eslint = require('gulp-eslint'); 7 | var webpack = require('./gulp/webpack'); 8 | var staticFiles = require('./gulp/staticFiles'); 9 | var tests = require('./gulp/tests'); 10 | var clean = require('./gulp/clean'); 11 | var inject = require('./gulp/inject'); 12 | 13 | var lintSrcs = ['./gulp/**/*.js']; 14 | 15 | gulp.task('delete-dist', function (done) { 16 | clean.run(done); 17 | }); 18 | 19 | gulp.task('build-js', ['delete-dist'], function(done) { 20 | webpack.build().then(function() { done(); }); 21 | }); 22 | 23 | gulp.task('build-other', ['delete-dist'], function() { 24 | staticFiles.build(); 25 | }); 26 | 27 | gulp.task('build', ['build-js', 'build-other', 'lint'], function () { 28 | inject.build(); 29 | }); 30 | 31 | gulp.task('lint', function () { 32 | return gulp.src(lintSrcs) 33 | .pipe(eslint()) 34 | .pipe(eslint.format()); 35 | }); 36 | 37 | gulp.task('watch', ['delete-dist'], function(done) { 38 | process.env.NODE_ENV = 'development'; 39 | Promise.all([ 40 | webpack.watch()//, 41 | //less.watch() 42 | ]).then(function() { 43 | gutil.log('Now that initial assets (js and css) are generated inject will start...'); 44 | inject.watch(); 45 | done(); 46 | }).catch(function(error) { 47 | gutil.log('Problem generating initial assets (js and css)', error); 48 | }); 49 | 50 | gulp.watch(lintSrcs, ['lint']); 51 | staticFiles.watch(); 52 | tests.watch(); 53 | }); 54 | 55 | gulp.task('watch-and-serve', ['watch'], function() { 56 | // local as not required for build 57 | var express = require('express') 58 | var app = express() 59 | 60 | app.use(express.static('dist', {'index': 'index.html'})) 61 | app.listen(8080); 62 | }); 63 | -------------------------------------------------------------------------------- /react-flux-babel-karma/karma.conf.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var, strict */ 2 | 'use strict'; 3 | 4 | var webpackConfig = require('./webpack.config.js'); 5 | 6 | module.exports = function(config) { 7 | // Documentation: https://karma-runner.github.io/0.13/config/configuration-file.html 8 | config.set({ 9 | browsers: [ 'PhantomJS' ], 10 | 11 | files: [ 12 | // This ensures we have the es6 shims in place from babel and that angular and angular-mocks are loaded 13 | // and then loads all the tests 14 | 'test/main.js' 15 | ], 16 | 17 | port: 9876, 18 | 19 | frameworks: [ 'jasmine' ], 20 | 21 | logLevel: config.LOG_INFO, //config.LOG_DEBUG 22 | 23 | preprocessors: { 24 | 'test/main.js': [ 'webpack', 'sourcemap' ] 25 | }, 26 | 27 | webpack: { 28 | devtool: 'inline-source-map', 29 | module: webpackConfig.module, 30 | resolve: webpackConfig.resolve 31 | }, 32 | 33 | webpackMiddleware: { 34 | quiet: true, 35 | stats: { 36 | colors: true 37 | } 38 | }, 39 | 40 | // reporter options 41 | mochaReporter: { 42 | colors: { 43 | success: 'bgGreen', 44 | info: 'cyan', 45 | warning: 'bgBlue', 46 | error: 'bgRed' 47 | } 48 | }, 49 | 50 | // the default configuration 51 | junitReporter: { 52 | outputDir: 'test-results', // results will be saved as $outputDir/$browserName.xml 53 | outputFile: undefined, // if included, results will be saved as $outputDir/$browserName/$outputFile 54 | suite: '' 55 | }, 56 | 57 | coverageReporter: { 58 | reporters:[ 59 | //{type: 'html', dir:'coverage/'}, // https://github.com/karma-runner/karma-coverage/issues/123 60 | {type: 'text'}, 61 | {type: 'text-summary'} 62 | ], 63 | } 64 | }); 65 | }; 66 | -------------------------------------------------------------------------------- /react-flux-babel-karma/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-flux-babel-karma", 3 | "version": "1.0.0", 4 | "description": "ES6 + TypeScript + Babel + React + Karma: The Secret Recipe", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "karma start --reporters mocha,junit --single-run --browsers PhantomJS", 8 | "serve": "gulp watch-and-serve", 9 | "watch": "gulp watch", 10 | "build": "gulp build" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/microsoft/typescriptsamples.git" 15 | }, 16 | "keywords": [ 17 | "react", 18 | "flux", 19 | "es2016", 20 | "typescript", 21 | "webpack" 22 | ], 23 | "author": "John Reilly", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/microsoft/typescriptsamples/issues" 27 | }, 28 | "homepage": "https://github.com/Microsoft/TypeScriptSamples/tree/master/react-flux-babel-karma#readme", 29 | "devDependencies": { 30 | "@types/fbemitter": "^2.0.32", 31 | "@types/flux": "0.0.32", 32 | "@types/jasmine": "^2.5.35", 33 | "@types/react": "^0.14.41", 34 | "@types/react-addons-test-utils": "^0.14.15", 35 | "@types/react-bootstrap": "0.0.33", 36 | "@types/react-dom": "^0.14.18", 37 | "babel": "^6.0.0", 38 | "babel-core": "^6.0.0", 39 | "babel-loader": "^6.0.0", 40 | "babel-preset-es2015": "^6.0.0", 41 | "babel-preset-es2016": "^6.16.0", 42 | "babel-preset-react": "^6.0.0", 43 | "del": "^2.0.2", 44 | "eslint": "^2.0.0", 45 | "express": "^4.13.3", 46 | "glob": "^7.0.0", 47 | "gulp": "^3.9.0", 48 | "gulp-autoprefixer": "^3.1.0", 49 | "gulp-cached": "^1.1.0", 50 | "gulp-cssmin": "^0.1.7", 51 | "gulp-eslint": "^2.0.0", 52 | "gulp-if": "^2.0.0", 53 | "gulp-inject": "^3.0.0", 54 | "gulp-notify": "^2.2.0", 55 | "gulp-sourcemaps": "^1.5.2", 56 | "gulp-streamify": "1.0.2", 57 | "gulp-uglify": "^1.2.0", 58 | "gulp-util": "^3.0.6", 59 | "jasmine-core": "^2.3.4", 60 | "karma": "^1.2.0", 61 | "karma-jasmine": "^1.0.0", 62 | "karma-junit-reporter": "^1.0.0", 63 | "karma-mocha-reporter": "^2.0.0", 64 | "karma-notify-reporter": "^1.0.0", 65 | "karma-phantomjs-launcher": "^1.0.0", 66 | "karma-sourcemap-loader": "^0.3.6", 67 | "karma-webpack": "^2.0.2", 68 | "phantomjs-prebuilt": "^2.1.4", 69 | "ts-loader": "^2.0.1", 70 | "typescript": "^2.1.4", 71 | "webpack": "^2.2.1", 72 | "webpack-fail-plugin": "^1.0.4", 73 | "webpack-notifier": "^1.2.1" 74 | }, 75 | "dependencies": { 76 | "babel-polyfill": "^6.0.0", 77 | "flux": "^2.0.3", 78 | "fbemitter": "^2.0.2", 79 | "react": "^15.4.1", 80 | "react-addons-test-utils": "^15.4.1", 81 | "react-dom": "^15.4.1" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/actions/GreetingActions.ts: -------------------------------------------------------------------------------- 1 | import {TypedEvent, AppDispatcher} from '../dispatcher/AppDispatcher'; 2 | 3 | export class AddGreetingEvent extends TypedEvent {} 4 | export class NewGreetingChanged extends TypedEvent {} 5 | export class RemoveGreeting extends TypedEvent {} 6 | 7 | export function addGreeting(newGreeting: string) { 8 | AppDispatcher.dispatch(new AddGreetingEvent(newGreeting)); 9 | } 10 | 11 | export function newGreetingChanged(newGreeting: string) { 12 | AppDispatcher.dispatch(new NewGreetingChanged(newGreeting)); 13 | } 14 | 15 | export function removeGreeting(greetingToRemove: string) { 16 | AppDispatcher.dispatch(new RemoveGreeting(greetingToRemove)); 17 | } 18 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import FBEmitter from "fbemitter"; 3 | 4 | import GreetingStore from '../stores/GreetingStore'; 5 | import GreetingState from '../types/GreetingState'; 6 | import WhoToGreet from './WhoToGreet'; 7 | import Greeting from './Greeting'; 8 | 9 | class App extends React.Component<{}, GreetingState> { 10 | eventSubscription: FBEmitter.EventSubscription; 11 | constructor(props: {}) { 12 | super(props); 13 | this.state = this.getStateFromStores(); 14 | } 15 | private onChange = () => { 16 | this.setState(this.getStateFromStores()); 17 | } 18 | 19 | public componentWillMount() { 20 | this.eventSubscription = GreetingStore.addChangeListener(this.onChange); 21 | } 22 | 23 | public componentWillUnmount() { 24 | this.eventSubscription.remove(); 25 | } 26 | 27 | render() { 28 | const { greetings, newGreeting } = this.state; 29 | return ( 30 |
31 |

Hello People!

32 | 33 | 34 | 35 | { greetings.map((g, index) => ) } 36 |
37 | ); 38 | } 39 | 40 | private getStateFromStores() { 41 | return GreetingStore.getState(); 42 | } 43 | } 44 | 45 | export default App; 46 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/components/Greeting.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import * as GreetingActions from '../actions/GreetingActions'; 4 | 5 | interface Props { 6 | key: number; 7 | targetOfGreeting: string; 8 | } 9 | 10 | class Greeting extends React.Component { 11 | constructor(props: Props) { 12 | super(props); 13 | } 14 | 15 | static propTypes: React.ValidationMap = { 16 | targetOfGreeting: React.PropTypes.string.isRequired 17 | } 18 | 19 | render() { 20 | return ( 21 |

22 | Hello { this.props.targetOfGreeting }! 23 | 24 | 28 |

29 | ); 30 | } 31 | 32 | _onClick = (_event: React.MouseEvent) => { 33 | GreetingActions.removeGreeting(this.props.targetOfGreeting); 34 | } 35 | } 36 | 37 | export default Greeting; 38 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/components/WhoToGreet.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import * as GreetingActions from '../actions/GreetingActions'; 4 | 5 | interface Props { 6 | newGreeting: string; 7 | } 8 | 9 | class WhoToGreet extends React.Component { 10 | constructor(props: Props) { 11 | super(props); 12 | } 13 | 14 | static propTypes: React.ValidationMap = { 15 | newGreeting: React.PropTypes.string.isRequired 16 | } 17 | 18 | render() { 19 | return ( 20 |
21 |
22 | 25 | 30 |
31 |
32 | ); 33 | } 34 | 35 | get _preventSubmission() { 36 | return !this.props.newGreeting; 37 | } 38 | 39 | _handleNewGreetingChange = (event: React.FormEvent) => { 40 | const newGreeting = (event.target as HTMLInputElement).value; 41 | GreetingActions.newGreetingChanged(newGreeting); 42 | } 43 | 44 | _onSubmit = (event: React.FormEvent) => { 45 | event.preventDefault(); 46 | 47 | if (!this._preventSubmission) { 48 | GreetingActions.addGreeting(this.props.newGreeting); 49 | } 50 | } 51 | } 52 | 53 | export default WhoToGreet; 54 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/dispatcher/AppDispatcher.ts: -------------------------------------------------------------------------------- 1 | import { Dispatcher } from 'flux'; 2 | 3 | export class TypedEvent

{ 4 | constructor(public payload: P) {} 5 | } 6 | 7 | export type Event = TypedEvent; 8 | 9 | const dispatcherInstance: Dispatcher = new Dispatcher(); 10 | 11 | export { dispatcherInstance as AppDispatcher }; 12 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | TypeScript, Babel, React, Flux, and Karma 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/main.tsx: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | import App from './components/App'; 6 | 7 | ReactDOM.render(, document.getElementById('content')); 8 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/stores/FluxStore.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'fbemitter'; 2 | import { Event } from '../dispatcher/AppDispatcher'; 3 | import * as Flux from "flux"; 4 | 5 | const CHANGE_EVENT = 'change'; 6 | 7 | class FluxStore { 8 | private changed: boolean; 9 | private emitter: EventEmitter; 10 | private dispatchToken: string; 11 | private dispatcher: Flux.Dispatcher; 12 | private cleanStateFn: () => TState; 13 | protected state: TState; 14 | 15 | constructor(dispatcher: Flux.Dispatcher, public onDispatch: (action: Event) => void, cleanStateFn: () => TState) { 16 | this.emitter = new EventEmitter(); 17 | this.changed = false; 18 | this.dispatcher = dispatcher; 19 | this.dispatchToken = dispatcher.register(payload => { 20 | this.invokeOnDispatch(payload); 21 | }); 22 | 23 | this.cleanStateFn = cleanStateFn; 24 | this.state = this.cleanStateFn(); 25 | } 26 | 27 | /** 28 | * Is idempotent per dispatched event 29 | */ 30 | emitChange() { 31 | this.changed = true; 32 | } 33 | 34 | hasChanged() { return this.changed; } 35 | 36 | addChangeListener(callback: () => void) { 37 | return this.emitter.addListener(CHANGE_EVENT, callback); 38 | } 39 | 40 | public cleanState() { 41 | this.changed = false; 42 | this.state = this.cleanStateFn(); 43 | } 44 | 45 | private invokeOnDispatch(payload: Event) { 46 | this.changed = false; 47 | this.onDispatch(payload); 48 | if (this.changed) { 49 | this.emitter.emit(CHANGE_EVENT); 50 | } 51 | } 52 | } 53 | 54 | export default FluxStore; 55 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/stores/GreetingStore.ts: -------------------------------------------------------------------------------- 1 | import FluxStore from './FluxStore'; 2 | import {Event, AppDispatcher} from '../dispatcher/AppDispatcher'; 3 | import GreetingState from '../types/GreetingState'; 4 | import { AddGreetingEvent, RemoveGreeting, NewGreetingChanged } from '../actions/GreetingActions'; 5 | 6 | class GreeterStore extends FluxStore { 7 | constructor(dispatcher: typeof AppDispatcher) { 8 | const onDispatch = (action: Event) => { 9 | if (action instanceof AddGreetingEvent) { 10 | const {payload} = action; 11 | this.state.newGreeting = ''; 12 | this.state.greetings = this.state.greetings.concat(payload); 13 | this.emitChange(); 14 | } 15 | else if (action instanceof RemoveGreeting) { 16 | const {payload} = action; 17 | this.state.greetings = this.state.greetings.filter(g => g !== payload); 18 | this.emitChange(); 19 | } 20 | else if (action instanceof NewGreetingChanged) { 21 | const {payload} = action; 22 | this.state.newGreeting = payload; 23 | this.emitChange(); 24 | } 25 | } 26 | super(dispatcher, onDispatch, () => ({ 27 | greetings: [], 28 | newGreeting: '' 29 | })); 30 | } 31 | 32 | getState() { 33 | return this.state 34 | } 35 | } 36 | 37 | const greeterStoreInstance = new GreeterStore(AppDispatcher); 38 | export default greeterStoreInstance; 39 | -------------------------------------------------------------------------------- /react-flux-babel-karma/src/types/GreetingState.ts: -------------------------------------------------------------------------------- 1 | interface GreetingState { 2 | greetings: string[]; 3 | newGreeting: string; 4 | } 5 | 6 | export default GreetingState; 7 | -------------------------------------------------------------------------------- /react-flux-babel-karma/test/components/App.tests.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TestUtils from 'react-addons-test-utils'; 3 | 4 | import App from '../../src/components/App'; 5 | import WhoToGreet from '../../src/components/WhoToGreet'; 6 | import Greeting from '../../src/components/Greeting'; 7 | import GreetingStore from '../../src/stores/GreetingStore'; 8 | 9 | describe('App', () => { 10 | it('renders expected HTML', () => { 11 | const app = render({ greetings: ['James'], newGreeting: 'Benjamin' }); 12 | expect(app).toEqual( 13 |
14 |

Hello People!

15 | 16 | 17 | 18 | { [ 19 | 20 | ] } 21 |
22 | ); 23 | }); 24 | 25 | function render(state: any) { 26 | const shallowRenderer = TestUtils.createRenderer(); 27 | spyOn(GreetingStore, 'getState').and.returnValue(state); 28 | 29 | shallowRenderer.render(); 30 | return shallowRenderer.getRenderOutput(); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /react-flux-babel-karma/test/components/Greeting.tests.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TestUtils from 'react-addons-test-utils'; 3 | 4 | import Greeting from '../../src/components/Greeting'; 5 | import * as GreetingActions from '../../src/actions/GreetingActions'; 6 | 7 | describe('Greeting', () => { 8 | let handleSelectionChangeSpy: jasmine.Spy; 9 | beforeEach(() => { 10 | handleSelectionChangeSpy = jasmine.createSpy('handleSelectionChange'); 11 | }); 12 | 13 | it('given a targetOfGreeting of \'James\' it renders a p containing a greeting and a remove button', () => { 14 | const targetOfGreeting = 'James'; 15 | 16 | const p = render({ targetOfGreeting }); 17 | expect(p.type).toBe('p'); 18 | expect(p.props.children[0]).toBe('Hello '); 19 | expect(p.props.children[1]).toBe('James'); 20 | expect(p.props.children[2]).toBe('!'); 21 | 22 | const [ , , , button ] = p.props.children; 23 | 24 | expect(button.type).toBe('button'); 25 | expect(button.props.className).toBe('btn btn-default btn-danger'); 26 | expect(button.props.children).toBe('Remove'); 27 | }); 28 | 29 | it('button onClick triggers an removeGreeting action', () => { 30 | const targetOfGreeting = 'Benjamin'; 31 | const p = render({ targetOfGreeting }); 32 | const [ , , , button ] = p.props.children; 33 | spyOn(GreetingActions, 'removeGreeting'); 34 | 35 | button.props.onClick(); 36 | 37 | expect(GreetingActions.removeGreeting).toHaveBeenCalledWith(targetOfGreeting); 38 | }); 39 | 40 | function render({ targetOfGreeting }: { targetOfGreeting: string; }) { 41 | const shallowRenderer = TestUtils.createRenderer(); 42 | shallowRenderer.render(); 43 | return shallowRenderer.getRenderOutput(); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /react-flux-babel-karma/test/components/WhoToGreet.tests.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TestUtils from 'react-addons-test-utils'; 3 | 4 | import WhoToGreet from '../../src/components/WhoToGreet'; 5 | import * as GreetingActions from '../../src/actions/GreetingActions'; 6 | 7 | describe('WhoToGreet', () => { 8 | let handleSelectionChangeSpy: jasmine.Spy; 9 | beforeEach(() => { 10 | handleSelectionChangeSpy = jasmine.createSpy('handleSelectionChange'); 11 | }); 12 | 13 | it('given a newGreeting then it renders a form containing an input containing that text and an add button', () => { 14 | const newGreeting = 'James'; 15 | 16 | const form = render({ newGreeting }); 17 | expect(form.type).toBe('form'); 18 | expect(form.props.role).toBe('form'); 19 | 20 | const formGroup = form.props.children; 21 | expect(formGroup.type).toBe('div'); 22 | expect(formGroup.props.className).toBe('form-group'); 23 | 24 | const [ input, button ] = formGroup.props.children; 25 | 26 | expect(input.type).toBe('input'); 27 | expect(input.props.type).toBe('text'); 28 | expect(input.props.className).toBe('form-control'); 29 | expect(input.props.placeholder).toBe('Who would you like to greet?'); 30 | expect(input.props.value).toBe(newGreeting); 31 | 32 | expect(button.type).toBe('button'); 33 | expect(button.props.type).toBe('submit'); 34 | expect(button.props.className).toBe('btn btn-default btn-primary'); 35 | expect(button.props.disabled).toBe(false); 36 | expect(button.props.children).toBe('Add greeting'); 37 | }); 38 | 39 | it('input onChange triggers a newGreetingChanged action', () => { 40 | const newGreeting = 'Benjamin'; 41 | const form = render({ newGreeting }); 42 | const formGroup = form.props.children; 43 | const [ input ] = formGroup.props.children; 44 | spyOn(GreetingActions, 'newGreetingChanged'); 45 | 46 | input.props.onChange({ target: { value: newGreeting }}); 47 | 48 | expect(GreetingActions.newGreetingChanged).toHaveBeenCalledWith(newGreeting); 49 | }); 50 | 51 | it('button onClick triggers an addGreeting action', () => { 52 | const newGreeting = 'Benjamin'; 53 | const form = render({ newGreeting }); 54 | const formGroup = form.props.children; 55 | const [ , button ] = formGroup.props.children; 56 | spyOn(GreetingActions, 'addGreeting'); 57 | 58 | button.props.onClick({ preventDefault: () => {} }); 59 | 60 | expect(GreetingActions.addGreeting).toHaveBeenCalledWith(newGreeting); 61 | }); 62 | 63 | function render({ newGreeting }: { newGreeting: string }) { 64 | const shallowRenderer = TestUtils.createRenderer(); 65 | shallowRenderer.render(); 66 | return shallowRenderer.getRenderOutput(); 67 | } 68 | }); 69 | -------------------------------------------------------------------------------- /react-flux-babel-karma/test/main.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import 'babel-polyfill'; 3 | 4 | const testsContext = require.context('./', true, /\.tests\.ts(x?)$/); 5 | testsContext.keys().forEach(testsContext); -------------------------------------------------------------------------------- /react-flux-babel-karma/test/stores/GreetingStore.tests.ts: -------------------------------------------------------------------------------- 1 | import GreetingStore from '../../src/stores/GreetingStore'; 2 | import { AddGreetingEvent, RemoveGreeting, NewGreetingChanged } from '../../src/actions/GreetingActions'; 3 | 4 | const registeredCallback = GreetingStore.onDispatch.bind(GreetingStore); 5 | 6 | describe('GreetingStore', () => { 7 | beforeEach(() => { 8 | GreetingStore.cleanState(); 9 | }); 10 | 11 | it('given no actions, newGreeting should be an empty string and greetings should be an empty array', () => { 12 | const { greetings, newGreeting } = GreetingStore.getState(); 13 | 14 | expect(greetings).toEqual([]); 15 | expect(newGreeting).toBe(''); 16 | }); 17 | 18 | it('given an ADD_GREETING action with a newGreeting of \'Benjamin\', the newGreeting should be an empty string and greetings should contain \'Benjamin\'', () => { 19 | [new AddGreetingEvent('Benjamin')].forEach(registeredCallback); 20 | 21 | const { greetings, newGreeting } = GreetingStore.getState(); 22 | 23 | expect(greetings.find(g => g === 'Benjamin')).toBeTruthy(); 24 | expect(newGreeting).toBe(''); 25 | }); 26 | 27 | it('given an REMOVE_GREETING action with a greetingToRemove of \'Benjamin\', the state greetings should be an empty array', () => { 28 | [new AddGreetingEvent('Benjamin'), new RemoveGreeting('Benjamin')].forEach(registeredCallback); 29 | 30 | const { greetings } = GreetingStore.getState(); 31 | 32 | expect(greetings.length).toBe(0); 33 | expect(greetings.find(g => g === 'Benjamin')).toBeFalsy(); 34 | }); 35 | 36 | it('given a NEW_GREETING_CHANGED action with a newGreeting of \'Benjamin\', the state newGreeting should be \'Benjamin\'', () => { 37 | [new NewGreetingChanged('Benjamin')].forEach(registeredCallback); 38 | 39 | const { newGreeting } = GreetingStore.getState(); 40 | 41 | expect(newGreeting).toEqual('Benjamin'); 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /react-flux-babel-karma/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "lib": [ 6 | "dom", 7 | "es2015", 8 | "es2016" 9 | ], 10 | "jsx": "preserve", 11 | "target": "es2016", 12 | "module": "es2015", 13 | "moduleResolution": "node", 14 | "noImplicitAny": true, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "removeComments": false, 18 | "preserveConstEnums": true, 19 | "sourceMap": true, 20 | "skipLibCheck": true 21 | } 22 | } -------------------------------------------------------------------------------- /react-flux-babel-karma/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var, strict, prefer-arrow-callback */ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | 6 | 7 | var babelOptions = { 8 | "presets": [ 9 | "react", 10 | [ 11 | "es2015", 12 | { 13 | "modules": false 14 | } 15 | ], 16 | "es2016" 17 | ] 18 | }; 19 | 20 | module.exports = { 21 | cache: true, 22 | entry: { 23 | main: './src/main.tsx', 24 | vendor: [ 25 | 'babel-polyfill', 26 | 'events', 27 | 'fbemitter', 28 | 'flux', 29 | 'react', 30 | 'react-dom' 31 | ] 32 | }, 33 | output: { 34 | path: path.resolve(__dirname, './dist/scripts'), 35 | filename: '[name].js', 36 | chunkFilename: '[chunkhash].js' 37 | }, 38 | module: { 39 | rules: [{ 40 | test: /\.ts(x?)$/, 41 | exclude: /node_modules/, 42 | use: [ 43 | { 44 | loader: 'babel-loader', 45 | options: babelOptions 46 | }, 47 | { 48 | loader: 'ts-loader' 49 | } 50 | ] 51 | }, { 52 | test: /\.js$/, 53 | exclude: /node_modules/, 54 | use: [ 55 | { 56 | loader: 'babel-loader', 57 | options: babelOptions 58 | } 59 | ] 60 | }] 61 | }, 62 | plugins: [ 63 | ], 64 | resolve: { 65 | extensions: ['.ts', '.tsx', '.js'] 66 | }, 67 | }; -------------------------------------------------------------------------------- /simple/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Simple 2 | 3 | ## Overview 4 | 5 | Simple use of classes and inheritance: 6 | - Classes: A base class and two subclasses 7 | - Super calls: Derived classes make super calls 8 | 9 | 10 | ## Running 11 | 12 | `tsc --sourcemap animals.ts` 13 | -------------------------------------------------------------------------------- /simple/animals.ts: -------------------------------------------------------------------------------- 1 | class Animal { 2 | constructor(public name) { } 3 | move(meters) { 4 | console.log(this.name + " moved " + meters + "m."); 5 | } 6 | } 7 | 8 | class Snake extends Animal { 9 | move() { 10 | console.log("Slithering..."); 11 | super.move(5); 12 | } 13 | } 14 | 15 | class Horse extends Animal { 16 | move() { 17 | console.log("Galloping..."); 18 | super.move(45); 19 | } 20 | } 21 | 22 | var sam = new Snake("Sammy the Python") 23 | var tom: Animal = new Horse("Tommy the Palomino") 24 | 25 | sam.move() 26 | tom.move(34) 27 | -------------------------------------------------------------------------------- /simple/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /systemjs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /systemjs/README.md: -------------------------------------------------------------------------------- 1 | **Fetch dependencies:** 2 | ``` 3 | npm install 4 | ``` 5 | 6 | **Run (using port 8080)** 7 | ``` 8 | npm start 9 | ``` 10 | 11 | **Run server on custom port** 12 | ``` 13 | node node_modules/http-server/bin/http-server -p 8080 14 | ``` 15 | 16 | '-p' sets the port to use, default port is 8080. If it is taken pick any port that is free. 17 | After server is started open 'localhost:8080' in a browser. -------------------------------------------------------------------------------- /systemjs/app.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-family: 'Segoe UI', sans-serif 4 | } 5 | 6 | span { 7 | font-style: italic 8 | } -------------------------------------------------------------------------------- /systemjs/app.ts: -------------------------------------------------------------------------------- 1 | import { Greeter } from 'greeter' 2 | 3 | export function main(el: HTMLElement): void { 4 | let greeter = new Greeter(el); 5 | greeter.start(); 6 | } -------------------------------------------------------------------------------- /systemjs/greeter.ts: -------------------------------------------------------------------------------- 1 | export class Greeter 2 | { 3 | element: HTMLElement; 4 | span: HTMLElement; 5 | timerToken: number; 6 | 7 | constructor (element: HTMLElement) 8 | { 9 | this.element = element; 10 | this.element.innerText += "The time is: "; 11 | this.span = document.createElement('span'); 12 | this.element.appendChild(this.span); 13 | this.span.innerText = new Date().toUTCString(); 14 | } 15 | 16 | start() 17 | { 18 | this.timerToken = setInterval(() => this.span.innerText = new Date().toUTCString(), 500); 19 | } 20 | 21 | stop() 22 | { 23 | clearTimeout(this.timerToken); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /systemjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SystemJS/TypeScript Sample 4 | 5 | 6 | 7 | 8 | 20 |

SystemJS/TypeScript Sample

21 |
22 | 23 | -------------------------------------------------------------------------------- /systemjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-systemjs", 3 | "version": "1.0.0", 4 | "description": "SystemJS/TypeScript demo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 8 | }, 9 | "dependencies": { 10 | "http-server": "0.9.0", 11 | "systemjs": "0.18.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^1.5.3" 15 | }, 16 | "scripts": { 17 | "start": "node node_modules/http-server/bin/http-server -o" 18 | } 19 | } -------------------------------------------------------------------------------- /systemjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "system", 4 | "sourceMap": true 5 | } 6 | } -------------------------------------------------------------------------------- /todomvc/.gitignore: -------------------------------------------------------------------------------- 1 | js/*.js 2 | js/*.js.map 3 | -------------------------------------------------------------------------------- /todomvc/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Todo MVC 2 | 3 | ## Overview 4 | 5 | This sample shows an implementation of the Backbone.js TODO sample derived from 6 | https://github.com/documentcloud/backbone/tree/master/examples/todos. The following 7 | TypeScript integration points are highlighted: 8 | - Backbone.js: Using TypeScript classes to create Backbone models and views 9 | - jQuery: Using jQuery for all DOM manipulation 10 | 11 | 12 | ## Running 13 | ``` 14 | npm install 15 | npm start 16 | ``` 17 | 18 | ## Caveats 19 | 20 | ``` 21 | This sample uses local storage and will not run properly on Internet Explorer if run 22 | from the local filesystem. Instead, host the sample from a web server (eg. IIS). 23 | 24 | 25 | Microsoft grants you the right to use these script files under the Apache 2.0 license. 26 | Microsoft reserves all other rights to the files not expressly granted by Microsoft, 27 | whether by implication, estoppel or otherwise. The copyright notices and MIT licenses 28 | below are for informational purposes only. 29 | 30 | Portions Copyright © Microsoft Corporation 31 | Apache 2.0 License 32 | 33 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 34 | file except in compliance with the License. You may obtain a copy of the License at 35 | http://www.apache.org/licenses/LICENSE-2.0 36 | 37 | Unless required by applicable law or agreed to in writing, software distributed under 38 | the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 39 | ANY KIND, either express or implied. 40 | 41 | See the License for the specific language governing permissions and limitations 42 | under the License. 43 | ``` 44 | 45 | 46 | ``` 47 | Provided for Informational Purposes Only 48 | MIT License 49 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 50 | software and associated documentation files (the "Software"), to deal in the Software 51 | without restriction, including without limitation the rights to use, copy, modify, merge, 52 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit 53 | persons to whom the Software is furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all copies 56 | or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 59 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 60 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 61 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 62 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 63 | DEALINGS IN THE SOFTWARE. 64 | ``` 65 | -------------------------------------------------------------------------------- /todomvc/css/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/todomvc/css/destroy.png -------------------------------------------------------------------------------- /todomvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-todomvc", 3 | "version": "1.0.0", 4 | "description": "TodoMVC/TypeScript demo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 8 | }, 9 | "dependencies": { 10 | "http-server": "^0.11.1" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^3.0.0" 14 | }, 15 | "scripts": { 16 | "start": "tsc && http-server -o" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /todomvc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true 4 | } 5 | } -------------------------------------------------------------------------------- /umd/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | shared/timeReporter.js 3 | browser/app.js 4 | node/app.js -------------------------------------------------------------------------------- /umd/README.md: -------------------------------------------------------------------------------- 1 | **Fetch dependencies:** 2 | ``` 3 | npm install 4 | ``` 5 | 6 | **Compile TypeScript source code** 7 | 8 | ``` 9 | node node_modules/typescript/bin/tsc.js 10 | ``` 11 | 12 | **Start browser version of the sample using http-server on custom port (code should be compiled prior to this step)** 13 | ``` 14 | node node_modules/http-server/bin/http-server -p 8080 -o 15 | ``` 16 | '-p' sets the port to use, default port is 8080. If it is taken pick any port that is free. 17 | After server is started open 'localhost:8080' in a browser. 18 | 19 | 20 | **Run example using Node (code should be compiled prior to this step)** 21 | 22 | ``` 23 | node node/app.js 24 | ``` 25 | 26 | Shortcuts for doing compile\run steps from above: 27 | 28 | *Browser* 29 | ``` 30 | npm run browser 31 | ``` 32 | 33 | *Node* 34 | ``` 35 | npm run node 36 | ``` -------------------------------------------------------------------------------- /umd/browser/app.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-family: 'Segoe UI', sans-serif 4 | } 5 | 6 | span { 7 | font-style: italic 8 | } -------------------------------------------------------------------------------- /umd/browser/app.ts: -------------------------------------------------------------------------------- 1 | import { TimeReporter } from '../shared/timeReporter' 2 | 3 | let element = document.getElementById("content"); 4 | element.innerText += "The time is: "; 5 | let span = document.createElement("span"); 6 | element.appendChild(span); 7 | 8 | function printer(s: string): void { 9 | span.innerText = s; 10 | } 11 | 12 | let timeReporter = new TimeReporter(printer); 13 | timeReporter.start(); 14 | -------------------------------------------------------------------------------- /umd/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | TypeScript HTML App 7 | 8 | 9 | 10 | 11 |

UMD/TypeScript sample

12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /umd/node/app.ts: -------------------------------------------------------------------------------- 1 | import { TimeReporter } from '../shared/timeReporter' 2 | import { EOL } from 'os'; 3 | function printer(s): void { 4 | console.log("The time is: " + s + EOL); 5 | } 6 | 7 | let timeReporter = new TimeReporter(printer); 8 | timeReporter.start(); -------------------------------------------------------------------------------- /umd/node/os.d.ts: -------------------------------------------------------------------------------- 1 | declare module "os" { 2 | export var EOL: string; 3 | } -------------------------------------------------------------------------------- /umd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-umd", 3 | "version": "1.0.0", 4 | "description": "UMD/TypeScript demo", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Microsoft/TypeScriptSamples.git" 8 | }, 9 | "dependencies": { 10 | "http-server": "0.8.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^1.5.3" 14 | }, 15 | "scripts": { 16 | "browser": "node node_modules/typescript/bin/tsc.js && node node_modules/http-server/bin/http-server -o", 17 | "node": "node node_modules/typescript/bin/tsc.js && node node/app.js" 18 | } 19 | } -------------------------------------------------------------------------------- /umd/shared/timeReporter.ts: -------------------------------------------------------------------------------- 1 | export type Printer = (s: string) => void; 2 | 3 | export class TimeReporter 4 | { 5 | printer: Printer 6 | timerToken: number; 7 | 8 | constructor (printer: Printer) 9 | { 10 | this.printer = printer; 11 | this.printer(new Date().toUTCString()); 12 | } 13 | 14 | start() 15 | { 16 | this.timerToken = setInterval(() => this.printer(new Date().toUTCString()), 500); 17 | } 18 | 19 | stop() 20 | { 21 | clearTimeout(this.timerToken); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /umd/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "UMD", 4 | "target": "es5" 5 | }, 6 | "files": [ 7 | "shared/timeReporter.ts", 8 | "browser/app.ts", 9 | "node/os.d.ts", 10 | "node/app.ts" 11 | ] 12 | } -------------------------------------------------------------------------------- /warship/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript Sample: Warship Combat 2 | 3 | ## Overview 4 | 5 | The classic grid-based warship combat game 6 | - Use of the jQuery and jQuery UI wrappers 7 | - Use of object-oriented techniques 8 | 9 | 10 | ## Running 11 | ``` 12 | tsc --sourcemap --target ES5 warship.ts 13 | start default.html 14 | ``` 15 | -------------------------------------------------------------------------------- /warship/default.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Warship Combat 11 | 12 | 13 | 17 |
18 |
19 |
20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /warship/img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/warship/img/bg.jpg -------------------------------------------------------------------------------- /warship/img/bg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TypeScriptSamples/b675f11d4ef8b7f94aa563586332415407bfe168/warship/img/bg2.jpg -------------------------------------------------------------------------------- /warship/jqueryui.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Partial typing for the jQueryUI library, version 1.8.x 4 | 5 | interface DraggableEventUIParam { 6 | helper: JQuery; 7 | position: { top: number; left: number;}; 8 | offset: { top: number; left: number;}; 9 | } 10 | 11 | interface DraggableEvent { 12 | (event: Event, ui: DraggableEventUIParam): void; 13 | } 14 | 15 | interface Draggable { 16 | // Options 17 | disabled?: boolean; 18 | addClasses?: boolean; 19 | appendTo?: any; 20 | axis?: string; 21 | cancel?: string; 22 | connectToSortable?: string; 23 | containment?: any; 24 | cursor?: string; 25 | cursorAt?: any; 26 | delay?: number; 27 | distance?: number; 28 | grid?: number[]; 29 | handle?: any; 30 | helper?: any; 31 | iframeFix?: any; 32 | opacity?: number; 33 | refreshPositions?: boolean; 34 | revert?: any; 35 | revertDuration?: number; 36 | scope?: string; 37 | scroll?: boolean; 38 | scrollSensitivity?: number; 39 | scrollSpeed?: number; 40 | snap?: any; 41 | snapMode?: string; 42 | snapTolerance?: number; 43 | stack?: string; 44 | zIndex?: number; 45 | // Events 46 | create?: DraggableEvent; 47 | start?: DraggableEvent; 48 | drag?: DraggableEvent; 49 | stop?: DraggableEvent; 50 | } 51 | 52 | interface DroppableEventUIParam { 53 | draggable: JQuery; 54 | helper: JQuery; 55 | position: { top: number; left: number;}; 56 | offset: { top: number; left: number;}; 57 | } 58 | 59 | interface DroppableEvent { 60 | (event: Event, ui: DroppableEventUIParam): void; 61 | } 62 | 63 | interface Droppable { 64 | // Options 65 | disabled?: boolean; 66 | accept?: any; 67 | activeClass?: string; 68 | greedy?: boolean; 69 | hoverClass?: string; 70 | scope?: string; 71 | tolerance?: string; 72 | // Events 73 | create?: DroppableEvent; 74 | activate?: DroppableEvent; 75 | deactivate?: DroppableEvent; 76 | over?: DroppableEvent; 77 | out?: DroppableEvent; 78 | drop?: DroppableEvent; 79 | } 80 | 81 | interface JQuery { 82 | draggable(options: Draggable): JQuery; 83 | draggable(optionLiteral: string, options: Draggable): JQuery; 84 | draggable(optionLiteral: string, optionName: string, optionValue: any): JQuery; 85 | draggable(optionLiteral: string, optionName: string): any; 86 | // draggable(methodName: string): any; 87 | droppable(options: Droppable): JQuery; 88 | droppable(optionLiteral: string, options: Draggable): JQuery; 89 | droppable(optionLiteral: string, optionName: string, optionValue: any): JQuery; 90 | droppable(optionLiteral: string, optionName: string): any; 91 | droppable(methodName: string): any; 92 | } 93 | -------------------------------------------------------------------------------- /warship/styles.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | width: 100%; 4 | height: 100%; 5 | -ms-content-zooming: none; 6 | margin: 0px; 7 | border: 0px; 8 | padding: 0px; 9 | } 10 | body { 11 | font-family: Verdana; 12 | width: 100%; 13 | height: 100%; 14 | /*background-color: #b5caae;*/ 15 | background: url('img/bg2.jpg'); 16 | margin: 0px; 17 | border: 0px; 18 | padding: 0px; 19 | min-height: 480px; 20 | min-width: 640px; 21 | } 22 | #header { 23 | width: 100%; 24 | height: 25%; 25 | } 26 | #boards { 27 | width: 100%; 28 | height: 75%; 29 | } 30 | .quadrant 31 | { 32 | display: inline-block; 33 | box-sizing: border-box; 34 | -moz-box-sizing: border-box; 35 | width: 40%; 36 | margin: 2%; 37 | vertical-align: top; 38 | } 39 | #banner { 40 | font-size: 40pt; 41 | font-weight: 800; 42 | font-style: italic; 43 | color: white; 44 | text-shadow: -1px 0 black, 0 2px black, 1px 0 black, 0 -1px black; 45 | height: 100px; 46 | } 47 | #status 48 | { 49 | width: 80%; 50 | border: 1px dotted gray; 51 | padding: 1%; 52 | background-color: #CCCCCC; 53 | height: 80%; 54 | } 55 | .board { 56 | background-color: #111111; 57 | border: 2px groove black; 58 | height: 80%; 59 | padding: 0%; 60 | position: relative; 61 | } 62 | .cell { 63 | box-sizing: border-box; 64 | -moz-box-sizing: border-box; 65 | float: left; 66 | height: 10%; 67 | width: 10%; 68 | border: 1px dotted #A0A0FF; 69 | margin: 0px; 70 | padding: 0px; 71 | position: relative; 72 | } 73 | 74 | .notBombed { 75 | opacity: 0.2; 76 | background: url('img/bg.jpg') repeat; 77 | /*background-color: black;*/ 78 | z-index: 0; 79 | } 80 | 81 | .cellHit { 82 | opacity: 0.5; 83 | background-color: #C00000; 84 | z-index: 2; 85 | } 86 | 87 | .cellMiss{ 88 | opacity: 0.5; 89 | background-color: #008000; 90 | z-index: 2; 91 | } 92 | 93 | .ship { 94 | position: absolute; 95 | box-sizing: border-box; 96 | -moz-box-sizing: border-box; 97 | margin: 0%; 98 | padding: 0%; 99 | width: 10%; 100 | height: 10%; 101 | border-radius: 20%; 102 | /*background-color: #FFFF80;*/ 103 | background: #666666; 104 | border: 2px solid black; 105 | z-index: 1; 106 | -ms-touch-action: none; 107 | } 108 | 109 | .dropTarget { 110 | background-color: white; 111 | } 112 | -------------------------------------------------------------------------------- /warship/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "sourceMap": true 5 | } 6 | } --------------------------------------------------------------------------------