How to use TypeScript in Sublime Text!

You want to code in TypeScript. You want to code with Sublime Text. Today, that is really easy to do, thanks to Package Control and Microsoft, which now provides a first-class plugin for Sublime Text to enable and light up TypeScript.


Step 1: Install Package Control

The installation instructions can be found here, but in summary, press Ctrl+` and then paste the following code (for Sublime Text 2; for 3, see their website) into the text box and press Enter:

import urllib2,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')

image

It takes a few seconds, during which nothing happens, and then the message window will display: “Please restart Sublime Text to finish installation” — so do that.


Step 2: Add the TypeScript package

Press Ctrl+Shift+P to bring up the command palette, type Package Control: Install Package, and press Enter.

You can use the arrow keys to navigate the list more efficiently and select the correct item instead of typing everything.

image

In the next command palette window, type TypeScript and hit Enter.

image

In the status bar, the plugin will start downloading and installing TypeScript:

image

Once that’s complete, you’ll have glorious TypeScript in Sublime!

image


Telkom is using a man-in-the-middle attack to change your websites

Part 2 is here, click that now (it will open in a new window) so you can continue when you’re done here.

The following is a screenshot I took of a webpage in Chrome. If you visit that same website, you’ll experience a different result because Telkom is using techniques similar to a man-in-the-middle attack to modify the website’s code and inject its own content.

Clipboard01

The key addition—visible in the lower right corner of the page—was inserted by Telkom without the website owner’s or Telkom ISP customer’s permission.

Image

While this seems harmless—even potentially useful—it’s deceptive. Even this seemingly minor change could cause major issues.

Breaking websites

Telkom cannot predict how this injection will affect every website on the web. While I’ll explain the technical details below, the core issue is that they’re injecting JavaScript into every page. This extra code could conflict with existing scripts, leading to unpredictable behavior and broken websites. Given the internet’s scale and complexity, it’s impossible to guarantee that no website will be disrupted.

Exposing security risks

The second major issue is the security vulnerability this creates. Telkom may argue their code is secure now—and it’s true for now—but security is never static.

They’re using an outdated version of jQuery (version 1.7.1), which has no reported vulnerabilities yet. But security flaws can emerge at any time. If a vulnerability is discovered in this library or in Telkom’s injected code, attackers could exploit it to launch attacks against users. Do you trust Telkom’s developers that much to have no security flaws?

A second risk: Telkom must host the servers and systems running this injection. If those servers are compromised—by hackers or even a disgruntled employee—they could be used for XSS attacks or key sniffing. As awareness grows, these servers will become prime targets. It’s only a matter of time before they’re breached.

Violating net neutrality and privacy

While ISPs should monitor traffic (with oversight), this practice makes it far too easy for Telkom to intercept and manipulate your data in ways you won’t even notice.

Telkom claims they handle this responsibly—but what prevents executives from using this to block unwanted content (e.g., MTN ads) or suppress websites critical of them (like those supporting the EFF or DA)? Without transparency or consent, do you trust them not to abuse this power? Their actions violate a core principle of the internet: net neutrality.

Performance impact

Lastly (though least concerning), Telkom forces users to download ~84.8 KB of extra JavaScript (see data here) and ~120 KB of extra images. This manipulation also slows down page rendering, increasing load times and bandwidth usage. They introduce unnecessary network hops, further degrading performance.


Technical details

Telkom only targets HTTP traffic—not HTTPS, which is encrypted. While HTTPS should be secure, it’s not impossible to bypass (as seen in the Superfish controversy). While unlikely, they could extend this to secure sites if motivated.

How it works

Telkom doesn’t alter the original HTML—they inject JavaScript after it loads. Here’s how:

  1. A website loads a JavaScript file (e.g., jQuery).
  2. Instead of fetching it directly, Telkom’s proxy intercepts the request.
  3. If the file is JavaScript, Telkom reroutes it to their server.
  4. Their server fetches the original file from the real website.
  5. Telkom appends their own code (including jQuery 2.0.1 and custom scripts).
  6. The modified file is sent back to your browser.

Normal flow (unmodified): Example1

  1. Browser requests a file.
  2. Request hits Telkom’s proxy (for caching/performance).
  3. Proxy fetches from the original server if needed.
  4. Unaltered file returns to the browser.

Modified flow (Telkom injection): Example2

  1. Browser requests JavaScript.
  2. Telkom’s proxy detects it’s JS and reroutes the request.
  3. Their server fetches the original file.
  4. Telkom appends their code.
  5. Modified file returns to the browser.

Evidence of injection: You can spot this by checking JavaScript file URLs—they redirect through Telkom’s servers, e.g.:

http://196.25.211.41/n/50fc073bb429a4eb303a6420235e9381.js?q=Pb4KQL0xYJ%2F53kOn%2FSnvQA%3D%3D%7C1435397545%7C02dfd5fbe207b80c1859ed08333cd16d&url=http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fjquery%2F1.7.1%2Fjquery.min.js
  • The q parameter likely prevents caching.
  • The url parameter shows the original file being modified.

Note: These URLs only work on Telkom’s network.

FAQ

Is this definitely Telkom’s doing?

Yes. I tested this on:

  • Windows 10 + Chrome (original screenshot)
  • Windows Phone + Edge (reproduced)
  • Microsoft Edge (confirmed on jQuery’s website)

Windows Phone/Edge jQuery on Edge

How are they injecting content without changing the HTML?

JavaScript can dynamically modify the page. Here’s the original HTML (source) vs. the rendered output:

Original vs. Rendered

Could this be an agreement with website owners?

No. This affects all HTTP sites, including:

  • StackOverflow (a CDN-hosted site where I compared their injected jQuery to the original): StackOverflow Injection Comparison

StackOverflow never approved this.

Examples of the injected code

Why don’t I see this?

Possible reasons:

  • You’re not on Telkom ADSL/ISP.
  • The site uses HTTPS (this only affects HTTP).
  • Telkom’s injection is inconsistent (I first noticed it a few days ago before it disappeared).
  • Some sites may not trigger their filters.

How can I protect myself?

  1. Opt out via Telkom’s tracker: https://secure.telkomsa.net/titracker (unverified effectiveness).
  2. Use HTTPS Everywhere: Install the EFF’s extension to force encrypted connections.
  3. Switch ISPs if you don’t trust Telkom with your data.

Opting out isn’t enough.

  • The system remains in place—it just checks your status.
  • Even after opting out, you may still hit Telkom’s servers, adding latency.
  • The only real solution is for Telkom to stop this entirely.

Updates

  • 10 July 2015, 12:05h: Clarified that many ISPs do use proxies (for performance), but not for content manipulation.
  • 29 June 2015, 15:00h: Updated data—total injection size is ~200 KB (84.8 KB JS + 120 KB images).
  • 29 June 2015, 15:30h: Added net neutrality violation and HTTPS Everywhere recommendation.
  • 20 June 2015, 18:25h: Details on opt-out limitations and performance trade-offs.

Telkom: Why do dumb?

I try not to rant on my blog and mostly I succeed. Today, though, I wanted to complain to Telkom about them inserting content into web pages on Twitter, so I head to their website to find their Twitter account. I don’t find one—I find three different Twitter accounts, and a situation so bad I cannot keep quiet!

Clipboard02

It isn’t ideal to have three, and I can understand that different components might need their own accounts. In fact, they look like a business account (1), their cellphone brand (2), and a general one (3). The part that baffles me is what happens when I checked them.

The business account

This account has been taken over by spammers. :facepalm:

Clipboard01

The mobile account

That account is suspended. :facepalm:

Clipboard03

In fact, only the general account works! Mistakes happen—people mess up, accounts get suspended or lost—but it isn’t ideal or professional. The damage could have been mitigated by removing those links from your website. The fact that Telkom can’t or won’t speaks volumes about their lack of care. There is no acceptable reason for those bad links to remain, and whoever runs their website should hang up their HTML spurs and find a new career.

Let them know

Want to help let them know this isn’t acceptable? Here’s the form for the webmaster, and here’s a handy link to tweet to them quickly.


My "cut" //Build keynote demo - A bunch of Visual Studio 2015 features

johannesburg_l Yesterday in Johannesburg, we had an amazing //Build Tour event! We had top international speakers—like Pete Brown—join us and wow the audience with Windows 10, IoT, Edge, and more! Unfortunately, the international speakers faced flight issues, and we had a one-hour-and-a-half gap before we could kick off. So, a bunch of local Microsoft people got together to provide a bit of local flavor in a pre-keynote event.

I was very excited to share my talk about Visual Studio 2015, but it got cut at the last minute as the presenters arrived. Part of my prep was to create a video of my talk, and you can watch this content now:

You can get the demo code on GitHub.


How to do your daily stand ups with a distributed team

With an agile team, you should meet daily for a quick meeting. Normally, that takes the form of each person answering a three-question status update (What did I achieve? What will I achieve? What is blocking me?). For a team working together, it means these steps:

  1. Team arrives at the shared team board
  2. Team goes around and gives a status update
  3. Team goes back to work

Just because your team is distributed doesn’t mean this shouldn’t happen—it just means you’ll find a few extra steps:

  1. Team members who work together go to a booked meeting room (you need a meeting room so those remote can hear over the normal work environment noise)
  2. You’re surprised to find someone in the room
  3. Explain that you booked the room
  4. Wait for them to leave the room
  5. Connect the projector
  6. Realize you left your microphone in your laptop bag, return to your desk, get it, and return to the meeting room
  7. Plug it in
  8. Open the digital scrum board
  9. Start the meeting software and join the meeting
  10. See one remote team member is already there—apologize for being late
  11. Wait for a response
  12. Wait for a response again
  13. Realize they can’t hear you
  14. Both the remote team member and you try to figure out what’s not working
  15. Figure out that there’s a mute hardware button that—today (and today only)—is turned itself on
  16. Try again—success! They can hear you now
  17. Wait for the product owner to join
  18. Give up waiting and kick off the meeting (everyone is seated now because no one’s legs last that long)
  19. Go around the team and give status updates
  20. The product owner joins during the second-to-last team member’s status update
  21. The product owner starts sharing a bunch of bugs and task updates that someone else is now capturing live
  22. Finish the status updates
  23. The team decides to use this time—while they’re all here—to discuss technical info around the new stuff from the product owner
  24. The product owner is late for the meeting and has to disconnect
  25. Someone walks into the meeting room and asks if this is the meeting for organizing the year-end party
  26. Silence
  27. No one answers
  28. Silence
  29. The Scrum master answers
  30. The team discusses technical issues. Half of them are marked as needing more info and will be discussed with the product owner in tomorrow’s meeting
  31. The call ends
  32. The team goes to get coffee (they need it) and says how glad they are using agile—because they save so much time with fewer meetings
  33. Two hours later
  34. Another team member joins the call alone because the time zone they’re in changed to daylight savings today

Stripping background images from PDFs

Sometimes I get a PDF I want to print, but there’s a background image or color that will eat too much ink, and I’d like to remove it. The example I’m going to use is the rules reference for Tales of Arabian Nights from The Esoteric Order of Gamers, which has a very bold parchment background.

image

This is a fairly simple job—you just need the right tool, and that tool is the FREE (and open-source) Inkscape. Once you’ve downloaded and installed it, browse to your file and open it. Being a PDF, you’ll be presented with a dialog asking you to convert it. You’ll need to do one page at a time, so select the page at the top.

image

Once you hit OK, it will import the file, and you can then select the background image and delete it. You’ll note that some of the text is in the wrong font—that’s because I don’t have the right font installed. Often, you’ll need to do cleanup like this (and possibly re-add logos), but that’s up to you depending on how polished you want the final result to be.

image

Once done, use File → Save As to save it back as a PDF. The biggest pain is that you’ll need to repeat this process page by page, ending up with numerous files (one for each page). But since the goal is to print it, it isn’t a big deal.

Here’s the before and after for another one I did:

image image


What does a developer user group attendee look like?

Someone who attends the awesome developer user group (DUG) is 26–35 years old, a senior C# developer, not looking for a new job, and works on websites or mobile apps at a company of 10 people or lessstatistically speaking. This is what came out in the recent DUG annual survey. This was the second time we ran the survey (2014 results can be found here), and we tried to keep the questions similar so we could compare. The goal of the survey is ultimately to understand the audience better so we can give it a better event.

Satisfaction

For us, as the leads of the group, the satisfaction numbers are very important, and we’re very happy to see a small uptick in them.

image

As for the complexity of sessions, it’s still near the middle but slightly higher, meaning they’re a bit more complex than last year.

Start Time

Going into last year’s survey, the start time for Johannesburg was a big discussion point: What time should the group start? Last year, 49% of people wanted it to remain as-is, 6% wanted it earlier, and 45% wanted it later. This year, those numbers have shifted: 57% want to keep it the same, none want it earlier, and 43% prefer a later time.

This year, we also have Pretoria data, and the picture is very different: only 37% are happy with the current time, while 63% want an earlier one. There’s no clear winner for the earlier time—16h30, 17h30, and 18h00 all received the same number of votes. Moving forward, this group will shift to an earlier time, so we hope to see an improvement next year.

Why Do You Attend?

Attendance is largely about skill development and networking, and for the most part, these numbers are similar to last year. The only interesting changes are around employment: those not looking for a job have decreased by 6%, while those looking for work have increased by around 5%.

image

Demographics

Breaking down the details of the group, starting with age:

  • 18–25: 10%
  • 26–35: 58%
  • 36–45: 26%
  • 46–55: 4%
  • 56–65: 2%

Skill level:

  • Senior: 67%
  • Intermediate: 18%
  • Junior: 14%

We’ve seen an increase in juniors since 2014—great trend!

Languages:

image

Compared to 2014, the declining languages are:

  • C# (down 3%)
  • C++ (down 1%)
  • Python, PHP, Scala, SQL (each down 1%, now dropping away completely)

The rising languages are:

  • Java (up 1%)
  • JavaScript (up 9%)
  • Objective-C (up 5%)
  • VB (up 1%)
  • Ruby, Haskell, and Meteor (all new at 2% this year)

What work are we doing?

image

There’s a trend away from web technology: internal websites are down 8%, public-facing websites 7%, while mobile development is up 9%.

Company size:

  • 1–10 employees: 28%
  • 11–20 employees: 12%
  • 91–200 employees: 8%
  • 41–80 employees: 8%
  • 21–40 employees: 2%
  • >200 employees: 0%

image

Role in purchasing:

  • Can suggest/influence purchases: 40%
  • None: 42%
  • Final say: 18%

Comments

Most comments were positive and supportive—thank you! One trend that stood out was video recording the sessions. This is something we’re investigating, and we want to offer these videos with a reliable system. It’s not an easy problem to solve, but we’re working on it.

Raw Data

If you’d like to explore the data yourself, you can find it below.


Code Formatter

If you want to commit to the .NET open source code, you need to follow the coding style that the teams use—and to assist with that, there is a helpful tool you can run over your code called Code Formatter. It’s a simple command-line tool that you can run over your code to fix up the style.

Clipboard01

Ultimately, I think this is a great tool and something that can easily be added to your build process to keep the code clean. I’d love to see someone like Steve Cadwallader, who made CodeMaid, start to introduce this tool so it can become part of Visual Studio.


A quick test

I decided to take it for a spin over my array fighter code, since it is a fairly messy piece of quick code I wrote, to see what would change—and it was really minor. First up, copyright headers were added, and I played with that to tweak the header a bit, which was a great option.

image

Second, all my items had accessors placed on them, and my fields were changed from starting with a capital to starting with a lowercase and underscore.

image


A bigger test

For a second test, I ran it over a HUGE project—which is frankly a disaster—and it took less than 10 seconds to handle just a few thousand files. Some things I noticed were:

  • The removal of blank lines:

image

  • Changing the copyright symbol to a Unicode number:

image

  • Prefixing static fields with s_:

image

  • Adding spaces in auto-properties and between member names and getters/setters:

image

image

I don’t personally like all of these changes, but they make sense—and it’s configurable.


Looking at the code

Since this is an open-source tool, we can look through the code for some interesting bits. The first area I examined was the unit tests, since they are all unit-tested using XUnit, and I really like how they structured them—simple to read and work with.

image

Nice to see someone using System.ComponentModel.Composition for a lightweight DI framework, since it’s been talked about so often but rarely seen in practice. The most interesting part, though, is that this is built with Roslyn—and it’s amazing how readable the code is. For example, here’s the code to insert the copyright header in about 20 lines:

image

If you’re looking for Roslyn examples, this is a great place to start.


Dead Regions

Hidden inside the solution is a second tool named Dead Regions, which finds and potentially edits conditional compiler blocks of code that are always TRUE/FALSE. It’s interesting, but I’m not sure it has as broad use as the formatter. Check out the readme.md for a good write-up on it.


String Interpolation (C# 6)

In our code today we often work with strings and want to mix code with it. The simplest version of this is just concatenation of strings:

// it is okay when it is small
var result = "Hello " + Name;

// it looks messy when it gets long
var result2 = "You " + SubjectName + " must be the pride and joy of " + SubjectHomeTown;

// and when you take it across multiple lines... it is ugly
var result3 = @"This was a " + TestResult + @". I am making a " + ReminderTool + @" here: " + SuccessRating;

[String.Format](https://msdn.microsoft.com/en-us/library/system.string.format(v=vs.110).aspx) is a potential help here:

```csharp
// multiple data slugs
return string.Format("{0} is {1} years old and their favourite animal is {2}",
    Name,
    Age,
    AnimalsOrderedByFavourite().First());

// using string.format for formatting
return string.Format("Hamsters cost {0:0.00}", 14.22);

The problem with string.Format is that it is possible to make mistakes with the format items, for example:

// this line works but outputs the wrong data. There is no way for the compiler to identify this, and you get no exceptions when you run it.
string.Format("{0} is {0} years old and their favourite animal is {2}",
    Name,
    Age,
    AnimalsOrderedByFavourite().First());

// this line compiles fine, but it will raise an exception when run, as there are only three parameters and you are asking for a fourth.
string.Format("{0} is {3} years old and their favourite animal is {2}",
    Name,
    Age,
    AnimalsOrderedByFavourite().First());

String Interpolation to the rescue!

String Interpolation aims to make these scenarios easier by allowing you to have blocks of code directly inside the string itself. To achieve this, we need to tell the compiler that the string may contain blocks of code, and we use the $ symbol prefixed on the string to do that. We can then insert blocks of code using the same braces we normally use for blocks of code. This allows us to change the code in the above examples to:

var result = $"Hello {Name}";
var result2 = $"You {SubjectName} must be the pride and joy of {SubjectHomeTown}";
var result3 = $@"This was a {TestResult}.
I am making a {ReminderTool} here:
{SuccessRating}";

return $"{Name} is {Age} years old and their favourite animal is {AnimalsOrderedByFavourite().First()}";

return $"Hamsters cost {14.22:0.00}";

In the above examples, it becomes clear what members we are working with, and it is no longer possible for us to make mistakes as the compiler will run and identify the issues at compile time—problems it can also simplify, as with the third line where we use a continuation without having to scatter multiple @ symbols around.

This is Code

This isn’t just a way to insert properties into strings; it is a way to insert code, so you can do all kinds of interesting things with it:

// concat inside the code block
var example1 = $"Hello {Name + LastName}";

// calling methods
var example2 = $"Your home town is in {LookupProvinceState(SubjectHomeTown)}";

// async works too
var example3 = $"The temp is {await GetTemp()}";

// strings inside strings with interpolation
var example4 = $"Inception is {Rating + $"Inception is {Rating}"}";

// LINQ works, and multi-line works if you add an @
var example5 = $@"LINQ works too {from a in AnimalsOrderedByFavourite()
                                 where a.Length > 20
                                 select a}";

// we can do string formatting
var example6 = $"Your balance is {Balance:C}";

The limitation here is that it must be a single statement. You cannot type a semicolon (;) inside the string interpolation.

Syntactic Sugar

This, like so many C# 6 features, is just syntactic sugar. Under the hood, it converts to using string.Format. For example, our first example above becomes:

string text = string.Format("Hello {0}",
    this.Name + this.LastName
);

What about Cultures? The Answer Is IFormattable

Looking at example six in the This is Code section, you can see we use string formatting for currency but cannot specify culture information. So how do we format it specifically?

The result of the interpolated string is a string that also implements IFormattable, and you can create a method to set the correct culture very easily:

static void Demo()
{
    // formatting as South African
    var example1 = en_za($"Your balance is {Balance:C}");
}

public static string en_za(IFormattable formattable)
{
    return formattable.ToString(null, new CultureInfo("en-za"));
}

In .NET 4.6, the string will also support System.Runtime.CompilerServices.FormattedString, enabling additional formatting options.


What is a Universal app?

A universal app (in regards to the Microsoft platform—as Apple uses this same term for something similar but different enough) is made up, at a very high level, of three areas. The first area, the User Interface (UI), is what you see, and for a universal app, it is built either with XAML or HTML. The second is the logic that powers the UI—the logic can go by many names (code behind, controller, view model, and more), and we will refer to the logic in this document as the brains. The UI and brains work together: the brains provide the raw data to the UI, which handles laying out and styling the data, and the UI provides input to the brains in the form of user interactions. The third piece is supporting code that the brains and UI use—for example, code that talks to an API or a database. This third piece is sometimes very separate and sometimes tightly mixed with the brains.

Traditionally, if you wanted to build an app that targets multiple platforms, you had to create a custom UI for each platform, and traditional software development tied the brains and the UI tightly together, meaning you often had to rewrite the brains or copy and paste code between different platforms. This leads to duplication in everything: cost, time to add features, bugs, etc.

1 Full image

Microsoft has introduced a concept called Universal Apps, which allows for creating a single core app that can run on Windows Phone 8.1, Windows 8/8.1/10, and Xbox One (coming soon). The way this works is by partitioning the app into multiple pieces—one for each target platform and an additional Shared piece. For this article, we’ll focus on building an app for Windows Phone 8.1 and Windows 8.1, meaning we’ll have three pieces in our project.

2 Full image

Microsoft does offer other technologies for greater code reuse, such as Portable Class Libraries (PCL), and there are industry patterns—like Dependency Injection (DI)—that can help, but none are essential or directly relevant here. The takeaway? Achieving maximum code reuse requires careful planning, an understanding of software development, and skilled developers.

The core idea in a Universal app is to place as much code as possible in the shared partition, allowing each platform to reuse the exact same UI, brains, and supporting code. Modern technologies in XAML and CSS 3 (for HTML) enable the UI to adapt intelligently to different screen sizes and devices, ensuring a single UI can work across all platforms. For the brains, proven practices like MVVM allow the logic to be decoupled from the UI, maximizing reuse.

In an ideal scenario, you’d get 100% of the code in shared—but in reality, it’s typically 75% to 95% (based on my experience and the app’s features/platform targets). The issue is that even with today’s best technology, some UI elements don’t work across all platforms, some features exist only on specific platforms, and optimizations can improve performance or user experience. In these cases, the relevant code or UI is moved out of the shared partition into the platform-specific section—with minimal duplication at worst.

A great example is settings: On Windows Phone, the design style dictates a single settings page accessed from a button in the app bar. For Windows 8.1, the design style suggests not including settings in the app bar—instead, you use the Settings charm and flyouts. In traditional development, this would require totally separate code and UI for settings. Following best practices, however, you can keep the logic once (in shared), break the UI into reusable components (also in shared), and compose them differently per platform. Only the unique composition details would vary.

3 Full image