1108 stories
·
1 follower

Screenshot? Ugh, you’re doing it wrong!

1 Share

A proper sharing feature has been part of iOS for years. It has a consistent, system-level UI that’s available from most any app with anything worth sharing and yet no one seems to use it. Well, no one but us geeks, right? Everyone else just takes screenshots—which require mastering an unintuitive multi-button press and a fair amount of dexterity.

I moaned when people started posting screenshots of highlighted selections from articles to beat the 140 character limit on Twitter because they just shared a picture of text that I can’t copy, reformat, enlarge, etc. I’ve been that guy when friends send a screenshot of a product rather than a link. Sharing properly is a very type-A process that I dutifully complete out of ease for my friends and respect for the content!

That’s why my inner pedant was delighted when Instagram noticed I had taken a screenshot and gently nudged me to use the proper share features.

Use the hardware buttons to make a screenshot and Instagram is all, “Oh silly luddite, please send people a functional link.” Tapping the Share banner in the second screenshot corrects your bad form and helps you share a URL.

It’s a really nice solution that gently guides the user to the correct way to share. I’ll admit this is probably the solution I’d have designed, too. The built-in Share feature should be easier and yet friends and relatives who can barely download an app find screenshotting to be second nature.

That’s why I was delighted to see Amazon’s take on the same problem. Where Instagram’s design is a gentle scolding, Ahem! I see you have no idea what you’re doing, Amazon’s much scrappier version says, Oh you made a screenshot? Cool, lemme help you with that.

“I got you, bro.”

Amazon shows a similar, though more obvious, banner after you make a screenshot but it does things a little differently after that. For one, it uses the system’s Share Sheet which is familiar and provides a lot more options than Instagram’s custom one.

More important than that, however, is the payload. Amazon shares my screenshot and then adds a URL to it. It’s a subtle difference but Amazon’s version makes me feel better. Where Instagram gets my intent and tries to help me do the right thing, it replaced my content. Amazon’s design let’s me do what I intended but helps me do it better. In the screenshots above a major difference is posting to Twitter. Instagram’s post wouldn’t include an image, Amazon’s would.

As a designer I love being surprised by solutions I wouldn’t have come up with. I can absolutely see how Instagram arrived at their solution. Part of UI design is guiding users back when they go off track. Designers want to change the world by making things easier, more understandable, more enjoyable—more ideal. That completely resonates but I can’t help but admire the audacity of Amazon’s designers who have accepted the world as it is and humbly offered a helping hand. Kudos!


Screenshot? Ugh, you’re doing it wrong! was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
emrox
3 days ago
reply
Hamburg, Germany
Share this story
Delete

One more

2 Shares

Read the whole story
emrox
4 days ago
reply
Hamburg, Germany
Share this story
Delete

A Good Vimrc

1 Share
Comments
Read the whole story
emrox
7 days ago
reply
Hamburg, Germany
Share this story
Delete

A formal spec for GitHub Flavored Markdown

1 Share

We are glad we chose Markdown as the markup language for user content at GitHub. It provides a powerful yet straightforward way for users (both technical and non-technical) to write plain text documents that can be rendered richly as HTML.

Its main limitation, however, is the lack of standarization on the most ambiguous details of the language. Things like how many spaces are needed to indent a line, how many empty lines you need to break between different elements, and a plethora of other trivial corner cases change between implementations: very similar looking Markdown documents can be rendered as wildly different outputs depending on your Markdown parser of choice.

Five years ago, we started building GitHub’s custom version of Markdown, GFM (GitHub Flavored Markdown) on top of Sundown, a parser which we specifically developed to solve some of the shortcomings of the existing Markdown parsers at the time.

Today we’re hoping to improve on this situation by releasing a formal specification of the syntax for GitHub Flavored Markdown, and its corresponding reference implementation.

This formal specification is based on CommonMark, an ambitious project to formally specify the Markdown syntax used by many websites on the internet in a way that reflects its real world usage. CommonMark allows people to continue using Markdown the same way they always have, while offering developers a comprehensive specification and reference implementations to interoperate and display Markdown in a consistent way between platforms.

The Specification

Taking the CommonMark spec and re-engineering our current user content stack around it is not a trivial endeavour. The main issue we struggled with is that the spec (and hence its reference implementations) focuses strictly on the common subset of Markdown that is supported by the original Perl implementation. This does not include some of the extended features that have been always available on GitHub. Most notably, support for tables, strikethrough, autolinks and task lists are missing.

In order to fully specify the version of Markdown we use at GitHub (known as GFM), we had to formally define the syntax and semantics of these features, something which we had never done before. We did this on top of the existing CommonMark spec, taking special care to ensure that our extensions are a strict and optional superset of the original specification.

When reviewing the GFM spec, you can clearly tell which parts are GFM-specific additions because they’re highlighted as such. You can also tell that no parts of the original spec have been modified and therefore should remain fully compliant with all other implementations.

The Implementation

To ensure that the rendered Markdown in our website is fully compliant with the CommonMark spec, the new backend implementation for GFM parsing on GitHub is based on cmark, the reference implementation for CommonMark developed by John MacFarlane and many other fantastic contributors.

Just like the spec itself, cmark focuses on parsing a strict subset of Markdown, so we had to also implement support for parsing GitHub’s custom extensions on top of the existing parser. You can find these changes on our fork of cmark; in order to track the always-improving upstream project, we continuously rebase our patches on top of the upstream master. Our hope is that once a formal specification for these extensions is settled, this patchset can be used as a base to upstream the changes in the original project.

Besides implementing the GFM-specific features in our fork of cmark, we’ve also contributed many changes of general interest to the upstream. The vast majority of these contributions are focused around performance and security. Our backend renders a massive volume of Markdown documents every day, so our main concern lies in ensuring we’re doing these operations as efficiently as possible, and making sure that it’s not possible to abuse malicious Markdown documents to attack our servers.

The first Markdown parsers in C had a terrible security history: it was feasible to cause stack overflows (and sometimes even arbitrary code execution) simply by nesting particular Markdown elements sufficiently deep. The cmark implementation, just like our earlier parser Sundown, has been designed from scratch to be resistant to these attacks. The parsing algorithms and its AST-based output are thought out to gracefully handle deep recursion and other malicious document formatting.

The performance side of cmark is a tad more rough: we’ve contributed many optimizations upstream based on performance tricks we learnt while implementing Sundown, but despite all these changes, the current version of cmark is still not faster than Sundown itself: Our benchmarks show it to be between 20% to 30% slower on most documents.

The old optimization adage that “the fastest code is the code that doesn’t run” applies here: the fact is that cmark just does more things than Sundown ever did. Amongst other functionality, cmark is UTF8 aware, has better support for references, cleaner interfaces for extension, and most importantly: it doesn’t translate Markdown into HTML, like Sundown did. It actually generates an AST (Abstract Syntax Tree) out of the source Markdown, which we can transform and eventually render into HTML.

If you consider the amount of HTML parsing that we had to do with Sundown’s original implementation (particularly regarding finding user mentions and issue references in the documents, inserting task lists, etc), cmark’s AST-based approach saves us a tremendous amount of time and complexity in our user content stack. The Markdown AST is an incredibly powerful tool, and well worth the performance cost that cmark pays to generate it.

The Migration

Changing our user content stack to be CommonMark compliant is not as simple as switching the library we use to parse Markdown: the fundamental roadblock we encountered here is that the corner cases that CommonMark specifies (and that the original Markdown documentation left ambiguous) could cause some old Markdown content to render in unexpected ways.

Through synthetic analysis of GitHub’s massive Markdown corpus, we determined that less than 1% of the existing user content would be affected by the new implementation: we gathered these stats by rendering a large set of Markdown documents with both the old (Sundown) and the new (cmark, CommonMark compliant) libraries, normalizing the resulting HTML, and diffing their trees.

1% of documents with minor rendering issues seems like a reasonable tradeoff to swap in a new implementation and reap its benefits, but at GitHub’s scale, 1% is a lot of content, and a lot of affected users. We really don’t want anybody to check back on an old issue and see that a table that was previously rendering as HTML now shows as ASCII – that is bad user experience, even though obviously none of the original content was lost.

Because of this, we came up with ways to soften the transition. The first thing we did was gathering separate statistics on the two different kinds of Markdown user content we host on the website: comments by the users (such as in Gists, issues, Pull Requests, etc), and Markdown documents inside the Git repositories.

There is a fundamental difference between these two kinds of content: the user comments are stored in our databases, which means their Markdown syntax can be normalized (e.g. by adding or removing whitespace, fixing the indentation, or inserting missing Markdown specifiers until they render properly). The Markdown documents stored in Git repositories, however, cannot be touched at all, as their contents are hashed as part of Git’s storage model.

Fortunately, we discovered that the vast majority of user content that was using complex Markdown features were user comments (particularly Issue bodies and Pull Request bodies), while the documents stored in Git repositories were rendering properly with both the old and the new renderer in the overwhelming majority of cases.

With this in mind, we proceeded to normalize the syntax of the existing user comments, as to make them render identically in both the old and the new implementations.

Our approach to translation was rather pragmatic: Our old Markdown parser, Sundown, has always acted as a translator more than a parser. Markdown content is fed in, and a set of semantic callbacks convert the original Markdown document into the corresponding markup for the target language (in our use case, this was always HTML5). Based on this design approach, we decided to use the semantic callbacks to make Sundown translate from Markdown to CommonMark-compliant Markdown, instead of HTML.

More than translation, this was effectively a normalization pass, which we had high confidence in because it was performed by the same parser we’ve been using for the past 5 years, and hence all the existing documents should be parsed cleanly while keeping their original semantic meaning.

Once we updated Sundown to normalize input documents and sufficiently tested it, we were ready to start the transition process. The first step of the process was flipping the switch on the new cmark implementation for all new user content, as to ensure that we had a finite cut-off point to finish the transition at. We actually enabled CommonMark for all new user comments in the website several months ago, with barely anybody noticing – this is a testament to the CommonMark team’s fantastic job at formally specifying the Markdown language in a way that is representative of its real world usage.

In the background, we started a MySQL transition to update in-place the contents of all Markdown user content. After running each comment through the normalization process, and before writing it back to the database, we’d render it with the new implementation and compare the tree to the previous implementation, as to ensure that the resulting HTML output was visually identical and that user data was never destroyed in any circumstances. All in all, less than 1% of the input documents were modified by the normalization process, matching our expectations and again proving that the CommonMark spec really represents the real-world usage of the language.

The whole process took several days, and the end result was that all the Markdown user content on the website was updated to conform to the new Markdown standard while ensuring that the final rendered output was visually identical to our users.

The Conclusion

Starting today, we’ve also enabled CommonMark rendering for all the Markdown content stored in Git repositories. As explained earlier, no normalization has been performed on the existing documents, as we expect the overwhelming majority of them to render just fine.

We are really excited to have all the Markdown content in GitHub conform to a live and pragmatic standard, and to be able to provide our users with a clear and authoritative reference on how GFM is parsed and rendered.

We also remain committed to following the CommonMark specification as it irons out any last bugs before a final point release. We hope GitHub.com will be fully conformant to the 1.0 spec as soon as it is released.

To wrap up, here are some useful links for those willing to learn more about CommonMark or implement it on their own applications:

Read the whole story
emrox
10 days ago
reply
Hamburg, Germany
Share this story
Delete

Discontinue support for weak cryptographic standards

2 Shares

Cryptographic standards are ever evolving. It is the canonical game of security cat and mouse, with attacks rendering older standards ill-suited, and driving the community to develop newer and stronger standards to take their place. There have been a number of cryptographic attacks over the past of couple of years. These include, but are not limited to, attacks such as POODLE and Logjam . And, while there have been workarounds for some of these attacks, they demonstrated that several cryptographic standards in wide deployment are showing their age and should be retired. As a result, GitHub is announcing the immediate deprecation, and eventual disablement, of our use of the following cryptographic standards:

  • TLSv1/TLSv1.1 - This applies to all HTTPS connections, including web, API, and git connections to https://github.com and https://api.github.com.
  • diffie-hellman-group1-sha1 - This applies to all SSH connections to github.com.
  • diffie-hellman-group14-sha1 - This applies to all SSH connections to github.com.

All of the above will be disabled on February 1, 2018.

In order to minimize the number of users affected by this change we intend do the following before disabling support:

  • Post quarterly updates to the GitHub engineering and GitHub developer blogs to remind people of the deprecation and encourage them to prepare for the change.
  • Reach out to popular projects that we know to be currently incompatible with these changes.
  • Update our own SSH implementation to add support for diffie-hellman-group-exchange-sha256, as this will minimize the number of SSH clients affected.

Technical details

TLS 1/1.1

The vast majority of HTTPS connections (approximately 95%) made to https://github.com and https://api.github.com use TLS 1.2 and will not be affected. This includes every currently shipping browser used by GitHub users. The vast majority of connections made to GitHub services using TLS 1/TLS 1.1 are clients built using older SSL/TLS libraries that do not support TLS 1.2. Mostly commonly, this includes clients built using older versions of the Java JDK as well clients built on operating systems bundled with an older version of OpenSSL.

The Java JDK did not use TLS 1.2 by default until JDK 8 was released in 2014. While JDK 7 supported TLS 1.2, it was not enabled by default for compatibility reasons. Likewise, OpenSSL did not support TLS 1.2 until version 1.0.1 was released in 2012. As a result, several popular older operating systems, such as Red Hat 5, continue to rely on older versions of OpenSSL. We appreciate the difficulty associated with upgrading systems that rely on these older libraries, but feel the security gained for all GitHub users make it a worthwhile trade-off.

Weak SSH key exchange algorithms

GitHub supports both HTTPS as well as SSH based connections when performing Git operations. When a SSH connection is made to github.com, the client and server must determine a mutually agreeable set of cryptographic algorithms to use for the connection. One such algorithm is the key exchange algorithm. The key exchange algorithm is used to securely exchange a strong cryptographic key to protect future messages in the protocol. Without a secure key exchange algorithm, all future messages exchanged between the client and server can’t be trusted.

The Logjam Attack research released in 2015 noted some key exchange algorithms were subject to an attack and should be disabled. In particular, they encouraged all system administrators to disable support for the diffie-hellman-group1-sha1 key exchange algorithm. While their analysis further clarified that diffie-hellman-group14-sha1 should be secure for the foreseeable future, GitHub is choosing to pro-actively discontinue support for this algorithm as well. SSH supports a number of more contemporary algorithms that are not subject, even theoretically, to the precompuation attacks described in the Logjam research.

The majority of SSH connections (approximately 75% ) made to GitHub.com are compatible with more contemporary SSH key exchange algorithms and will not be affected by the removal of diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1. However, that leaves a minority, but still substantial, set of clients that are currently only compatible with one of the legacy key exchange algorithms. Fortunately, the vast majority of these clients do support some newer algorithms, but none that currently overlap with those supported by GitHub. As a result, GitHub will add support for diffie-hellman-group-exchange-sha256 before we remove support for diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1. By adding support for diffie-hellman-group-exchange-sha256 we estimate that 5% of current clients would be affected.

Conclusion

We understand that this will incur additional burden for a small set of developers and users. It is for that reason that we are announcing this deprecation now. We hope that, given approximately a year to prepare, developers and users are able to upgrade their operating systems, libraries, and client software to be compatible with these changes. If you have any questions or concerns related to this announcement, please don’t hesitate to contact us.

Read the whole story
emrox
13 days ago
reply
Hamburg, Germany
alvinashcraft
27 days ago
reply
West Grove, PA
Share this story
Delete

Feature watch: ECMAScript 2018

2 Shares

This blog post tracks what features may be included in ES2018. I will continually update it.

Proposed ECMAScript 2018 features

Recall that every ECMAScript feature proposal goes through stages:

  • Stage 4 means that a feature will be in the next release (or the one after that).
  • Stage 3 means that a feature still has a chance of being included in the next release.

Stage 4 and part of ECMAScript spec draft

(No proposals at this time.)

Candidate features (stage 3)

The following features are currently at stage 3:

FAQ

What do the stages mean?

They refer to maturity stages of the so-called “TC39 process”. Check chapter “The TC39 process for ECMAScript features” in “Exploring ES2016 and ES2017” for more information.

How is [my favorite proposed feature] doing?

If you are wondering what stages various proposed features are in, consult the readme of the ECMA-262 GitHub repository.

Further reading

The following books by me are free to read online:

Read the whole story
emrox
14 days ago
reply
Hamburg, Germany
alvinashcraft
26 days ago
reply
West Grove, PA
Share this story
Delete
Next Page of Stories