<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Dan Matthew</title><description>Notes and thoughts from Dan Matthew, an accessibility and design systems consultant</description><link>https://danmatthew.co.uk/</link><item><title>Glofox Data Breach March 2020</title><link>https://danmatthew.co.uk/notes/glofox-data-breach-march-2020/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/glofox-data-breach-march-2020/</guid><pubDate>Tue, 25 May 2021 16:32:11 GMT</pubDate><content:encoded>&lt;p&gt;Have you heard of a company called &lt;a href=&quot;https://www.glofox.com&quot;&gt;Glofox&lt;/a&gt;? Their software provides the booking system for gyms and fitness studios.&lt;/p&gt;
&lt;p&gt;They suffered a data breach in March 2020, &lt;a href=&quot;https://duckduckgo.com/?q=glofox+data+breach&quot;&gt;but haven&apos;t said much about it&lt;/a&gt;. &lt;a href=&quot;https://www.glofox.com/blog/category/news/&quot;&gt;Nothing I could find&lt;/a&gt;. &lt;a href=&quot;https://www.irishtimes.com/business/technology/irish-start-up-glofox-investigates-possible-data-breach-1.4414837&quot;&gt;Others have, however&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Glofox has not responded to media requests for comment on a possible security breach but it has, in recent days, responded to individuals on Twitter who posed questions to the company after being informed its website had been compromised.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lame. I was under the impression that under data protection legislation, organisations must contact the appropriate body and make a public statement as soon as they have knowledge of a breach. As an Irish company, they should have reported it to the &lt;a href=&quot;https://www.dataprotection.ie/&quot;&gt;Data Protection Commission&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;From 25 May 2018, the General Data Protection Regulation (GDPR) introduces a requirement for organisations to report personal data breaches to the relevant supervisory authority, where the breach presents a risk to the affected individuals. Organisations must do this within72 hours of becoming aware of the breach.&lt;/p&gt;
&lt;p&gt;Where a breach is likely to result in a high risk to the affected individuals, organisations must also inform those individuals without undue delay.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Whoops. Did Glofox pass this responsibility on to their customers, or are they not bothered? Note the date of the Irish Times report: November 2020.&lt;/p&gt;
&lt;p&gt;In January 2021 I was alerted to the breach thanks to a service called &lt;a href=&quot;https://haveibeenpwned.com/PwnedWebsites#Glofox&quot;&gt;Have I Been Pwned&lt;/a&gt;. It&apos;s integrated in my password manager, &lt;a href=&quot;https://1password.com/&quot;&gt;1Password&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since the Glofox dashboard does not offer a way to delete an account, it took an email to &lt;a href=&quot;mailto:dataprivacy@glofox.com&quot;&gt;dataprivacy@glofox.com&lt;/a&gt; to do so.&lt;/p&gt;
&lt;p&gt;It&apos;s taken until May for the first spam emails to arrive at the compromised email addresses: both hawking a Norton Antivirus subscription which needs renewing. Do you think it leads to a legitimate website?&lt;/p&gt;
&lt;p&gt;If you&apos;re going to look after personal data, get your shit together. Mistakes happen, but don&apos;t try and hide it.&lt;/p&gt;
</content:encoded></item><item><title>Access local server from Parallels VM</title><link>https://danmatthew.co.uk/notes/access-local-server-from-parallels-vm/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/access-local-server-from-parallels-vm/</guid><pubDate>Sun, 09 May 2021 18:28:53 GMT</pubDate><content:encoded>&lt;p&gt;I was struggling to access a development server on my host machine from a Windows 10 virtual machine (VM). Despite sharing a network, turns out the trick is not to use the host IP address, but  that of the bridged network the VM has created. For Parallels, that address tends to be &lt;code&gt;10.211.55.2&lt;/code&gt;&lt;/p&gt;
</content:encoded></item><item><title>Netlify CMS</title><link>https://danmatthew.co.uk/notes/2021-01-17-netlify-cms/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2021-01-17-netlify-cms/</guid><pubDate>Sun, 17 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been experimenting with services such as &lt;a href=&quot;https://www.contentful.com/&quot;&gt;Contentful&lt;/a&gt;, &lt;a href=&quot;https://prismic.io/&quot;&gt;Prismic&lt;/a&gt;, and finally &lt;a href=&quot;http://sanity.io&quot;&gt;Sanity&lt;/a&gt;. Currently, each post on this site is a Markdown file, and it is converted into a HTML page by 11ty when the site is built. The &quot;content-as-a-service&quot; platforms return data over the wire, and each record in the GraphQL response is turned into the post it represents.&lt;/p&gt;
&lt;p&gt;However, I think I prefer to keep each post as a file, all wrapped up on Github, so it&apos;s back to &lt;a href=&quot;https://www.netlifycms.org&quot;&gt;Netlify CMS&lt;/a&gt; for me.&lt;/p&gt;
</content:encoded></item><item><title>Pharmaceuticals</title><link>https://danmatthew.co.uk/notes/2020-12-08-pharmaceuticals/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-12-08-pharmaceuticals/</guid><pubDate>Tue, 08 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I thought I was an OK runner. I trained hard over the course of 2018 and aimed to get under 1:40 at the Great North Run. I ran 1:31, and then a few weeks later went 1:27 at Birmingham&apos;s Great Run.&lt;/p&gt;
&lt;p&gt;Since that purple patch, running has gotten harder and harder because my asthma has become harder to control.&lt;/p&gt;
&lt;p&gt;While I&apos;ve had a blue &quot;rescue&quot; inhaler to hand since I was a child, I&apos;ve quickly progressed through the various steroids over the past two years:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Beclometasone 400mg (&lt;em&gt;Clenil Modulite&lt;/em&gt;, brown)&lt;/li&gt;
&lt;li&gt;Fluticasone (&lt;em&gt;Flutiform&lt;/em&gt;, white)&lt;/li&gt;
&lt;li&gt;Beclometasone 100 &lt;em&gt;micro&lt;/em&gt;-grams (&lt;em&gt;Fostair 100&lt;/em&gt;, pink)&lt;/li&gt;
&lt;li&gt;Beclometasone 200 &lt;em&gt;micro&lt;/em&gt;-grams (&lt;em&gt;Fostair 200&lt;/em&gt;, pink)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;ve been on the Fostair 200 for over a year now, in conjunction with another corticosteroid called Ciclesonide.&lt;/p&gt;
&lt;p&gt;Now because my blood tests show high levels of &lt;em&gt;eosinophils&lt;/em&gt; the assumption is that I&apos;m allergic to something, so I pair those with the following tablets to try and tamp down those naughty cells in my body which are flaring up and causing constriction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1x montelukast 10mg&lt;/li&gt;
&lt;li&gt;2x theophylline 200mg (&lt;em&gt;Uniphyllin&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, I&apos;ve also had a spell on Spiriva Respimat – often given to COPD patients - which delivers 3 micrograms of tiotropium bromide monohydrate. I tend to be the youngest in the clinic waiting room when I visit the consultant. From &lt;a href=&quot;https://www.coventrywarksapc.nhs.uk/mf.ashx?ID=c52e4489-fdb1-4606-820c-be9e236bc06a&quot;&gt;this NHS worksheet&lt;/a&gt;, I&apos;m at the &quot;Seek specialist advice&quot; stage of progression.&lt;/p&gt;
&lt;p&gt;I don&apos;t particularly wish to be taking steroids for any longer than necessary. Because of this constant barrage of steroids, I suffer from oral thrush (yum yum), and my voice has changed in tone. I get frequent upper-respiratory infections, and each morning I get to hock up my lungs like a 20-a-day smoker. I&apos;ve had several doses of an oral steroid and antibiotics, but was one course shy of being invited to another clinic to take an injected medicine.&lt;/p&gt;
&lt;p&gt;What really gets my goat is how it affects my ability to exercise: I can be working and breathing hard, but as soon as an interval ends and my body relaxes – BANG: here comes the constriction. Classic exercise-induced bronchitis symptoms.&lt;/p&gt;
&lt;p&gt;While I know I this is still a case of extreme privilege, I would love to discover a route out because a lot of my self-worth was tied up in running.&lt;/p&gt;
</content:encoded></item><item><title>Weeknotes: 2020-10-25</title><link>https://danmatthew.co.uk/notes/2020-10-25-weeknotes-october-25/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-10-25-weeknotes-october-25/</guid><pubDate>Sun, 25 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m super consistent with writing these, eh?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&apos;s been a glut of televised cycling with the condensed racing calendar, so we&apos;ve had the Ronde van Vlaanderen, the climax of the Giro d&apos;Italia, and the start of La Vuelta in the space of the past week.&lt;/li&gt;
&lt;li&gt;That helps, because I&apos;ve been feeling rather sorry for myself when it comes to exercise. I&apos;ve been suffering from &quot;something&quot; for nigh-on a month. Whatever it is, it&apos;s taking a long time to kick and is making activity difficult.&lt;/li&gt;
&lt;li&gt;Really enjoyed reading &lt;a href=&quot;https://www.goodreads.com/book/show/54501445-mismatch&quot;&gt;Kat Holmes&apos; &lt;em&gt;Mismatch&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Finished watching &lt;a href=&quot;https://www.netflix.com/title/81237854&quot;&gt;The Haunting of Bly Manor on Netflix&lt;/a&gt;. Not as creepy as Hill House.&lt;/li&gt;
&lt;li&gt;It&apos;s been a week for Australian film: watched Justin Kurzel&apos;s adapatation of &lt;em&gt;The True History of the Ned Kelly gang&lt;/em&gt;, and Jennifer Kent&apos;s &lt;em&gt;The Nightingale&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Creating Github Releases With Lerna</title><link>https://danmatthew.co.uk/notes/2020-08-01-lerna-github-releases-circleci/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-08-01-lerna-github-releases-circleci/</guid><pubDate>Sat, 01 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Reducing the number of manual steps needed to get code live is a good thing. This is how I create Github releases from the CI process.&lt;/p&gt;
&lt;h2&gt;Lerna&lt;/h2&gt;
&lt;p&gt;Lerna is a tool to manage a monorepo. It can automate releases on Github when the version of a package changes, which is one less task to perform manually.&lt;/p&gt;
&lt;h2&gt;Circle CI&lt;/h2&gt;
&lt;p&gt;Circle is a continuous integration solution. In this scenario, Circle is configured to run the test suite for each component after a commit. Once the tests pass, Lerna will increment the version number of the component, using the &lt;a href=&quot;https://www.conventionalcommits.org/en/v1.0.0/&quot;&gt;Conventional Commits specification&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Creating a release&lt;/h2&gt;
&lt;h3&gt;Circle Config&lt;/h3&gt;
&lt;p&gt;Here is a workflow definition with two discrete jobs. The first runs the tests; the second runs &lt;code&gt;lerna version&lt;/code&gt; against the desired components.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;version: 2.1
orbs:
  node: circleci/node@1.1.6
jobs:
  build-and-test:
    executor:
      name: node/default
    docker:
      - image: circleci/node:latest-browsers
    resource_class: small
    steps:
      - checkout
      - node/with-cache:
          steps:
            - run: npm install
            - run: npm test

release:
    docker:
      - image: circleci/node
    resource_class: small
    steps:
      - checkout
      - node/with-cache:
          steps:
            - add_ssh_keys:
                fingerprints:
                  - &quot;F1:NG:3R:PR:1N:T&quot;
            - run: npx lerna bootstrap --hoist --ci
            - run: npx lerna version --no-private --conventional-commits --create-release github --yes

workflows:
    build-and-test:
      jobs:
        - build-and-test
        - release:
            filters:
              branches:
                only: main
            requires:
              - build-and-test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All the interesting work is contained within this instruction:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx lerna version --no-private --conventional-commits --create-release github --yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lerna will increment the version of public packages using the Conventional Commits spec, before creating a Github release, and it won&apos;t need any prompting to do so.&lt;/p&gt;
&lt;h3&gt;Creating a deploy key&lt;/h3&gt;
&lt;p&gt;In order to modify the project repository, Circle will need an SSH key with write access: a &quot;deploy key&quot;. The public key is added from the project&apos;s &lt;code&gt;settings/keys&lt;/code&gt; screen on Github; the private half is added to Circle via Project Settings -&amp;gt; SSH Keys. You&apos;ll know if you got it right, because you&apos;ll avoid the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lerna ERR! lerna ERROR: The key you are authenticating with has been marked as read only.
lerna ERR! lerna fatal: Could not read from remote repository.
lerna ERR! lerna
lerna ERR! lerna Please make sure you have the correct access rights
lerna ERR! lerna and the repository exists.
lerna ERR! lerna
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Adding an access token&lt;/h3&gt;
&lt;p&gt;While the machine might be authenticated, Lerna will need to identify itself as working with the correct permissions. Thus the addition of &lt;code&gt;GH_TOKEN&lt;/code&gt; available to it. A new access token can be created from within &lt;a href=&quot;https://github.com/settings/tokens/&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Publishing the release&lt;/h2&gt;
&lt;p&gt;When a build goes green on the main branch, a &lt;a href=&quot;https://github.com/danielmatthew/accessible-web-components/releases&quot;&gt;new release will appear automatically on Github&lt;/a&gt;. The release notes will be filled automatically, and the changelog for each package will have been updated at the same time. There does appear to be a slight bug with the version number. My understanding is that &lt;code&gt;fix&lt;/code&gt; commits will increment the patch number when using semantic versioning, but the component has increased from &lt;code&gt;0.2.0&lt;/code&gt; to &lt;code&gt;0.2.1&lt;/code&gt; with a single &lt;code&gt;chore&lt;/code&gt; commit…&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;Lerna&apos;s &lt;code&gt;publish&lt;/code&gt; command works the same as &lt;code&gt;version&lt;/code&gt;, but automates publishing to NPM.&lt;/p&gt;
</content:encoded></item><item><title>Weeknotes: 2020-08-01</title><link>https://danmatthew.co.uk/notes/2020-08-01-weeknotes/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-08-01-weeknotes/</guid><pubDate>Sat, 01 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;I spent a day off watching a series of talks from &lt;a href=&quot;https://www.youtube.com/c/JAMstackConf&quot;&gt;JAMstack Conf&lt;/a&gt;, before getting wet and wild out on the bike: that was not a pleasurable experience.&lt;/li&gt;
&lt;li&gt;This week I have been getting to grips with Figma. DesignLab&apos;s &lt;a href=&quot;https://trydesignlab.com/figma-101-course/introduction-to-figma/&quot;&gt;Introduction to Figma&lt;/a&gt;, alongside &lt;a href=&quot;https://www.youtube.com/watch?v=p0H4NW5ILto&quot;&gt;Sketch Together&apos;s video content&lt;/a&gt; have been useful.&lt;/li&gt;
&lt;li&gt;This resulted in the illustration at the beginning of the page, inspired by &lt;a href=&quot;https://www.risd.edu&quot;&gt;RISD&apos;s&lt;/a&gt; work for the 2006 Winter Olympics. I wanted to play with animation, and SVG will make that easier to achieve.&lt;/li&gt;
&lt;li&gt;At Talis, we&apos;ve been working hard to improve the interactive states of our interface elements &lt;a href=&quot;https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast&quot;&gt;to correct issues with contrast&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I played my first-ever game of Fortnite on Switch, and took the Victory Royale. I think I&apos;ve peaked for 2020.&lt;/li&gt;
&lt;li&gt;Rode RLSCC&apos;s bash again this week and beat last week&apos;s time by a couple of minutes. I&apos;ve started adding some run training back into the schedule to maintain that fitness.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>CircleCI Node Images with Browsers</title><link>https://danmatthew.co.uk/notes/circle-ci-node-browsers/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/circle-ci-node-browsers/</guid><pubDate>Mon, 27 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Building a Node project with Circle and want access to browser binaries? The default &lt;code&gt;circleci/node&lt;/code&gt; image doesn&apos;t come with them installed, which threw a spanner in the works when attempting to run some tests. Circle maintain an exhaustive list of images one can use: any Node version appended with &lt;code&gt;-browsers&lt;/code&gt; will come installed with Chrome, Firefox, OpenJDK v11, and Geckodriver.&lt;/p&gt;
</content:encoded></item><item><title>Using continuous integration to build, test, and publish with Netlify</title><link>https://danmatthew.co.uk/notes/2020-07-26-continuous-integration-build-publish-netlify/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-07-26-continuous-integration-build-publish-netlify/</guid><pubDate>Sun, 26 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week, Chris Coyier &lt;a href=&quot;https://css-tricks.com/develop-preview-test/&quot;&gt;published a post on CSS Tricks which covered an approach to the simplest of testing set-ups&lt;/a&gt;: ensuring the website loads and displays some content. A &quot;smoke test&quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just one super basic integration goes a long way. If your site spins up, returns a page, and renders stuff on it that you expect, a lot is going right.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&apos;ve been meaning to add some level of test coverage to this website for a while now. I&apos;d been wanting to run builds against Lighthouse CI to ensure that anything that breaks the performance budget or fails one of the automated accessibility tests doesn&apos;t make it into production.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://docs.cypress.io/guides/getting-started/writing-your-first-test.html#Step-1-Visit-a-page&quot;&gt;some well-written documentation&lt;/a&gt;, it was easy to get Cypress installed and configured to test against my local development server.&lt;/p&gt;
&lt;h2&gt;The test&lt;/h2&gt;
&lt;p&gt;Per the docs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;reference types=&quot;Cypress&quot; /&amp;gt;

describe(&apos;Home page&apos;, () =&amp;gt; {
  it(&apos;successfully loads&apos;, () =&amp;gt; {
    cy.visit(&apos;/&apos;);

    cy.get(&apos;h1&apos;).should(&apos;contain&apos;, &apos;Dan Matthew&apos;);
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cypress will look for a configuration file in the directory, and it&apos;s in this &lt;code&gt;cypress.json&lt;/code&gt; where a &lt;code&gt;baseUrl&lt;/code&gt; can be defined:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;baseUrl&quot;: &quot;http://localhost:8080&quot;,
  &quot;ignoreTestFiles&quot;: &quot;cypress/integration/examples/*.js&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each call to &lt;code&gt;.visit()&lt;/code&gt; will use the &lt;code&gt;baseUrl&lt;/code&gt; as its root. While it&apos;s set to &lt;code&gt;localhost&lt;/code&gt; here, we&apos;ll want to change it later on, for reasons that will become apparent.&lt;/p&gt;
&lt;h2&gt;Testing against a local web server&lt;/h2&gt;
&lt;p&gt;Netlify expects tests to be run elsewhere, since every commit to the linked VCS causes a build and publish. I&apos;d &lt;a href=&quot;/notes/deploying-with-travis/&quot;&gt;used Travis CI previously&lt;/a&gt;, so thought I&apos;d pick up where I left off. I wanted it to operate like my local development environment, where I&apos;d run &lt;code&gt;npx eleventy serve&lt;/code&gt; and then spawn Cypress in the background: &lt;code&gt;npm run serve:ci &amp;amp;&amp;amp; npm test&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This &lt;a href=&quot;https://travis-ci.com/github/danielmatthew/website/builds/176151683&quot;&gt;did not work as anticipated&lt;/a&gt;. &lt;code&gt;serve&lt;/code&gt; was never going to end, and Cypress was never going to be started 😂. The Cypress docs even warned against this, and do &lt;a href=&quot;https://docs.cypress.io/guides/guides/continuous-integration.html#Solutions&quot;&gt;cover a number of solutions&lt;/a&gt;, but pig-headedly I didn&apos;t want to install yet another package.&lt;/p&gt;
&lt;p&gt;Time to rethink.&lt;/p&gt;
&lt;h2&gt;Building a Deploy Preview with the Netlify CLI&lt;/h2&gt;
&lt;p&gt;With Netlify in control of builds, I&apos;d configured it to use a couple of &lt;a href=&quot;https://docs.netlify.com/configure-builds/build-plugins/&quot;&gt;Build Plugins&lt;/a&gt;. I didn&apos;t realise that these can be installed locally as devDependencies and they&apos;ll operate on the generated site just as they do on live. This meant using the CLI became a plausible alternative – just as soon as automatic builds were turned off.&lt;/p&gt;
&lt;p&gt;This setting can be found at https://app.netlify.com/sites/{YOUR_SITE_NAME}/settings/deploys. Look for &quot;Build Settings&quot;, and then &quot;Stop builds&quot;. The following warning is displayed:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Netlify will never build your site. You can build locally via the CLI and then publish new deploys manually via the CLI or the API.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now the onus is on the developer 😬. In this case, we&apos;ll get Travis to perform this task for us. With the simplest of configurations each commit will build the site, but only those pushed to &lt;code&gt;main&lt;/code&gt; will trigger a deploy:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: node_js
node_js:
  - &quot;node&quot;
cache: npm
script:
  - npx netlify build
deploy:
  cleanup: false
  provider: script
  script: npx netlify deploy
  on:
    branch: main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The boffins out there will know that this implementation is naive: it doesn&apos;t run any tests; and it&apos;s going to give me a green build each time, which is nice for the ego, less so for confirming that the site renders. That &lt;code&gt;build&lt;/code&gt; script might have only succeeded in pumping out a broken site if something&apos;s gone screwy in development.&lt;/p&gt;
&lt;h2&gt;Testing a Deploy Preview with Cypress&lt;/h2&gt;
&lt;p&gt;One of the neat things about Netlify is that each branch will get built and published with a unique URL. This makes it easy to visit the preview in a browser and ensure it works as expected. How can we access that URL and provide it to Cypress?&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://cli.netlify.com/commands/deploy&quot;&gt;documentation for &lt;code&gt;deploy&lt;/code&gt;&lt;/a&gt; offers a hint:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;alias (option) - Specifies the alias for deployment. Useful for creating predictable deployment URL&apos;s&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Very useful indeed, Netlify. But what to use as our alias? I don&apos;t know how long branch deploys exist, so it didn&apos;t seem sensible to use a hard-coded string. It turns out that Travis surfaces a number of environment variables: I opted for &lt;code&gt;$TRAVIS_JOB_ID&lt;/code&gt; because it seemed like it&apos;s probably going to be unique…&lt;/p&gt;
&lt;p&gt;First off however, the branch build is going to have to be deployed: &lt;code&gt;npx netlify deploy --alias $TRAVIS_JOB_ID&lt;/code&gt;. Then Cypress is invoked: &lt;code&gt;npx cypress run --env host=$TRAVIS_JOB_ID--danmatthew.netlify.app --spec \&quot;cypress/integration/home_page.spec.js\&quot; --headless&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--env&lt;/code&gt; flag in the &lt;code&gt;cypress run&lt;/code&gt; command overrides the &lt;code&gt;baseUrl&lt;/code&gt; from &lt;code&gt;cypress.json&lt;/code&gt; and ensures we are testing the latest deploy.&lt;/p&gt;
&lt;p&gt;In the logs of previous builds I&apos;d seen:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If everything looks good on your draft URL, deploy it to your main site URL with the --prod flag.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alrighty, then!&lt;/p&gt;
&lt;p&gt;🚨 Uh-oh. Cypress crashed: &lt;a href=&quot;https://github.com/cypress-io/cypress/issues/3957&quot;&gt;apparently the spec flag doesn&apos;t play nicely with CI environments&lt;/a&gt;. Ah well, don&apos;t have to worry about running all the tests if there&apos;s only one test…&lt;/p&gt;
&lt;p&gt;With that resolved, the build failed again. &lt;code&gt;--env host&lt;/code&gt; is completely the wrong flag, and to set the baseUrl from the environment is done thusly:
&lt;code&gt;CYPRESS_BASE_URL=https://$TRAVIS_JOB_ID--danmatthew.netlify.app npx cypress run --headless --config-file false&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With that done, our config looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;os: linux
dist: xenial
language: node_js
node_js:
  - &quot;node&quot;
cache:
  npm: true
  directories:
    - ~/.cache
script:
  - npx netlify build
  - npx netlify deploy --alias $TRAVIS_JOB_ID
  - CYPRESS_BASE_URL=https://$TRAVIS_JOB_ID--danmatthew.netlify.app npx cypress run --headless --config-file false
deploy:
  cleanup: false
  provider: script
  script: npx netlify deploy --prod
  on:
    branch: main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…and we get a succesful build.&lt;/p&gt;
&lt;h2&gt;Use the Netlify provider, stupid&lt;/h2&gt;
&lt;p&gt;There&apos;s me, using multiple steps under the &lt;code&gt;script&lt;/code&gt; phase, when Travis provides its own deploy step for Netlify projects.&lt;/p&gt;
&lt;p&gt;Perhaps the &lt;a href=&quot;https://docs.travis-ci.com/user/deployment-v2/#supported-providers&quot;&gt;documentation needs to be clearer&lt;/a&gt; because it references &lt;a href=&quot;https://app.netlify.com/drop&quot;&gt;Netlify Drop&lt;/a&gt;, which at first glance looks like a different mechanism entirely. When I looked closer at the required arguments, I realised they were identical to the CLI commands I was using earlier.&lt;/p&gt;
&lt;p&gt;Using the provider means the deploy stage of our &lt;code&gt;travis.yml&lt;/code&gt; takes this form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deploy:
  cleanup: false
  provider: netlify
  site: $NETLIFY_SITE_ID
  auth: $NETLIFY_AUTH_TOKEN
  prod: true
  edge: true
  on:
    branch: main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There we go: we&apos;ve got a CI tool taking care of testing our builds. If the tests pass, the site will be set live. If not, we can go visit the deploy preview and see what&apos;s gone wrong.&lt;/p&gt;
&lt;h2&gt;Bonus: Automating Github releases&lt;/h2&gt;
&lt;p&gt;Doing this isn&apos;t strictly necessary, but I wanted to play with the &lt;a href=&quot;https://semantic-release.gitbook.io/semantic-release/&quot;&gt;semantic-release&lt;/a&gt; package and see what it could do. I had intended to incorporate it into the Accessible Web Components project, but I discovered Lerna could perform both actions for me, which rendered it superfluous.&lt;/p&gt;
&lt;p&gt;To &lt;a href=&quot;https://github.com/danielmatthew/website/releases&quot;&gt;publish a new release on Github&lt;/a&gt;, we can add a &lt;code&gt;run&lt;/code&gt; property to the deploy stage, or make it a little more obvious with the &lt;code&gt;after_deploy&lt;/code&gt; stage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if tag IS blank
after_deploy:
  - npx semantic-release
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The conditional there is to prevent yet another build when semantic-release creates the tag. It took me a while to figure out why I was seeing three builds…&lt;/p&gt;
&lt;p&gt;Like many other tools, semantic-release supports many configuration options. In this case, I didn&apos;t want the package being pushed to npm, so it was necessary to override the default plugins with the following in my &lt;code&gt;releaserc&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;branches&quot;: &quot;main&quot;,
  &quot;plugins&quot;: [
    &quot;@semantic-release/commit-analyzer&quot;,
    &quot;@semantic-release/release-notes-generator&quot;,
    &quot;@semantic-release/github&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Accessible Web Components: Tabs</title><link>https://danmatthew.co.uk/notes/2020-07-12-accessible-web-components-tabs/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-07-12-accessible-web-components-tabs/</guid><pubDate>Sun, 12 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;The web component&lt;/h2&gt;
&lt;p&gt;I&apos;ve finally published my first NPM package: a &lt;a href=&quot;https://www.npmjs.com/package/@accessible-web-components/tabs&quot;&gt;web component to represent a tabbed interface&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://v505e.csb.app&quot;&gt;View the demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rock and roll.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It might not be the most fashionable of side projects - or technologies - but I felt that a wrapping up the desired behaviour of a tabbed interface into a bog-standard web component might do some good. If it saves another developer spending an afternoon doing the same thing, or makes the life of the user a little easier, then I&apos;d consider that worthwhile.&lt;/p&gt;
&lt;p&gt;The component follows the behaviours specified in the &lt;a href=&quot;https://www.w3.org/TR/wai-aria-practices-1.2/#tabpanel&quot;&gt;WAI-ARIA Authoring Practices document&lt;/a&gt;. It can be styled with CSS to suit its environment, and will display as a single column should there be a hitch. Alas, web components &lt;em&gt;do&lt;/em&gt; require JavaScript in order to be registered, and it certainly requires JS in order to enhance the markup with the required ARIA attributes.&lt;/p&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;h4&gt;JavaScript&lt;/h4&gt;
&lt;p&gt;Import the three components, and tell the browser about them:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { AwcTabs, AwcTab, AwcPanel } from &quot;@accessible-web-components/tabs&quot;;

window.customElements.define(&quot;awc-tabs&quot;, AwcTabs);
window.customElements.define(&quot;awc-tab&quot;, AwcTab);
window.customElements.define(&quot;awc-panel&quot;, AwcPanel);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;HTML&lt;/h4&gt;
&lt;p&gt;It takes the following structure.  Add as many tabs and panels as are required.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;awc-tabs&amp;gt;
  &amp;lt;awc-tab role=&quot;heading&quot; slot=&quot;tab&quot;&amp;gt;Tab 1&amp;lt;/awc-tab&amp;gt;
  &amp;lt;awc-panel role=&quot;region&quot; slot=&quot;panel&quot;&amp;gt;
    &amp;lt;h2&amp;gt;My first tab&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;Here is some text…&amp;lt;/p&amp;gt;
    &amp;lt;ul&amp;gt;
      &amp;lt;li&amp;gt;…and a list&amp;lt;/p&amp;gt;
    &amp;lt;/ul&amp;gt;

    &amp;lt;button type=&quot;button&quot;&amp;gt;I am a focusable element within the tab&amp;lt;/button&amp;gt;
  &amp;lt;/awc-panel&amp;gt;
  &amp;lt;awc-tab role=&quot;heading&quot; slot=&quot;tab&quot;&amp;gt;Tab 2&amp;lt;/awc-tab&amp;gt;
  &amp;lt;awc-panel role=&quot;region&quot; slot=&quot;panel&quot;&amp;gt;Content 2&amp;lt;/awc-panel&amp;gt;
  &amp;lt;awc-tab role=&quot;heading&quot; slot=&quot;tab&quot;&amp;gt;Tab 3&amp;lt;/awc-tab&amp;gt;
  &amp;lt;awc-panel role=&quot;region&quot; slot=&quot;panel&quot;&amp;gt;Content 3&amp;lt;/awc-panel&amp;gt;
&amp;lt;/awc-tabs&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To the 67 brave souls who have downloaded it since yesterday morning: &lt;s&gt;you are brave&lt;/s&gt; thanks &lt;s&gt;for being my guinea pigs&lt;/s&gt;!. I&apos;ve put the package level as a pre-release, at &lt;code&gt;0.0.0-alpha.3&lt;/code&gt;. I don&apos;t think it&apos;s going to break your project, but there are a few more features I want to include before it goes to &lt;code&gt;0.0.1&lt;/code&gt;. I guess it would help if I wrote some tests, and I can certainly improve the documentation.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Side projects, eh? Gotta love &apos;em.&lt;/p&gt;
&lt;p&gt;Four years ago, I made the first commit in a Github repository called &lt;a href=&quot;https://github.com/danielmatthew/accessible-web-components/commit/3c7089a62c9459f7be782ca4a0985f54ef0b330e&quot;&gt;Accessible Web Components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following year, in March 2017, I gave a &lt;a href=&quot;https://pusher.com/sessions/meetup/hydrahack/web-components-and-me&quot;&gt;talk at HydraHack&lt;/a&gt; about my plan to create a whole series of components. As a fellow speaker that night, I&apos;m hopeful &lt;a href=&quot;https://twitter.com/nivims&quot;&gt;Nivi&apos;s&lt;/a&gt; offer of feedback still stands!&lt;/p&gt;
&lt;p&gt;The first component – &lt;a href=&quot;https://www.w3.org/TR/wai-aria-practices-1.2/#alert&quot;&gt;an alert message&lt;/a&gt; – was the &quot;Hello world!&quot; I used to play with various frameworks. It moved across Polymer, Polymer v2, Stencil, a custom element, Vue, and finally LitElement. The &lt;a href=&quot;https://github.com/danielmatthew/accessible-web-components/tree/master/alert&quot;&gt;Polymer version still lives in the repository&lt;/a&gt;, complete with its use of &lt;a href=&quot;https://www.w3.org/TR/html-imports/&quot;&gt;HTML Imports&lt;/a&gt;. It&apos;s a shame that particular spec got shot down: it feels awkward defining component templates inside the JavaScript.&lt;/p&gt;
&lt;p&gt;Then, with the plan to create a whole series of these components, I thought a monorepo would be a good idea. I installed &lt;a href=&quot;https://github.com/lerna/lerna/&quot;&gt;Lerna&lt;/a&gt;, and spent way too much time getting its configuration &lt;em&gt;just&lt;/em&gt; so.&lt;/p&gt;
&lt;p&gt;With Lerna just about sussed, I turned to the guidelines suggested by the &lt;a href=&quot;https://open-wc.org/index.html&quot;&gt;open-wc&lt;/a&gt; project when it comes to publishing. I&apos;ve been using their linting and commit standards for some time, but the project has really been evolving: I&apos;ve used their generator to scaffold the next component in the series.&lt;/p&gt;
&lt;p&gt;Finally, it was time to publish. Again, it took too long figuring out how to create an organisation on NPM, such that the package name could be in the format: &lt;code&gt;@accessible-web-components/&amp;lt;blah&amp;gt;&lt;/code&gt;. While it sounds trivial, I thought it worth keeping this and future components grouped together right from the start.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Despite it being a fairly trivial piece of software, I&apos;m excited yet nervous at the thought of third parties using something I&apos;ve written. I&apos;m looking forward to constructive criticism to help shape it and make the web a richer, and more accessible platform.&lt;/p&gt;
</content:encoded></item><item><title>Goodbye Gatsby; Hello Eleventy!</title><link>https://danmatthew.co.uk/notes/2020-07-05-goodbye-gatsby-hello-eleventy/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2020-07-05-goodbye-gatsby-hello-eleventy/</guid><pubDate>Sun, 05 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello there! It&apos;s been a good while since anything new content has appeared on this website, and while I&apos;ve tinkered with the splash page on occasion, it&apos;s not displayed anything more than my name in a &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Some thoughts on &apos;v3&apos;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&apos;ve gotten rid of &lt;a href=&quot;https://www.gatsbyjs.org&quot;&gt;Gatsby&lt;/a&gt;. It wasn&apos;t long after I upgraded to v2 that I noticed the site no longer rendered if JS was disabled; something I had appreciated in v1.&lt;/li&gt;
&lt;li&gt;The site now runs on &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt;, and uses &lt;a href=&quot;https://twitter.com/hankchizljaw&quot;&gt;Andy Bell&apos;s&lt;/a&gt; &lt;a href=&quot;https://hylia.website&quot;&gt;Hylia Starter Kit&lt;/a&gt; to get me going. I expect to be hacking away at it over the next week.&lt;/li&gt;
&lt;li&gt;I wanted to place to display my photos. Yes, I know there&apos;s only a single photo being displayed. It&apos;s a shot of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Molino_Stucky&quot;&gt;Molino Stucky&lt;/a&gt; in Venice. I&apos;m using &lt;a href=&quot;https://cloudinary.com&quot;&gt;Cloudinary&lt;/a&gt; to host the image and apply transforms based on device DPI, orientation, and screen width.&lt;/li&gt;
&lt;li&gt;I want the site to feel fast. It&apos;s preconnecting to third-party origins (Cloudinary, Google Fonts, Speedcurve), and preloading the most important assets. I&apos;m inlining the first blast of CSS, then &lt;a href=&quot;https://www.filamentgroup.com/lab/load-css-simpler/&quot;&gt;loading the rest asynchronously&lt;/a&gt;. &lt;a href=&quot;https://www.webpagetest.org/result/200703_BQ_692dc3c1922a505eb90b3a3ca14c76a0/1/details/#waterfall_view_step1&quot;&gt;Benchmarking the site on Web Page Test&lt;/a&gt;, it surprised me &lt;a href=&quot;https://www.webpagetest.org/result/200703_23_f52e3ba3fbeae8474b248fe75200090d/1/details/#waterfall_view_step1&quot;&gt;how much slower the site performed when this wasn&apos;t done&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Speedcurve was mentioned above. Thought I&apos;d have a play and see how the site performs over time. Additionally, I only just found out that one doesn&apos;t need to use Chrome to play with Lighthouse: &lt;a href=&quot;https://adactio.com/journal/16523&quot;&gt;Jeremy Keith&lt;/a&gt; put together a bookmarklet to send the current document over to the &lt;a href=&quot;https://googlechrome.github.io/lighthouse/viewer/&quot;&gt;Lighthouse viewer&lt;/a&gt;. In the same vein, &lt;a href=&quot;https://lighthouse-metrics.com&quot;&gt;Lighthouse Metrics&lt;/a&gt; seems a neat way to keep tabs on performance.&lt;/li&gt;
&lt;li&gt;I want to begin publishing accessibility audits of some of my favourite sites. At &lt;a href=&quot;https://talis.com&quot;&gt;Talis&lt;/a&gt;, I&apos;ve been spending a good chunk of time reviewing and improving the accessibility of our products ahead of September&apos;s &amp;lt;abbr title=&quot;The Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018&quot;&amp;gt;&lt;a href=&quot;http://www.legislation.gov.uk/uksi/2018/952/contents/made&quot;&gt;PSBAR&lt;/a&gt;&amp;lt;/abbr&amp;gt; deadline. While I&apos;ve been championing accessibility internally since I started, it has felt like a struggle to get cross-functional buy-in until recently.&lt;/li&gt;
&lt;li&gt;When not working on improving our accessibility, the recent focus has been on relaunching our website. I am extremely grateful for &lt;a href=&quot;http://timber.github.io&quot;&gt;Timber&lt;/a&gt;, which made working with WordPress a much more pleasurable experience. Something that irks me is that I tried hard to keep the site snappy, but as third-party plugins have been enabled to support desired functionality - &quot;buy, don&apos;t build&quot; is the mantra - more and more external resources get pulled in. Even the WordPress core functionality dumps a load of crap in, which has to be manually disabled via the theme&apos;s &lt;code&gt;functions.php&lt;/code&gt;. &lt;em&gt;Le sigh.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Preload, Prefetch, and Preconnect</title><link>https://danmatthew.co.uk/notes/2017-12-09-preload-prefetch-preconnect/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2017-12-09-preload-prefetch-preconnect/</guid><pubDate>Sat, 09 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Working on a Polymer project recently, I got to experiment with serving the content from Firebase Hosting, which now &lt;a href=&quot;https://firebase.googleblog.com/2016/09/http2-comes-to-firebase-hosting.html&quot;&gt;offers support for HTTP/2 and Server Push&lt;/a&gt;. Server Push allows content to be delivered speculatively: content is delivered whether or not the user has it already, and in some cases it might not be required at all.&lt;/p&gt;
&lt;h2&gt;Preload&lt;/h2&gt;
&lt;p&gt;To take advantage of this ability though, I needed to declare the assets I wanted to be pushed down. In my &lt;code&gt;firebase.json&lt;/code&gt; file I declared:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;headers&quot;: [{
  &quot;key&quot;: &quot;Link&quot;,
  &quot;value&quot;: &quot;&amp;lt;my-app.js&amp;gt;;rel=preload;as=script&quot;
}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which instructed Firebase to serve the file with the appropriate &lt;code&gt;Link&lt;/code&gt; header. It&apos;s possible to do the same when referencing resources via a &lt;a href=&quot;https://html.spec.whatwg.org/multipage/links.html#external-resource-link&quot;&gt;&lt;code&gt;link&lt;/code&gt;&lt;/a&gt; element too:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&quot;preload&quot; href=&quot;foo.js&quot; as=&quot;script&quot;&amp;gt;
&amp;lt;link rel=&quot;preload&quot; href=&quot;bar.css&quot; as=&quot;style&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you inspect this site, you&apos;ll see that Gatsby does this for me in production. Coupled with HTTP/2 on Cloudfront, visitors should experience a fairly snappy load. Essentially, all assets for a page are transferred in a single round trip, though it does mean if you&apos;re a repeat visitor (hi mum!), I&apos;m probably using bandwidth unneccessarily. &lt;a href=&quot;https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf&quot;&gt;Addy Osmani&lt;/a&gt; suggests that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use Push when you know the precise loading order for resources and have a service worker to intercept requests that would cause cached resources to be pushed again.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I guess that&apos;s next on my to-do list with &lt;a href=&quot;https://github.com/GoogleChrome/workbox&quot;&gt;Workbox&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Prefetch&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;link rel=&quot;prefetch&quot; href=&quot;/font.woff2&quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Prefetch is another resource hint developers can take advantage of. Prefetch tells the browser that a resource will be needed on the next page, or navigation. Resources marked as such will be treated as a much lower-priority fetch than those with &lt;code&gt;preload&lt;/code&gt;, and it&apos;s up to the browser to make the call as to whether it will load it or not. I&apos;ve seen a pattern where a webfont is set to be pre-fetched so that it doesn&apos;t block rendering on the first load, but is available right away when a visitor navigates to a new page.&lt;/p&gt;
&lt;h2&gt;Preconnect&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;link rel=&quot;preconnect&quot; href=&quot;/page2&quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Preconnect can be used to &apos;warm-up&apos; the connection to a resource in order to &lt;a href=&quot;https://www.igvita.com/2015/08/17/eliminating-roundtrips-with-preconnect/&quot;&gt;&quot;eliminate the costly DNS, TCP, and TLS roundtrips from the critical path of the actual request&quot;&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;All of these techniques can be used in an attempt to improve the performance of your site but it&apos;s a trade-off between second-guessing the behaviour of your guests, while not exhausting their bandwidth unneccessarily – especially for those on metered connections.&lt;/p&gt;
&lt;h3&gt;Sources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;https://caniuse.com/#search=pre&lt;/li&gt;
&lt;li&gt;https://www.w3.org/TR/resource-hints/&lt;/li&gt;
&lt;li&gt;https://www.w3.org/TR/preload/&lt;/li&gt;
&lt;li&gt;https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf&lt;/li&gt;
&lt;li&gt;https://css-tricks.com/prefetching-preloading-prebrowsing/&lt;/li&gt;
&lt;li&gt;https://blog.cloudflare.com/announcing-support-for-http-2-server-push-2/&lt;/li&gt;
&lt;li&gt;https://firebase.googleblog.com/2016/09/http2-comes-to-firebase-hosting.html&lt;/li&gt;
&lt;li&gt;http://www.bramstein.com/writing/preload-hints-for-web-fonts.html&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Automating the Build Process with Travis-CI</title><link>https://danmatthew.co.uk/notes/2017-11-20-deploying-with-travis/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2017-11-20-deploying-with-travis/</guid><pubDate>Mon, 20 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Updated 9th December to illustrate latest iteration of Travis.yml&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before I ported this site over to &lt;a href=&quot;https://www.gatsbyjs.org&quot;&gt;Gatsby&lt;/a&gt;, it was powered by good old &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;Jekyll&lt;/a&gt;. I&apos;d make an edit, run &lt;code&gt;jekyll build&lt;/code&gt;, then push the output to S3 with &lt;a href=&quot;https://github.com/laurilehmijoki/s3_website&quot;&gt;&lt;code&gt;s3_website&lt;/code&gt;&lt;/a&gt;. Not exactly onerous, but I noticed that I&apos;d be drafting posts, or updating the structure of the site and then not pushing them live in a timely manner. &lt;em&gt;(And what do you know, it&apos;s happened again! – Ed., December 2nd)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cue a Continuous Integration (CI) solution – although it took me many attempts to get it right. And by right, I mean it at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;builds the site&lt;/li&gt;
&lt;li&gt;deploys to S3&lt;/li&gt;
&lt;li&gt;invalidates the CloudFront distribution.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Attempt #1: Use the default S3 provider&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.travis-ci.com&quot;&gt;Travis&apos;&lt;/a&gt; documentation is pretty, pretty, pretty good. I think you could just about get away with this, if you&apos;re happy to serve straight from the S3 bucket:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: node_js
node_js:
 - &quot;8&quot;
script:
 - yarn build
deploy:
  provider: s3
  access_key_id: $AWS_ACCESS_KEY_ID
  secret_access_key: $AWS_SECRET_ACCESS_KEY
  bucket: danmatthew.co.uk
  region: $AWS_DEFAULT_REGION
  # Prevent Travis from deleting your built site so it can be uploaded.
  skip_cleanup: true
  # Path to a directory containing your built site.
  local_dir: public
  on:
    branch: master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because I have both &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt; in my repository, Travis is smart enough to figure I want to use Yarn to run during the &lt;code&gt;install&lt;/code&gt; phase.&lt;/p&gt;
&lt;p&gt;I like this implementation, but Travis is only concerned with S3 here. I have a Cloudfront distribution sat in front of this bucket in the hope of saving a few pence and making the site feel snappy. Sure, I could manually log in to AWS and invalidate the distribution or do it via the command line, but y&apos;know: let&apos;s automate it.&lt;/p&gt;
&lt;h2&gt;Attempt #2: Use AWS CLI to invalidate the Cloudfront distribution&lt;/h2&gt;
&lt;p&gt;This is where it feels messy, and there are a bunch of extra steps to mess up. AWS CLI is installed via Pip, so this implementation needs to be driven by Python.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: python
python: 3.6
sudo: required
dist: trusty
env:
 - TRAVIS_NODE_VERSION=&quot;8&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I had to explicitly specify the version of Python, because the default appeared to be 2.4 and I ran into issues… Java-related, &lt;em&gt;possibly?&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is where it starts to be a blend of different tasks, and I&apos;m piecing together instructions from various sources.&lt;/p&gt;
&lt;h3&gt;Install Yarn&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;before_install:
  - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
  - echo &quot;deb https://dl.yarnpkg.com/debian/ stable main&quot; | sudo tee /etc/apt/sources.list.d/yarn.list
  - sudo apt-get -qq update
  - sudo apt-get -y install yarn
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Install NVM&lt;/h3&gt;
&lt;p&gt;As it&apos;s not provided by default, I need to install Node and NPM in order to install my site&apos;s dependencies and then build it. I figured NVM would be the most sensible approach:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;install:
 - rm -rf ~/.nvm &amp;amp;&amp;amp; git clone https://github.com/creationix/nvm.git ~/.nvm &amp;amp;&amp;amp; (cd ~/.nvm &amp;amp;&amp;amp; git checkout `git describe --abbrev=0 --tags`) &amp;amp;&amp;amp; source ~/.nvm/nvm.sh &amp;amp;&amp;amp; nvm install $TRAVIS_NODE_VERSION
 - pip install awscli
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I discover afterwards that the ugly &lt;code&gt;$TRAVIS_NODE_VERSION&lt;/code&gt; environment variable could have been avoided by &lt;a href=&quot;https://docs.travis-ci.com/user/languages/javascript-with-nodejs/&quot;&gt;specifying the version in the project&apos;s &lt;code&gt;.nvmrc&lt;/code&gt; file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As the Travis cycle goes &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;script&lt;/code&gt;, &lt;code&gt;deploy&lt;/code&gt;, next up is…&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;before_script:
  npm install
script:
  npm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;(Travis experts – could those commands just have been listed sequentially in the &lt;code&gt;script&lt;/code&gt; block?)&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Configure S3 bucket&lt;/h3&gt;
&lt;p&gt;We use the same &lt;code&gt;deploy&lt;/code&gt; block as before:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deploy:
  provider: s3
  access_key_id: $AWS_ACCESS_KEY_ID
  secret_access_key: $AWS_SECRET_ACCESS_KEY
  bucket: danmatthew.co.uk
  region: $AWS_DEFAULT_REGION
  # Prevent Travis from deleting your built site so it can be uploaded.
  skip_cleanup: true
  # Path to a directory containing your built site.
  local_dir: public
  on:
    branch: master
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Blow away the old Cloudfront distribution&lt;/h3&gt;
&lt;p&gt;When this succeeds, we can now use the AWS CLI to ensure that Cloudfront serves the latest version of these files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;after_deploy:
 # Allow `awscli` to make requests to CloudFront.
 - aws configure set preview.cloudfront true
 # Invalidate every object in the targeted distribution.
 - test $TRAVIS_BRANCH = &quot;master&quot; &amp;amp;&amp;amp; aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths &quot;/*&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inspecting the bucket, I notice that Travis doesn&apos;t doesn&apos;t sync the files – i.e. only new files are added; old ones are deleted. It might not be an issue in practice, but I quite like keeping my buckets tidy… 😒&lt;/p&gt;
&lt;p&gt;Next!&lt;/p&gt;
&lt;h2&gt;Attempt #3: Use s3_website&lt;/h2&gt;
&lt;p&gt;I mentioned in the intro that when publshing the website from my computer I used the s3_website gem. I know it, it does all the tasks I want it to, and it&apos;s straightforward to configure.&lt;/p&gt;
&lt;p&gt;(Although, I fib: since upgrading to Sierra, I&apos;ve not been &lt;s&gt;able&lt;/s&gt; inclined to deploy since it requires a Java installation which I really don&apos;t want to do. I know, weaksauce.)&lt;/p&gt;
&lt;p&gt;So, we go again! Now, we&apos;re sacking off a Python-based deployment pipe in favour of a Ruby powered process:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: ruby
rvm: 2.2
sudo: required
dist: trusty
# Again with the redundant env var
env:
 - TRAVIS_NODE_VERSION=&quot;8&quot;
before_install:
  - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
  - echo &quot;deb https://dl.yarnpkg.com/debian/ stable main&quot; | sudo tee /etc/apt/sources.list.d/yarn.list
  - sudo apt-get -qq update
  - sudo apt-get -y install yarn
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Install s3_website&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;install:
  - . $HOME/.nvm/nvm.sh
  - nvm install stable
  - nvm use stable
  - gem install s3_website
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Push to S3&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;before_script:
 - yarn
script:
 - yarn build
after_script:
 - test $TRAVIS_BRANCH = &quot;master&quot; &amp;amp;&amp;amp; s3_website push
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Boom. All my &lt;code&gt;s3_website&lt;/code&gt; settings are configured in environment variables and my &lt;code&gt;s3_website.yml&lt;/code&gt; config, so that one line in the &lt;code&gt;after_script&lt;/code&gt; block pushes to the correct bucket and invalidates the Cloudfront distribution.&lt;/p&gt;
&lt;p&gt;Looking back over it, I think I&apos;d be quite happy to sack off the yarn installation and reply on NPM. Again I wonder whether the blocks can be consolidated into one and the commands listed sequentially? I&apos;m not experienced enough with Travis to know what benefits I get from splitting the commands into the different stages, especially since this particular deployment process is not exactly complicated. Perhaps so the process can fail earlier if necessary?&lt;/p&gt;
&lt;h2&gt;Proposed attempt #4: Use AWS CLI for everything&lt;/h2&gt;
&lt;p&gt;I suspect I could probably do all of the above with the AWS CLI, though it will need switching back over to Python again. Woe is me 😩.&lt;/p&gt;
&lt;h2&gt;Attemp #5: Concise&lt;/h2&gt;
&lt;p&gt;…whereupon I decided to sack off Yarn, and after configuring Travis to build PR and branch merges, whitelist the &lt;code&gt;master&lt;/code&gt; branch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;branches:
  only:
    - master
language: ruby
rvm: 2.2
sudo: required
dist: trusty
cache:
  - npm
install:
  - . $HOME/.nvm/nvm.sh
  - nvm install stable
  - nvm use stable
  - gem install s3_website
before_script:
  - npm install
script:
  - npm run build
after_script:
  - s3_website push
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Hide An Element From A Screenreader</title><link>https://danmatthew.co.uk/notes/2017-10-04-hidden-elements-accessibility/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2017-10-04-hidden-elements-accessibility/</guid><pubDate>Wed, 04 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently discovered that it&apos;s not enough to rely on either &lt;code&gt;role=&quot;presentation&quot;&lt;/code&gt; or &lt;code&gt;aria-hidden=&quot;true&quot;&lt;/code&gt; to remove an element from the accessibility tree. Just like CSS quirks, in order to ensure an element is truly hidden from screenreaders across operating systems and browsers, you will want to double-up on the attributes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  &amp;lt;!-- Tested with macOS, Voiceover, and Chrome 63 --&amp;gt;

  &amp;lt;!-- Will be announced --&amp;gt;
  &amp;lt;div&amp;gt;I am a presentation element. I don&apos;t add anything more than a visual flourish.&amp;lt;/div&amp;gt;

  &amp;lt;!-- Will be announced in Voiceover, but not in JAWS --&amp;gt;
  &amp;lt;div role=&quot;presentation&quot;&amp;gt;I am a presentation element. I don&apos;t add anything more than a visual flourish.&amp;lt;/div&amp;gt;

  &amp;lt;!-- Voiceover will ignore this element; JAWS won&apos;t --&amp;gt;
  &amp;lt;div aria-hidden=&quot;true&quot;&amp;gt;I am a presentation element. I don&apos;t add anything more than a visual flourish.&amp;lt;/div&amp;gt;

  &amp;lt;!-- Voiceover will ignore this element --&amp;gt;
  &amp;lt;div aria-hidden=&quot;true&quot; role=&quot;presentation&quot;&amp;gt;I am a presentation element. I don&apos;t add anything more than a visual flourish.&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://output.jsbin.com/zaqiboc&quot;&gt;You can view the demo at JSBin&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>npm 101 – Version Ranges</title><link>https://danmatthew.co.uk/notes/2016-01-25-npm-version-ranges/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2016-01-25-npm-version-ranges/</guid><pubDate>Mon, 25 Jan 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The following is a snippet from this site&apos;s &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  &quot;devDependencies&quot;: {
    &quot;bower&quot;: &quot;^1.6.5&quot;,
    &quot;grunt&quot;: &quot;~0.4.5&quot;,
    &quot;grunt-contrib-imagemin&quot;: &quot;~0.9.4&quot;,
    &quot;grunt-contrib-sass&quot;: &quot;~0.9.2&quot;,
    &quot;grunt-contrib-watch&quot;: &quot;~0.6.1&quot;,
    &quot;matchdep&quot;: &quot;~0.3.0&quot;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As per the JSON spec, we&apos;ve got a series of key/value pairs making up the &lt;code&gt;devDependencies&lt;/code&gt; object: the name of the package we want installed for those working on the project, and the version number of that package. However, using &lt;code&gt;npm install &amp;lt;package&amp;gt;&lt;/code&gt; will leave odd extra characters in the generated file. So what do they mean?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Caret range&lt;/td&gt;
&lt;td&gt;Allows minor and patch updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tilde range&lt;/td&gt;
&lt;td&gt;Allows patch-level changes if minor version is specified&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;It&apos;s possible to add configure your project to help ensure only a specific version of a package is added. Create a file called &lt;code&gt;.npmrc&lt;/code&gt;, and specify &lt;code&gt;save-exact=true&lt;/code&gt;. As a bonus, you can also added &lt;code&gt;save=true&lt;/code&gt; to make sure that any new installs are added to your projects&apos; &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;
</content:encoded></item><item><title>Column Sizing and Captions in Safari</title><link>https://danmatthew.co.uk/notes/2015-12-07-safari-table-columns/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2015-12-07-safari-table-columns/</guid><pubDate>Mon, 07 Dec 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;lt;p class=&quot;message&quot;&amp;gt;
&amp;lt;em&amp;gt;Updated 25/09/2016:&amp;lt;/em&amp;gt; It still appears to be an issue in Safari 10.0 (macOS Sierra).
&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;A couple of weeks ago, I encountered an odd rendering issue with Safari and column widths. I had planned to write about it, lest the afternoon I spent trying to debug it be of use to anyone who stumbles across this post. Before I could get round to it, lo and behold: I&apos;ve fallen victim to it again! Safari on OSX - both Yosemite and El Capitan - does not like the following scenario:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.col-checkbox {
  width: 28px;
}

.col-content {
  width: auto;
}

.col-action-btn {
  width: 60px;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;table class=&quot;table table-striped&quot;&amp;gt;
 &amp;lt;caption class=&quot;sr-only&quot;&amp;gt;My caption to describe the table&amp;lt;/caption&amp;gt;
  &amp;lt;colgroup&amp;gt;
    &amp;lt;col class=&quot;col-checkbox&quot;&amp;gt;
    &amp;lt;col class=&quot;col-content&quot;&amp;gt;
    &amp;lt;col class=&quot;col-action-btn&quot;&amp;gt;
  &amp;lt;/colgroup&amp;gt;
  &amp;lt;thead&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;span&amp;gt;
          &amp;lt;input type=&quot;checkbox&quot;&amp;gt;
        &amp;lt;/span&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Two&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Three&amp;lt;/th&amp;gt;
  &amp;lt;/th&amp;gt;
&amp;lt;/tr&amp;gt;
&amp;lt;/thead&amp;gt;
&amp;lt;tbody&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;input type=&quot;checkbox&quot;&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;Content&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;Content&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Safari refuses to apply the column widths specified in the stylesheet, and instead splits the columns based on their content, flagrantly ignoring the authors instructions.&lt;/p&gt;
&lt;p&gt;It seems to be related to the &lt;code&gt;sr-only&lt;/code&gt; class applied to the &lt;code&gt;caption&lt;/code&gt;. This utility class hides the element from those who can see the table contents as a whole, but provides a useful description for those using assistive technologies. Within this class, the &lt;code&gt;position: absolute&lt;/code&gt; declaration used to remove the element from the document flow causes the bug. But strangely, it only happens when applied to &lt;code&gt;caption&lt;/code&gt;: were one to use a &lt;code&gt;span&lt;/code&gt; here, Safari will respect the column widths.&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- &lt;img src=&quot;/public/img/src/safari-table-bug.png&quot; alt=&quot;Screenshot illustrating the table rendering bug in Safari&quot; /&gt; --&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;ve not been able to replicate in other desktop browsers: Chrome, Firefox, and Opera split the columns as desired, though Mobile Safari renders the table as per its desktop cousin. The Internet seems to have a scarcity of other reports, which makes me wonder if I have encountered a bug. Or maybe nobody else is combining this class with table captions, column widths - defined using classes, since the &lt;code&gt;width&lt;/code&gt; attribute is obsolete - and Safari. I wonder at what point does it become a Safari / Webkit bug? I have a demo of it available on &lt;a href=&quot;http://jsbin.com/sabisa/embed?html,output&quot;&gt;JSBin&lt;/a&gt; and the various permutations are easily replicable.&lt;/p&gt;
</content:encoded></item><item><title>Two forms of IIFE</title><link>https://danmatthew.co.uk/notes/2015-10-22-two-types-of-iife/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2015-10-22-two-types-of-iife/</guid><pubDate>Thu, 22 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;TIL there are two ways of creating an IIFE - and there&apos;s &lt;a href=&quot;https://stackoverflow.com/questions/8774425/vs-in-javascript-closures&quot;&gt;heated discussion&lt;/a&gt; between parties as to why they have chosen their preferred style. Douglas Crockford prefers the second structure here, as the first &lt;a href=&quot;https://twitter.com/paul_irish/status/176187448420864000&quot;&gt;&quot;looks like dog balls&quot;&lt;/a&gt;. If you use &lt;a href=&quot;http://www.jslint.com/&quot;&gt;JSLint&lt;/a&gt;, you&apos;ll be encouraged to adopt the latter style - it suggests the parentheses that invoke the function should sit within those that contain it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(function(){
  function foo() {
    // I&apos;m not polluting the global scope!
  }
})();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;(function(){
  function bar() {
    // Nor am I!
  }
}());
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Shadowing And Hoisting In JavaScript</title><link>https://danmatthew.co.uk/notes/2015-01-25-shadowing-and-hoisting-in-javascript/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2015-01-25-shadowing-and-hoisting-in-javascript/</guid><pubDate>Sun, 25 Jan 2015 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Shadowing&lt;/h2&gt;
&lt;p&gt;To &quot;shadow&quot; a variable is to create a new variable with the same name as one that exists in a higher scope. In JavaScript, a new scope is created when writing a function. When resolving a variable, JavaScript starts at the innermost scope and searches outwards.&lt;/p&gt;
&lt;h2&gt;Hoisting&lt;/h2&gt;
&lt;p&gt;Hoisting, on the other hand, is a behaviour which results in variables being raised, or &apos;hoisted&apos;, to the top of the scope - the function - in which they have been defined. It&apos;s recommended to declare all of your variables at the top of a function in order to avoid overwriting a value.&lt;/p&gt;
</content:encoded></item><item><title>Checking Date Equality in JavaScript</title><link>https://danmatthew.co.uk/notes/2014-04-16-checking-date-equality-in-javascript/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2014-04-16-checking-date-equality-in-javascript/</guid><pubDate>Wed, 16 Apr 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Checking whether one date is equal to another is made difficult because of the way object equality works in JavaScript. Object equality isn&apos;t tested by the internal value of the object, but by identity. If the date object isn&apos;t a straight copy, it isn&apos;t considered equal. The following example will never return &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function isChristmas(dateToTest){
  var christmas = new Date(&quot;12/25/2014&quot;);
  return (dateToTest === christmas);
}

console.log(isChristmas(new Date(&quot;12/25/2014&quot;))); // False
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make the &lt;code&gt;isChristmas&lt;/code&gt; function work, we need to check equality in a different way. We use the &lt;code&gt;getTime&lt;/code&gt; method that is available on Date object, and compare the values it returns. &lt;code&gt;getTime&lt;/code&gt; returns an integer representing the number of milliseconds since midnight of the epoch: January 1st, 1970.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function isChristmas(dateToTest){
  var christmas = new Date(&quot;12/25/2014&quot;);
  return (dateToTest.getTime() === christmas.getTime());
}

console.log(isChristmas(new Date(&quot;12/25/2014&quot;))); // True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But! If we happen to compare against a &lt;code&gt;Date&lt;/code&gt; object that occurs on the same day, but a different hour, we&apos;ll run into trouble - because the time elapsed since the epoch will be different.&lt;/p&gt;
&lt;p&gt;A work around here might be to check our date against the year, month and day, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function isChristmas(dateToTest){
  return (dateToTest.getFullYear() === 2014) &amp;amp;&amp;amp;
  (dateToTest.getMonth() === 11) &amp;amp;&amp;amp;
  (dateToTest.getDate() === 25);
}

console.log(isChristmas(new Date(&quot;12/25/2014 12:00&quot;))); // True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But then this is glossing over the complexities that daylight savings and timezones introduce.&lt;/p&gt;
&lt;p&gt;TL;DR: Be aware that there are &apos;gotchas&apos; when comparing dates. Use &lt;a href=&quot;http://momentjs.com&quot;&gt;Moment.js&lt;/a&gt; to avoid them and make your life easier.&lt;/p&gt;
</content:encoded></item><item><title>Closures 101</title><link>https://danmatthew.co.uk/notes/2014-02-03-closures-101/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2014-02-03-closures-101/</guid><pubDate>Mon, 03 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;I updated this post on the 16th February in order to clarify my writing and thoughts.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;What is a closure?&lt;/h2&gt;
&lt;p&gt;In computer science:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be &quot;closed over&quot; its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A higher-level definition is that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A closure is a function defined within another scope that has access to all the variables within the outer scope.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And just in case, think of it as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...like keeping a copy of the all the local variables, just as they were when a function exited.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Closures are a strange concept to get to grips with, but once this core concept is understood they&apos;re relatively easy to understand: a closure is created when a developer accesses variables outside of the immediate lexical scope.&lt;/p&gt;
&lt;h2&gt;An example of a closure in action&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;function makeAdder(a) {
  return function(b) {
    return a + b;
  };
}

x = makeAdder(5);
y = makeAdder(20);

x(6); // 11
y(7); // 27
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/95PTq/&quot;&gt;JSFiddle demo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What happens in a closure?&lt;/h2&gt;
&lt;p&gt;When &lt;code&gt;makeAdder&lt;/code&gt; is called, a new scope is created with one property: &lt;code&gt;a&lt;/code&gt; - the argument passed to the function. It also returns the anonymous function declared within it. This returned function maintains a reference back to that original scope. This scope will persist and escape being garbage collected until there are no more references to that function.&lt;/p&gt;
&lt;p&gt;Take a look at what happens when we log &lt;code&gt;x&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function(b){
  return a + b;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So when we call &lt;code&gt;x&lt;/code&gt; and pass an argument, that&apos;s going straight into the anonymous function &lt;code&gt;makeAdder&lt;/code&gt; returned the first time. Because we know a closure is a combination of a function and its scope&lt;/p&gt;
&lt;p&gt;Since we are then able to all &lt;code&gt;y&lt;/code&gt;, we discover that we have ended up with two different copies of &lt;code&gt;makeAdder&lt;/code&gt;&apos;s local variables: one in which &lt;code&gt;a&lt;/code&gt; is 5, and another where &lt;code&gt;a&lt;/code&gt; is 20.&lt;/p&gt;
&lt;h2&gt;When would I use a closure?&lt;/h2&gt;
&lt;p&gt;The technique is often used to prevent against contaminating higher levels of &lt;a href=&quot;http://danmatthew.co.uk/2013/05/18/variable-scope-in-javascript/&quot;&gt;scope&lt;/a&gt; - data is kept tucked away. Along these lines, a closure can be used to help practise encapsulation: an object can return its public methods and variable, while keeping those intended to be private hidden and inaccessible to the rest of the codebase.&lt;/p&gt;
&lt;p&gt;You may have taken advantage of one without realising it, as they&apos;re a key concept when implementing an &apos;Immediately-Invoked Function Expression&apos; (IIFE). Using an IIFE within a module, as per the &lt;a href=&quot;http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript&quot;&gt;Module Pattern&lt;/a&gt;, ensures that the module is self-contained.&lt;/p&gt;
&lt;p&gt;An intelligent developer will&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;use closures to create additional scopes that can be used to group interrelated and dependent code in a way that minimises the risk of accidental interaction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Useful reading&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://howtonode.org/why-use-closure&quot;&gt;http://howtonode.org/why-use-closure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jibbering.com/faq/notes/closures/&quot;&gt;http://www.jibbering.com/faq/notes/closures/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/111102/how-do-javascript-closures-work&quot;&gt;http://stackoverflow.com/questions/111102/how-do-javascript-closures-work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures?redirectlocale=en-US&amp;amp;redirectslug=JavaScript%2FGuide%2FClosures&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures?redirectlocale=en-US&amp;amp;redirectslug=JavaScript%2FGuide%2FClosures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://learn.jquery.com/javascript-101/closures/&quot;&gt;http://learn.jquery.com/javascript-101/closures/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example&quot;&gt;http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Exclude folders in Jekyll</title><link>https://danmatthew.co.uk/notes/2014-01-18-exclude-folders-in-jekyll/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2014-01-18-exclude-folders-in-jekyll/</guid><pubDate>Sat, 18 Jan 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;After experimenting with Grunt, I noticed that the deploy was taking rather a long time - it turned out that Jekyll was bundling my &apos;node_modules&apos; directory (all 32MB of it!) into its compiled site folder. However, I can avoid this in future by adding: &lt;code&gt;exclude: node_modules&lt;/code&gt; to my &lt;code&gt;_config.yml&lt;/code&gt; file.&lt;/p&gt;
</content:encoded></item><item><title>Remove Child Nodes In JavaScript</title><link>https://danmatthew.co.uk/notes/2013-12-11-remove-child-nodes-in-javascript/</link><guid isPermaLink="true">https://danmatthew.co.uk/notes/2013-12-11-remove-child-nodes-in-javascript/</guid><pubDate>Wed, 11 Dec 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;After discovering whether an element has children, one may want to go ahead and remove them. The brutalist approach involves setting the node&apos;s &lt;code&gt;innerHTML&lt;/code&gt; property to an empty string.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&quot;box&quot;&amp;gt;
  &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;

var box = document.getElementById(&apos;box&apos;);
if (box.firstChild) {
  box.innerHTML = &apos;&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another option is to grab the &lt;code&gt;firstChild&lt;/code&gt; and then remove it like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;while (box.firstChild) {
  box.removeChild(box.firstChild);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The results on &lt;a href=&quot;http://jsperf.com/innerhtml-vs-removechild&quot;&gt;jsperf&lt;/a&gt; indicate that removeChild is the faster of the two techniques, and also the more robust: the &lt;code&gt;innerHTML&lt;/code&gt; technique won&apos;t work on XML markup.&lt;/p&gt;
&lt;p&gt;But wait! As usual, there is another alternative. Check out:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;while (box.hasChildNodes()) {
	box.removeChild(box.lastChild);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s really just a variant on the method above: ensuring that &lt;code&gt;box&lt;/code&gt; still has children and removing them from the bottom instead of the top.&lt;/p&gt;
</content:encoded></item></channel></rss>