Skip to content

Commit

Permalink
Merge pull request #776 from alexwlchan/port-all-tils
Browse files Browse the repository at this point in the history
Bring across all the existing TIL files
  • Loading branch information
alexwlchan authored Apr 8, 2024
2 parents 88b98f2 + 4af24ce commit 48b4b5b
Show file tree
Hide file tree
Showing 66 changed files with 2,428 additions and 1 deletion.
Binary file added src/_images/2023/the-runner-text-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2023/the-watcher-text-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/netlify-usage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/obsidian-table-broken.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/obsidian-table-fixed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wiki-commons-title.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wmc-inspector-search-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wmc-inspector-search-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wmc-inspector-search-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wmc-inspector-search-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/_images/2024/wmc-inspector-search-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/_includes/post_meta.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@
{% endfor %}
</li>
{% endif %}
{% if page.date_updated %}
<li>
Last updated
<time datetime="{{ page.date_updated | date: "%Y-%m-%d" }}">
{{- page.date_updated | date: site.date_format -}}
</time>
</li>
{% endif %}
</ul>
2 changes: 2 additions & 0 deletions src/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,8 @@
/projects/ /410/ 410

/til/2024/ /til/
/til/2023/ /til/
/til/2021/ /til/
/til/2016/ /til/
/til/2013/ /til/

Expand Down
4 changes: 4 additions & 0 deletions src/_scss/components/til.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ article.til {
}

#list_of_tils {
& > li {
width: 100%;
}

h4 {
font-weight: normal;
margin-bottom: 5px;
Expand Down
23 changes: 23 additions & 0 deletions src/_til/2021/2021-12-27-calliope-syndrome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
layout: til
title: Calley-ope (calliope) Syndrome is pronouncing a word wrong because you’ve only ever read it on the page
date: 2021-12-27 08:45:38 +0000
tags:
- interesting-words
---
This is a phrase that goes around the Internet every once in a while, but there's no definitive reference page for it.

## Where does it come from?

Several sources on the Internet point to Judith Wynn Halsted's book *Some of My Best Friends Are Books: Guiding Gifted Readers*.
The Internet Archive has digitised the second edition from 2002, and the relevant passage is [on page 207](https://archive.org/details/someofmybestfrie00hals/page/206/mode/2up?q=syndrome):

> Books that contain pronunciation guides are helpful for gifted readers (though they are rare, and a pleasant surprise when found), since so many avid readers know words only from reading and therefore mispronounce them. One excellent teacher of gifted high school students calls this “The Calley-ope (calliope) Syndrome.”
An almost-identical passage appears in one of her earlier books, *Guiding Gifted Readers*, published in 1988.
(The two books have a very similar structure, so I think this is a "first edition" of *Some of My Best Friends* – but of course, not described that way at time of publication.)
It's been digitised by the Internet Archive and the passage is [on page 126](https://archive.org/details/guidinggiftedrea0000hals/page/126/mode/2up?q=calliope):

> Pronunciation guides are helpful for gifted readers (though they are rare, and a pleasant surprise when found), since so many of them know words only from reading and therefore mispronounce them. One excellent teacher of gifted high school students calls this “The Calley-ope (calliope) Syndrome.”
But this doesn't tell me which teacher coined the phrase!
49 changes: 49 additions & 0 deletions src/_til/2023/2023-05-23-profiling-swift.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
layout: til
date: 2023-05-23 21:05:27 +0000
title: How to profile Swift code
tags:
- swift
---
[Stack Overflow coughed up a snippet which I've adapted](https://stackoverflow.com/a/24755958/1558022):

```swift
let start = DispatchTime.now()
var elapsed = start

func printElapsed(_ label: String) -> Void {
let now = DispatchTime.now()

let totalInterval = Double(now.uptimeNanoseconds - start.uptimeNanoseconds) / 1_000_000_000
let elapsedInterval = Double(now.uptimeNanoseconds - elapsed.uptimeNanoseconds) / 1_000_000_000

elapsed = DispatchTime.now()

print("Time to \(label):\n \(elapsedInterval) seconds (\(totalInterval) total)")
}
```

e.g. in this profiling:

```console
$ time swift actions/run_action.swift 934BD809-D6D9-4147-AE7E-E1701C82AADD/L0/001 toggle-rejected
Time to waking up:
1.3583e-05 seconds
Time to get photo:
0.110328541 seconds
Time to enter switch:
0.1103705 seconds
Time to toggle needs action:
0.159904833 seconds
Time to all done:
0.211530583 seconds

________________________________________________________
Executed in 523.46 millis fish external
usr time 136.72 millis 60.00 micros 136.66 millis
sys time 52.85 millis 683.00 micros 52.17 millis
```

it's pretty obvious the "time to get photo" step is the slow one

The Stack Overflow answer suggests using `ContinuousClock`; that was in a newer version of Swift than I had available when I wrote this snippet – for now I'm sticking with what I've got and which I know works.
60 changes: 60 additions & 0 deletions src/_til/2023/2023-06-01-buildkite-concurrency-gates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
layout: til
title: Use concurrency gates to prevent concurrent deployments
date: 2023-06-01 20:37:05 +0000
tags:
- buildkite
---
Concurrency gates are a Buildkite feature you can use to "lock" certain tasks, e.g. ensure that you're only deploying one copy of an app at a time.
The pattern is described [in a Buildkite blog post](https://buildkite.com/blog/concurrency-gates), but it took actually implementing it [in Wellcome's front-end builds](https://github.com/wellcomecollection/wellcomecollection.org/pull/9884) to wrap my head around it.

Here's a simplified version of the Buildkite YAML from that PR, with my comments intact -- which are what helped me understand it.

```yaml
steps:
- label: "Deploy to prod environment"
command: "deploy_to_prod_environment.sh"

# These three lines create a "lock" around this pipeline.
#
# This means that once a deployment starts to an environment,
# no other builds will deploy to that environment until this
# deployment is complete and has run the end-to-end tests.
#
# == How it works ==
#
# This uses the "concurrency gate" pattern described in the Buildkite blog
# here: https://buildkite.com/blog/concurrency-gates
#
# Once this job starts running, this build has to either:
#
# 1) fail, or
# 2) complete all the other tasks in this concurrency group -- which is
# just the "Complete!" task at the end of the pipeline
#
# before any other build is allowed to run tasks in this concurrency group.
# This means no other build can start a new deployment until this deployment
# is complete.
concurrency_group: "front-end-deployment-gate"
concurrency: 1

- wait

- label: "Run end-to-end tests on the new deployment"
command: "run_e2e_tests.sh"

- wait

- label: "Complete the deployment"
command: echo "Deployment complete!"

# This is the second half of the concurrency gate described above.
#
# Buildkite won't let any other pipelines run in this concurrency group until
# this step has run (or the entire deployment has failed).
#
# When this step completes, it "unlocks" the deployment and allows other
# deployments to begin.
concurrency_group: "front-end-deployment-${BUILDKITE_GITHUB_DEPLOYMENT_ENVIRONMENT}-gate"
concurrency: 1
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
layout: til
title: Use Unicode property escapes to detect emoji in JavaScript
date: 2023-09-06 23:46:15 +0000
tags:
- javascript
- unicode
---
From [how to detect emoji using JavaScript](https://stackoverflow.com/a/64007175/1558022) on Stack Overflow:

> The answers might work but are terrible because they rely on unicode ranges that are unreadable and somewhat "magic" because it's not always clear where do they come from and why they work, not to mention they're not resilient to new emojis being added to the spec.
>
> Major browsers now support [unicode property escape](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes) which allows for matching emojis based on their belonging in the `Emoji` unicode category: `\p{Emoji}` matches an emoji, `\P{Emoji}` matches a non-emoji.
which includes some example code:

```javascript
console.log(
/\p{Emoji}/u.test('flowers'), // false :)
/\p{Emoji}/u.test('flowers 🌼🌺🌸'), // true :)
/\p{Emoji}/u.test('flowers 123'), // true :(
)
console.log(
/\p{Extended_Pictographic}/u.test('flowers'), // false :)
/\p{Extended_Pictographic}/u.test('flowers 🌼🌺🌸'), // true :)
/\p{Extended_Pictographic}/u.test('flowers 123'), // false :)
)
```

But this doesn't just apply to emoji – the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Unicode_character_class_escape) explains you can also use this for different chunks of the Unicode spectrum, e.g. `\P{Script_Extensions=Latin}` or `\p{Letter}`.

I used this to detect emoji [as part of enhanced spam detection](https://github.com/wellcomecollection/wellcomecollection.org/pull/10181) in Wellcome Collection's catalogue search.
16 changes: 16 additions & 0 deletions src/_til/2023/2023-10-02-woe-means-where-on-earth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
layout: til
title: "The acronym \"woe\" in the Flickr API stands for \"Where On Earth\""
date: 2023-10-02 17:29:30 +0000
tags:
- flickr
- naming-things
---
For example, the parameter in the [flickr.places.placesForContacts API][api]:

> <dl>
> <dt><code>woe_id</code> (Optional)</dl>
> <dd>A Where on Earth identifier to use to filter photo clusters. For example all the photos clustered by <strong>locality</strong> in the United States (WOE ID <strong>23424977</strong>).</dd>
> </dl>
[api]: https://www.flickr.com/services/api/flickr.places.placesForContacts.html
12 changes: 12 additions & 0 deletions src/_til/2023/2023-10-10-what-is-a-snak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
layout: til
date: 2023-10-10 15:42:27 +0000
title: Why the term "snak" keeps appearing in the Wikidata API
tags:
- wikimedia-commons
- naming-things
---
This is one of those terms I kept seeing in API responses and documentation, but it wasn't immediately obvious to me what it means.
I found an explanation in the [Wikibase/DataModel](https://www.mediawiki.org/wiki/Wikibase/DataModel#Overview_of_the_data_model) docs:

> For lack of a better name, any such basic assertion that one can make in Wikidata is called a **Snak** (which is small, but more than a byte). This term will not be relevant for using Wikidata (editors will not encounter it), but it is relevant for developers to avoid confusion with Statements or other claims.
55 changes: 55 additions & 0 deletions src/_til/2023/2023-10-16-find-files-with-sdc-fields.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
layout: til
date: 2023-10-16 16:45:35 +0000
title: Find files that use a particular SDC field
tags:
- wikimedia-commons
- sparql
---
## Using Special:MediaSearch

You can do structured data queries using [Special:MediaSearch](https://www.mediawiki.org/wiki/Help:MediaSearch#Statements_and_structured_data).
Here are a couple of examples:

* To find uses of a particular statement:

* Videos with property P1651 (YouTube video ID): <https://commons.wikimedia.org/wiki/Special:MediaSearch?type=video&search=haswbstatement%3AP1651>
* Images with property P12120 (Flickr photo ID): <https://commons.wikimedia.org/wiki/Special:MediaSearch?type=image&search=haswbstatement%3AP12120>

* To find a statement with a particular value:

* Images with P7482=Q66458942 (source of file is original creation by uploader): <https://commons.wikimedia.org/wiki/Special:MediaSearch?search=haswbstatement%3AP7482%3DQ66458942&type=image>

## Using the Commons Query Service

You can run SPARQL queries with the [Commons Query Service](https://commons.wikimedia.org/wiki/Commons:SPARQL_query_service).
I'm not super experienced with SPARQL, but I'll use this as a place to gather queries I've been able to get working.

* This is a query that finds files which have a P7482=Q74228490, P137=Q420747, and one of two Flickr URLs in the P973 field.

```sparql
SELECT ?item ?described_url WHERE {
?item wdt:P7482 wd:Q74228490 . # P7482 (source of file) = Q74228490 (file available on the internet)
?item p:P7482 ?statement .
?statement pq:P137 wd:Q103204. # P137 (operator) = Q420747 (National Library of Finland)
?statement pq:P973 ?described_url.
VALUES (?described_url) { (<https://www.flickr.com/photos/sunrise/29916169/>) (<https://www.flickr.com/photos/sunrise/29916169>) }
} LIMIT 1
```
[Link to query in WCQS](https://commons-query.wikimedia.org/#SELECT%20%3Fitem%20%3Fdescribed_url%20WHERE%20%7B%0A%20%20%3Fitem%20wdt%3AP7482%20wd%3AQ74228490%20.%20%20%20%20%20%20%20%23%20P7482%20%28source%20of%20file%29%20%3D%20Q74228490%20%28file%20available%20on%20the%20internet%29%0A%20%20%3Fitem%20p%3AP7482%20%3Fstatement%20.%0A%20%20%3Fstatement%20pq%3AP137%20wd%3AQ103204.%20%20%20%20%20%20%20%23%20P137%20%28operator%29%20%3D%20Q420747%20%28National%20Library%20of%20Finland%29%0A%20%20%3Fstatement%20pq%3AP973%20%3Fdescribed_url.%0A%20%20VALUES%20%28%3Fdescribed_url%29%20%7B%20%28%3Chttps%3A%2F%2Fwww.flickr.com%2Fphotos%2Fsunrise%2F29916169%2F%3E%29%20%28%3Chttps%3A%2F%2Fwww.flickr.com%2Fphotos%2Fsunrise%2F29916169%3E%29%20%7D%0A%7D%20LIMIT%201), which returns a single result.
* This is a query that finds users with a particular value in the Flickr User ID field:
```sparql
SELECT ?image WHERE {
# P170 (creator) / P3267 (Flickr user ID) = specified ID
?file p:P170 ?creator .
?creator pq:P3267 "52498302@N08" .
# Retrieve the image URL to display as a link
?file schema:url ?image .
}
```
[Link to query in WCQS](https://commons-query.wikimedia.org/#SELECT%20%3Fimage%20WHERE%20%7B%0A%20%20%23%20P170%20%28creator%29%20%2F%20P3267%20%28Flickr%20user%20ID%29%20%3D%20specified%20ID%0A%20%20%3Ffile%20p%3AP170%20%3Fcreator%20.%0A%20%20%3Fcreator%20pq%3AP3267%20%2252498302%40N08%22%20.%0A%20%20%0A%20%20%23%20Retrieve%20the%20image%20URL%20to%20display%20as%20a%20link%0A%20%20%3Ffile%20schema%3Aurl%20%3Fimage%20.%0A%7D%0A)
23 changes: 23 additions & 0 deletions src/_til/2023/2023-10-17-how-to-do-resumable-downloads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
layout: til
title: How to do resumable downloads with curl
date: 2023-10-17 20:10:10 +0000
tags:
- curl
---
The flag you want is [`--continue-at -`](https://curl.se/docs/manpage.html#-C), which will resume the transfer from the size of the already-downloaded file.

Here's an example of using it in practice.

```bash
curl \
--location \
--remote-name \
--continue-at - \
https://dumps.wikimedia.org/other/wikibase/commonswiki/20231009/commons-20231009-mediainfo.json.bz2
```

It behaves in a "sensible" way at the beginning and end of the download:

* If you haven't downloaded anything yet, it starts downloading from the first byte of the remote file.
* If you've already downloaded the complete file, it stops as soon as it checks the byte count with the remote server.
54 changes: 54 additions & 0 deletions src/_til/2023/2023-12-08-convert-between-m-ids-and-filenames.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
layout: til
date: 2023-12-08 20:58:33 +0000
title: Go between M-IDs and filenames on Wikimedia Commons
tags:
- wikimedia-commons
---
Every file on Wikimedia Commons has two identifiers:

* A filename, e.g. `File:Herestraat Groningen.JPG`.
This always starts with `File:` because these are pages in the [File namespace][namespaces]
* A numeric identifier, e.g. `M128`.
This is a unique dientifier for each file on Commons, similar to Q IDs for entities on Wikidata.

The APIs for searching/updating Wikimedia Commons typically accept both forms; sometimes it's convenient to go between the two.

1. To go from filename to numeric ID, you can use the [Query API][query] and do a search with the `titles` parameter.
The M ID is included in the response.

For example:

```console
$ curl 'https://commons.wikimedia.org/w/api.php?action=query&format=xml&titles=File:Herestraat%20Groningen.JPG'
<?xml version="1.0"?>
<api batchcomplete="">
<query>
<pages>
<page _idx="128" pageid="128" ns="6" title="File:Herestraat Groningen.JPG"/>
</pages>
</query>
</api>
```

2. To go from numeric ID to filename, go to `https://commons.wikimedia.org/?curid=[ID]`.

For example, <https://commons.wikimedia.org/?curid=128>.

Alternatively, you can use the Query API with the `pageids` parameter.
For example:

```console
$ curl 'https://commons.wikimedia.org/w/api.php?action=query&format=xml&pageids=128'
<?xml version="1.0"?>
<api batchcomplete="">
<query>
<pages>
<page _idx="128" pageid="128" ns="6" title="File:Herestraat Groningen.JPG"/>
</pages>
</query>
</api>
```

[query]: https://www.mediawiki.org/wiki/API:Query
[namespaces]: https://commons.wikimedia.org/wiki/Help:Namespaces
Loading

1 comment on commit 48b4b5b

@alexwlchan
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Published on https://alexwlchan.net as production
🚀 Deployed on https://6613e2dadac15e10d782c677--alexwlchan.netlify.app

Please sign in to comment.