747 Matching Annotations
  1. Mar 2016
    1. Very useful brief explanation of the basics of matrix/vector math that is relevant to 3D graphics and explanation of the process of transforming model vertexes into rendered pixel positions on screen.

    1. define and document the interfaces between them

      Agreed. Your point here is about the fact that we should document them, not how, but I have some proposals around tools that would help us with this - on the front-end at least.

    2. 1. The Hypothesis client library (hypothesis.js)

      I would consider the sidebar an application rather than a library - since it is something that is fully usable by an end-user on its own.

      Making the client a distinct entity from the web service is an important first step, but given the goals outlined above, I think this is still quite monolithic and we already have use cases (eg. EPUB) which will require dividing this into smaller pieces, with public APIs connecting them. This doesn't have to happen all at once, but we'll need to have it in mind. I think the initial division might look something like this:

      1. The code that lives in the web page or application and handles creation, anchoring and display of annotations in text documents. This is currently the code that lives in h/static/scripts/annotator. This would expose a public API that clients could use in order to display those annotations in a viewer (like our sidebar), attach information about the parent document, persist annotations to/from storage. This raises the question of whether we should use Annotator (2.x?)'s APIs as the public API or whether we should define our own and have Annotator be an implementation detail.
      2. The app that allows the user to view, edit, reply and otherwise interact with annotations on the content. This would connect with clients implementing the public API in (1). Initially this would include our HTML and PDF clients and I expect we would introduce one for EPUB as well.
      3. A library that serves as an SDK for the Hypothesis service and compatible web services. This would be used by (2) for retrieving/persisting annotations, subscribing to real-time updates etc.

      I would envision that (1) and (3) would have minimal external dependencies, so that they could be integrated into a variety of environments.

    3. it's about building a platform that will outlast Hypothesis the organisation.

      Providing a platform that other people can run is an important part of building something that can outlast the organization, but a big factor is providing a tool and service that proves the potential value of such a layer over the web.

      There are a few aspects to this which I think are relevant to the architecture of H:

      Enabling Integrations

      I think a lot of the potential value of H and annotation tools in general depends on making it convenient to integrate it with other services and web content. Areas of integration include:

      1. Identity/user profile and authentication.
      2. Custom document viewers
      3. Providers of machine-generated annotations

      (2) and (3) are relevant in terms of how we partition the client into libraries and what public APIs we expose.

      Enabling us to provide services on top of the data

      When talking about separating the client and web service, I think there has been the implicit assumption that the architecture would be like this:

      Hypothesis WS <==> Client <==> Third party identity/annotation providers
      

      Whilst I we will clearly need to support that model, I think we could also satisfy many needs with a model where the client communicates only (or primarily) with our service, and our service then communicates with third parties:

      Client <==> Hypothesis Web Service <==> 3rd party providers
      

      The primary advantages of this approach, from my perspective, is more control over the quality and consistency of user experience and the ability to provide services around that third-party data.

    4. It is far too early to be talking about creating new projects and git repositories for most of the components described above.

      My instinct at the moment is that I would rather we didn't create a bunch of new projects and Git repositories. I completely agree that we want to restructure the source tree so that it mirrors the overall architecture. However, I think having a single repository (or a very small number) has advantages in terms of reducing the total volume of project config boilerplate, making developers feel freer to engage with any part of the codebase, keeping track of issues and PRs and supporting open source contributions etc.

    5. This library is semantically versioned and released independently, and is deployed as built assets to a CDN.

      We could deploy this via npm to make it convenient for 3rd-party consumers. If we split the application as I suggested above then each of the parts with a public API would be its own npm package.

      We could potentially leverage cdnjs as the CDN if we did this, although we could obviously quite easily host it ourselves as well.

    6. In particular, we are pursuing two goals which can at times be in direct tension

      They can also be mutually very supportive.

      In particular, having a clear architecture with well-defined interfaces between the components is something that will help us regardless of what other people do with it.

    1. <!-- flex item: anonymous block box around inline content --> anonymous item 3

      In this case, text nodes inside a flex element will automatically be wrapped in a block box, so:

      <div style="display:flex">Some text</div>
      

      Is the same as writing

      <div style="display:flex"><div>Some text</div></div>
      
    1. The DROP COLUMN form does not physically remove the column, but simply makes it invisible to SQL operations. Subsequent insert and update operations in the table will store a null value for the column. Thus, dropping a column is quick but it will not immediately reduce the on-disk size of your table, as the space occupied by the dropped column is not reclaimed. The space will be reclaimed over time as existing rows are updated. (These statements do not apply when dropping the system oid column; that is done with an immediate rewrite.)
    1. Overall, there's a strong correlation between job satisfaction and pushing code into production. 65% of developers who never check in code are satisfied at their jobs vs. 77% satisfaction rate among developers who commit code multiple times per day. Developers want to code! (Or maybe happy developers just commit more than everyone else.)
    1. Therefore we've built https://github.com/salsita/redux-side-effects which is at least "somehow" trying to simulate the Continuations with Effect handlers approach. The idea is very simple, if reducer was generator then you could simply yield side effects and return mutated app state. So the only condition is to turn all your reducers into function* and use yield* whenever you want to compose them.

      This also looks like an interesting and potentially relatively simple take on supporting effects in reducers.

    1. In general, it is important to recognize that any big team will have multiple roles. And HTML templates are more inclusive of real-world workflow that includes designers, testers, and others who aren't deeply familiar with JavaScript, but who can interact with HTML templates directly or through tools.

      The question here is whether designers do actually edit Angular component templates or not, or whether something like JSX would actually be a problem for them. I don't have enough experience in such environments to answer this.

    1. This is a useful introduction through recent developments in client-side data management and an overview of the different choices available when building a new application and guidance on what is appropriate for different sizes of app.

    1. generate(ast, null, code);

      The code argument here is used for sourcemaps. Each node in the AST has source location information, which is retained as the AST is transformed. This information is then used to generate a sourcemap.

  2. Feb 2016
    1. This is a good short overview of how change detection works in Angular 2.

      It fixes the fundamental algorithmic complexity problem that change detection has in Angular 1.x by making it possible to prune parts of the component tree from change detection if the inputs have not changed.

      Unfortunately the zone.js implementation involves some horrifying monkey-patching of various DOM APIs.

    1. This is a perfect use-case for @extend. These rulesets are inherently related; their shared traits are shared for a reason, not coincidentally. Further, we aren’t transplanting their selectors hundreds of lines away from their source, so our Specificity Graph stays nice and sane

      So a sensible policy might be to use @extend only for related classes in the same source file, where source order is obvious.

    2. Some useful notes on the pros and cons of @extend vs mixins in SCSS.

      In a nutshell, he suggests avoiding @extend entirely.

      My main bugbear is that it prevents local reasoning about the final set of rules that will apply for an element with a given class.

    1. We’ve learned so far that bindings create a bigger $digest cycle, and it’d be a great idea for directives we create to potentially be statically rendered components that aren’t tied into Angular unless really needed.

      This is the critical performance problem with Angular. $interpolate looks interesting.

    1. ES6 performance sucks! Strong mode is a mode for ES6, you cannot use it without using various ES6 features. However, idiomatic ES6 code currently is substantially slower than ES5, across all browsers -- easily by 2x, often by 10x or more. Due to the sheer size of ES6, plus a number of unfortunate design choices, it will likely take years until implementations catch up with ES5 optimisations, and the hundreds of man years that went into those. Until then, strong mode is not going to be an attractive target

      Oh dear, "unfortunate design choices" sound ominous.

    1. n the Webpack approach, each Sass file is compiled in isolation. This isn't a new idea, but I think it's a much better way of doing Sass. It just means you need to @import dependencies like variables & mixins wherever you use them

      Which is a much better thing to be doing anyway in terms of having clear and explicit dependencies.

    1. If however, you’re predominantly dependent on the NPM ecosystem and you want a tool with a small and very well designed API and takes minimal configuration, you should go for Browserify

      We don't particularly need Node compatibility at the moment, but "small and well designed API" is appealing.

      On the other hand, not having to hunt around and collect all the tools together for packaging code for the browser is also appealing.

    1. When not setting an explicit domain for a cookie, the default in most browsers is to only send the cookie when the domain matches exactly. However, Internet Explorer violates the RFC, and will send it to all subdomains as well.
    1. Any browser extensibility is a potential vector for malicious software, and our extensions will be vetted, delivered, and managed through the Windows Store

      No details here on whether automated publishing of extensions will be possible using APIs

    1. “Search is the cornerstone of Google,” Corrado said. “Machine learning isn’t just a magic syrup that you pour onto a problem and it makes it better. It took a lot of thought and care in order to build something that we really thought was worth doing.”
    1. API-wise, one issue with React (or JSX) is that the render function often involves a lot of logic, and ends up looking more like a piece of program (which in fact it is) rather than a visual representation of the interface. For some developers this is a bonus, but for designer/developer hybrids like me, having a template makes it much easier to think visually about the design and CSS. JSX mixed with JavaScript logic breaks that visual model I need to map the code to the design. In contrast, Vue.js pays the cost of a lightweight data-binding DSL so that we have a visually scannable template and with logic encapsulated into directives and filters.

      I wonder whether JSX has proven problematic in practice for "designer/developer hybrids"?

  3. Jan 2016
    1. match_main(text, pattern, loc) => location Given a text to search, a pattern to search for and an expected location in the text near which to find the pattern, return the location which matches closest. The function will search for the best match based on both the number of character errors between the pattern and the potential match, as well as the distance between the expected location and the potential match.

      This is the core function currently used by the dom-anchor-text-quote library to handle fuzzy anchoring of annotations.

    1. All kinds of frameworks and architectures have state. In Ember apps and Backbone apps, state is in Models. In Angular apps, state is often in Factories and Services. In most Flux implementations, it is in Stores. How does Redux differ from these?

      Useful explanation of how state storage in Redux differs from other frameworks.

    1. Learn the actual underlying technologies, before learning abstractions. Don't learn jQuery, learn the DOM. Don't learn SASS, learn CSS. Don't learn HAML, learn HTML. Don't learn CoffeeScript, learn JavaScript. Don't learn Handlebars, learn JavaScript ES6 templates.

      Very true and a useful way to evaluate potential developers.

    1. Some docs on a prototype Hot Reloader for Angular. It relies on new component instances being able to pull data from singleton services, unlike the Redux solution where the store is passed down via context and most components just get the data via props.

    1. Note that this is functionally equivalent to using the HTML5 doctype.

      In other words, if you use the preferred <!DOCTYPE html>, you don't need the 'X-UA-Compatible' meta-tag.

    1. ink it so very much out of the way to hear the Rabbit say to itself, "Oh dear! Oh dear! I shall be too late!" But when the Rabbit actually took a watch out of its waistcoat-pocket and looke

      Foo bar

    2. And so it was indeed! She was now only ten inches high, and her face brightened up at the thought that she was now the right size for going through the little door into that lovely garden.

      This

    1. Now, as far as I know, this use of the UUID does not cause any major issues with the retailers, and will not lead to your EPUB being rejected. But it does not make sense to identify an EPUB with an ID that is not the ISBN. Future-proofing your content is one of the most important steps you can take as a production specialist.

      A summary of best practices for unique identifiers for epubs

    1. Shallow rendering currently throws an error if setState is called. React seems to expect that, if you use setState, the DOM is available. To work around the issue, we use jsdom so React doesn’t throw the exception when the DOM isn’t available. Here’s how to set it up:

      The issue may be fixed upstream in React > 0.14.6, there is also a simpler alternative on that thread which doesn't require setting up a pseudo-DOM environment for tests.

    1. Composing components in a single compile-time checked file is one of the big reasons JSX is so special.

      Not to mention that TypeScript can perform static type checking of JSX with nice IDE integration.

    1. You can call store.dispatch(action) from anywhere in your app, including components and XHR callbacks, or even at scheduled intervals.

      For an example of dispatch at regular intervals, the SoundRedux media player app dispatches an action every time the play time of the current song, measured in seconds, changes.

    2. If you find yourself often writing such operations, it’s a good idea to use a helper like react-addons-update, updeep, or even a library like Immutable that has native support for deep updates.

      Note that the "updeep" library has a dependency on lodash.

    1. EPUB CFIs are also a key part of the answer for how to share bookmarks, highlights, annotations and other reader-definable features between reading systems and between readers. By standardizing the referencing mechanism, it ensures that any reading system will be able to correctly dereference the location referenced by these CFIs, avoiding proprietary solutions to the same problem. (But, for true interop, a standard means of structuring the information for sharing is still necessary.)

      This is a good argument for why Hypothesis should use CFIs for anchoring in epubs

    1. Substrings in brackets are extensible assertions that improve the robustness of traversing paths and migrating them from one revision of the document to another. These assertions preserve additional information about traversed elements of the document, which makes it possible to recover intended location even after some modifications are made to the EPUB Publication
    1. Our current integration with Hypothesis is nearly two years old now and the interface needs rethinking and updating. Sliding panels coming in from both side aren’t ideal and obscure content. The design too closely mimics a printed book and as a result the paginated rendering hinders being able to make annotations across pages. A scrolling view would allow navigating the book and using the Hypothes.is toolbar at the same time. We’re going to create a new example reader with the controls, navigation and Hypothes.is integrated together with scrolling text.

      Are there any mockups of this available?

    1. When you associate a controller with a directive, an instance of the controller gets stored in the data store of the element. The naming convention for the key value is '$' + name of directive + 'Controller'

      @seanh - See this section and the 'element.data' part below in the code example

    1. Useful set of benchmarks based on the DBMonster demo for a set of different frameworks - looking at various axes such as GC collection, layout and paint times.

      There are some notable caveats in the comments though that the subjective feel was not always reflected in the metrics, suggesting that the authors believe they have not found the optimal set of metrics that reflect user-perceived performance.

  4. Dec 2015
    1. This is an interesting opinion piece on the difficulties that newcomers have with the React ecosystem and the problems with the lack of a central guidelines about which pieces to use and how to tie them altogether.

      I don't think it applies to just React though - choices around testing frameworks, build tools, languages etc. apply regardless of which framework you are using.

    1. I highly recommend giving it a read.

      Ditto, this is a very well constructed argument in favor of small modules.

      Unfortunately however, the current tendency to couple project infrastructure structure (Git repository, issue tracker etc.) to npm project structure doesn't suit this well.

    1. This effectively means that these directives cannot be used outside of annotated-image because Angular will throw an error when it cannot locate the required controller.

      In other words, the child components are no longer re-usable and this breaks composability.

    1. It is important to note that the path attribute does not protect against unauthorized reading of the cookie from a different path. It can be easily bypassed using the DOM, for example by creating a hidden iframe element with the path of the cookie, then accessing this iframe's contentDocument.cookie property. The only way to protect the cookie is by using a different domain or subdomain, due to the same origin policy.
    1. This will make the directory /data inside the container live outside the Union File System and directly accessible on the host. Any files that the image held inside the /data directory will be copied into the volume. We can find out where the volume lives on the host by using the docker inspect command on the host (open a new terminal and leave the previous container running if you’re following along):

      In Docker 1.9 the field name is Mounts rather than Volumes

    1. and a related URL fragment specification will leverage the FindText API to let you share a URL that navigates directly to the selection you shared

      Does anyone have a link to said specification?

  5. Nov 2015
    1. Firefox and Chrome exhibit different behaviors when trying to style elements that appear inside a <use> block. In Firefox 45, a .use-element-class .sub-element-class selector will style the element as expected. In Chrome it won't because this is trying to cross a DOM boundary (that is, the SVG content and the <use> element are in different DOMs). This article has useful background to this and approaches to use.

    1. Here’s an example with a component directive that uses bindToController. Instead of defining the scope properties on scope, we declaratively define what properties are bound to the component’s controller:

      Example of idiomatic integration of controllers into directives in Angular 1.4.x+

    1. This extension passes the AMO validator with no signing warnings, meaning it would be automatically signed for distribution. #1 required no modifications to pass validation. #2 and #3 required some l33t hacking in the form of Components.interfaces["nsI" + "p".toUpperCase() + "rocess"] and window['e'.replace() + 'val'](req.responseText) — variations on basic string concatentation.

      Good lord Mozilla, this is not how you do security.

    1. Won't this be fixed now under Bug 49739?

      "WebIDL attributes should be implemented as getters and setters on the prototype chain " - As of 24/11/15, assigned but not yet implemented.

    2. Trying to override the getter on the prototype of an element is somewhat pointless as WebKit does not use getters for DOM properties. Technically we could make it do so, but that basically means throwing away performance for no good reason. Comment 2 T. Brains 2010-03-21 14:23:58 PDT That means there's absolutely no way to override or extend the default get or set behavior of any of the built-in DOM properties, which is very limiting, and like I mentioned contradicts the behavior of other browsers.

      When this was written, overriding getters for native DOM properties was not possible.

    1. The free plan of ngrok allows only a single concurrent tunnel to be opened. Even though BroswerStack and Sauce Labs provide their own tunneling solution, we decided to go with ngrok, in order to provide a more generic solution. We happily upgraded to the $25/month business account following our excellent experience with the free account.
    1. Given we put the system in a known state before the user (or external system) starts interacting with the system (in the When steps). Avoid talking about user interaction in givens. When we take key actions the user (or external system) performs. This is the interaction with your system which should (or perhaps should not) cause some state to change. Then we observe outcomes.
    1. This problem is precisely the kind of problem that FSMs are very good at resolving. If you can enumerate the states, and events, then you know the number of paths though the system. So if Given/When/Then statements are truly nothing more than state transitios, all we need to do is enumerate the number of GIVENs and the number of WHENs. The number of scenarios will simply be the product of the two.

      Main observation here is that BDD is essentially a syntax for specifying states and transitions in a state machine. If all possible states and events can be enumerated, you can quantify what proportion of paths through the system have been tested

    1. Most apps had detailed stats to help improve performance. However, to a friend who is not a runner, that info is much less exciting. They would probably much rather see that it was equal to 5 donuts, and give you a thumbs up.
    1. On October 14, 2003, the Swiss newspaper Tages-Anzeiger published a few articles presenting as a scandal the fact that the Degussa company was involved in the construction of the memorial producing the anti-graffiti substance Protectosil used to cover the stelae, because the company had been involved in various ways in the National-Socialist persecution of the Jews. A subsidiary company of Degussa, Degesch, had even produced the Zyklon B gas used to poison people in the gas chambers.
    1. The onboarding flow can be designed in many other ways that might be more useful to your users. Slack, for instance, uses the first screen to create some context. They simply introduce themselves, focusing on benefits instead of screens and features.
    2. That’s why now all the big players are shifting from hamburger menus towards making the most relevant navigation options always visible.

      Interesting example of YouTube switching away from the hamburger menu.

    1. use Hypothesis

      Hello MozFest 2015!

      If you have any feedback, feel free to add comments here.

      You can create a Hypothesis account for yourself, or use one shared for this presentation:

      username: mozfest2015

      password: mozfest

    1. You’ll now have three Docker containers

      On Ubuntu the steps below will work fine because Docker runs the containers on the same IP as the host. On OS X however the containers will run in a VM with a different IP address. The H default configuration expects to find the services on localhost, so make dev fails.

    1. So in both cases we are writing contracts that say “I require input with this shape, and I will give you output with that shape.” This is the essence of ruling out runtime errors in Elm. We always know what kind of values a function needs and what kind it produces, so we can just check that we always follow these rules.
  6. Oct 2015
    1. Installing the services¶

      The current version of these steps will run all of the services under Docker.

      If you are on Linux, the services will be available on localhost:<port number>.

      If you are on Mac however, the services will usually be available on the IP of the virtual machine which is running the docker containers. If using docker-machine which is the recommended tool, then the IP is given by docker-machine ip default.

      If the host is not localhost, you'll need to set environment variables to override the default ports/hosts for services which are defined in conf/development.ini.

      eg. Create a file that defines environment variables. Assuming the host of your Docker VM was called "docker" (replace with the actual hostname or IP):

      export DATABASE_URL='postgresql://postgres@docker/postgres'
      export TEST_DATABASE_URL='postgresql://postgres@docker/h_test'
      
      export ELASTICSEARCH_PORT=
      export ELASTICSEARCH_PORT_9200_TCP_ADDR=docker
      export ELASTICSEARCH_PORT_9200_TCP_PORT=9200
      
      export NSQD_PORT=
      export NSQD_PORT_4150_TCP_ADDR=docker
      export NSQD_PORT_4150_TCP_PORT=4150
      export NSQD_PORT_4151_TCP_ADDR=docker
      export NSQD_PORT_4151_TCP_PORT=4151
      
      export REDIS_PORT=
      export REDIS_PORT_6379_TCP_ADDR=docker
      export REDIS_PORT_6379_TCP_PORT=6379
      

      And source it with source <filename>

    2. Python dependencies

      During this step I ran into the following error under OS X at the very end of dependency installation:

      gevent is in an unsupported or invalid wheel

      See http://stackoverflow.com/questions/33009545/gevent-is-in-an-unsupported-or-invalid-wheel for a solution

      In short, the fix was:

      1. Edit setup.py to loosen the requirement for gevent to `gevent>=1.0.2
      2. Install a newer version of gevent via: pip install gevent=1.1b6 where 1.1b6 is the current beta at the time of writing.

      Once the final 1.1 build is released we should bump the dependency.

    3. PostgreSQL

      Later on when installing the python dependencies required to run the H backend, the pg_config executable will be required.

      Although you can install postgres via Docker, it appears that the postgres dev tools still need to be installed on the host machine as well.

      On OS X this can be done via brew install postgres

    4. Install h’s Python dependencies into the virtual environment, and its Node dependencies into the h/node_modules directory

      This has been obsoleted now by making this step happen as part of make dev (see the section below on "Running h")

    5. Download and run the official NSQ image, the official PostgreSQL image, and our custom Elasticsearch with ICU image

      On the command line this can be done with:

      docker pull nsqio/nsq
      docker pull postgres
      docker pull nickstenning/elasticsearch-icu
      
    1. The best explanation I was able to get from them for why they did this was, ``it looked ugly and I didn't understand why it was there.''

      First rate commit message material

    1. The temporary solution we found is to wrap chrome.* api callback with setTimeout() function. In that case errors thrown within chrome.* api call are passed to window.onerror with correct line number. Example:

      Wrapping all the chrome.* async API calls such that exceptions in the callback result in an error being logged to a handler that we control looks like the way to go.

    1. Replace a two-way '=' binding on the directive configuration with an expression binding '&'

      Note the caveats in the comments section at the bottom. '=' is not only a two-way binding but it also handles automatic updates when the input changes. In the absence of React-style 're-render the whole component' when a model value changes, this is needed.

    2. Smart components are connected to services. Though they may have inputs and outputs, they mostly know how to load their own data, and how to persist changes when they occur

      Useful categorization of 'smart' and 'dumb' in the context of Angular

    3. We can refactor this component by, first of all, changing its signature so that it gives out the new version of the object when the user is done, instead of just mutating the input object in place:

      The section on refactoring components that rely on two-way binding to update the model is useful

    1. Here’s what the team says about preparing code for less migration effort when we get Angular 2.0, which is luckily in-line with the guesses that several others came up with so far.

      Some useful notes about writing Angular components in a forwards-compatible way.

  7. lhorie.github.io lhorie.github.io
    1. In version 1.4, bindToController gets even more powerful. When having an isolated scope with properties to be bound to a controller, we always define those properties on the scope definition and bindToController is set to true. In 1.4 however, we can move all our property binding definitions to bindToController and make it an object literal.

      This starts to look a lot like propTypes, except without runtime type checking.

    2. In fact, we don’t even need to request $scope in our controller anymore, since the scope is bound the controller’s this reference when using controllerAs.

      So in the context of a directive, when a property is specified on scope in the directive's definition object, it will be available in expressions in the template via vm.<property>, assuming vm is the name assigned to the controller via controllerAs

    1. JSX is Not an HTML Template LanguageThough it looks like it, JSX isn’t a template in the sense that Handlebars and EJS are templates. It’s not a simple token replace and `.innerHTML= foo` dump like so many other tools.

      This is a great explanation of why JSX is not a templating engine, which it is often mistaken for.

    1. Consolidated all our HTML resets into a new module, Reboot. Reboot steps in where Normalize.css stops, giving you more opinionated resets like box-sizing: border-box, margin tweaks, and more all in a single Sass file.

      Worth having a look into the Reboot module to see what the reset involves and the rationale.

      Note that normalize.css is used as a baseline, with styles from reboot.scss applied on top.

      See https://github.com/twbs/bootstrap/blob/v4-dev/scss/_reboot.scss

    1. The bad news: we now have to contemplate adding authentication to our RSS/Atom feeds.

      Since anyone who has the original link can join a group, perhaps just provide a way for group members to generate an RSS link that includes authentication (eg. as a query string parameter)?

    1. You can then just use one class in your markup <button class="Button--error"> and get the common & specific styles you want. It’s a really powerful concept, but the implementation has some edge cases & pitfalls that you should be aware of. A great summary of those issues and links to further reading is available here, thanks to Hugo Giraudel.

      Some notes worth a read on SASS and @extends

  8. Sep 2015