Running list of little interesting things I learn. Uninteresting things not included. Not guaranteed to be interesting for all / any audiences.
All of the support tables are lying: Safari 10 and 11 parse let and const, but if you try to rely on their block scoping, they break.
The fix: enable the safari10
option in uglify-es.
In Chrome, you can set style-src to just somedomain.com
and it'll work. In Firefox, unless you set unsafe-inline
, style=""
attributes will break.
Let's say you have a monospace-formatted table, so all the |
should align. If any value in any column includes a character that isn't supported by the monospace font, the table won't be aligned. Example:
| h |
| 🚀 |
git status
will show a moved file on a case-sensitive system, but not here.
~/tmp/example〉git init .
Initialized empty Git repository in /Users/tmcw/tmp/example/.git/
~/tmp/example〉touch Hi
~/tmp/example〉git add Hi
~/tmp/example〉git commit -m "First"
[master (root-commit) c09565f] First
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 Hi
~/tmp/example〉mv Hi hi
~/tmp/example〉git status
On branch master
nothing to commit, working tree clean
In CSS Color Module 4, rgba and hsla are officially 'legacy' - you can add an alpha component without adding the a
to either - just use rgb()
and hsl()
always.
If you're in extreme pedant mode and want to find any place where you've typed an errant '
instead of a curly ’
, and you use Google Chrome's built-in search, you'll be surprised to see that - it matches both, regardless of which character you type. Apparently the search aliases certain common characters, because there are more people who would be upset about some quote-containing search to not return results based on typographical pedantry than people who would want to search for non-curly quotes only.
<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->
Spot the weirdness. Well: if you have some script that's sync or that's async but loads before google analytics, and that script changes the page location, then the first page that's tracked is not the page URL that's loaded. We throw in a
ga("set", "page", location.pathname + location.search);
To make sure the first-page-location-loaded is tracked.
Okay, I knew this one before, but it's always good to remember: console.log isn't sync. If you console.log something and then immediately modify the thing, console.log is likely to show the modified version, not the version at the time of the console.log
call. Beware.
There are some tough cases in English punctuation: see this issue in the marked repository:
I won't do it 'cause I don't want to.
This should have:
- won’t
- 'cause
- don’t
The commonplace smartypants option isn't smart enough to parse that, but implementations like markdown-it and Medium's online editor can do very advanced quote formatting.
An attacker could upload a specially crafted JPEG file that contained script content, and then send a link to the file to unsuspecting victims. When the victims visited the server, the malicious file would be downloaded, the script would be detected, and it would run in the context of the picture-sharing site.
Here's one blog post. It's weird, because before even if you declared a content-type, IE would still try to auto-detect a content type, and might re-interpret the file as something different. So you serve a file that contains JavaScript-looking content, but with an image/jpg
mime-type, IE would treat it as a script. So they:
- stopped sniffing image/ content
- let you turn sniffing off
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie2
It's just weird, that's all.
https://fetch.spec.whatwg.org/#should-response-to-request-be-blocked-due-to-mime-type?
So, like - usually you can fetch anything into anything, but if you're doing something like a Paint Worklet or a WebWorker, and the thing you're fetching has an image or CSV mime type, it's blocked.
https://fetch.spec.whatwg.org/#body-mixin
example
let resp = await fetch('https://unpkg.com/propel@3.2.0?meta');
[await resp.json(), await resp.text()];
This breaks! What .json()
and .text()
do internally is that they consume a stream of the body, and like other streams, you can only consume it once.
In code review, I came across
const compile = eval;
And wondered why we were renaming it. Almost everywhere in JavaScript, reassigning one variable to another name has no effect. That is not the case with eval: renaming eval makes it turn into an indirect eval call.
I should have written this one down a while ago, it's something that I learned from Mike's code:
let resolve;
let myPromise = new Promise(_resolve => { resolve = _resolve });
// now you can resolve that promise remotely
resolve();
It sort of inverts Promises, in a way, freeing you from relying on the resolve/reject methods only being called from inside its function.
I spent an hour debugging a simple query and got Jeremy to help and we both were stuck, until I re-read the Postgres documentation about comparison operators: and, here's how it works:
- (7 = NULL) = NULL
- (7 != NULL) = NULL
NULL, in Postgres, propagates. Any comparison with NULL always yields NULL. I ended up switching to the new IS DISTINCT FROM
comparison instead of simple =
comparisons.
Apples, oranges, and bananas
Versus
Apples, oranges, and bananas
This from Elements of Typographic Style.
I often write
/A-Za-z/
But if I want to really cover all the bases, I should write
/A-ZÀ-ÿa-z/
Otherwise accented words break the regex.
If you have a CTE in Postgresql:
WITH something AS (SELECT …)
SELECT * from something
The order of something
is not necessarily preserved. It uses the CTE as an optimization but you cannot depend on it. Instead, you’ll need to re-sort, or expose an integer that can be sorted, like
ROW_NUMBER () OVER (${orderClause}) AS rn
Like
SELECT 1 as a, 2, as a;
This gets tricky because most postgres bindings exposed row objects as objects, so the value is just the last duplicate-named column.
- Death and Life of Great American Cities
- Contretemp: minor diagreement
- Automat: coin-operated/automated restaurant
- Inveigle: to win over with flattery
- Petrel: a shearwater-like seabird
- Nekton: a plankton-like sea creature
- Israel
- Kippah: another word for yarmulke
- Deicide: the killing of a god
- Amanuensis: a literary or artistic assistant
- Lachrymose: prone to weeping
- Sangfroid: composure and coolness
- Stevedore: a longshoreman or dockworker
- Hillock: a small hill or mound
- Cynosure: a center of attention
- Janissary: a devoted follower
- Ex parte: one-sided, from one side
- Soupcon: a small portion
hidden
attribute
There's an HTML attribute called hidden
that simply hides elements:
<div hidden>This is hidden!</div>
It's part of the moreutils package that you can install with homebrew, and you just run vidir
in a directory, change the names, and exit your editor and everything is saved.
For example:
const x = Array.from({ length: 1000000 }, (_, i) => i)
const y = [];
y.push(...x);
This code crashes, because ...x
creates an arguments object that's too big. That triggers RangeError: Maximum call stack size exceeded
and crashes. Avoid ...
for values of unknown length. This does notably only relate to function calls, like .push()
. Using spread in an array, like [...x]
doesn't trigger the same issue.
Postgres does proper locale-based sorting, whereas JavaScript just compares characters by default. You can change the intricate behavior of string sorting by specifying a COLLATE option.
Remember this - the one indexed languages that you'll actually encounter - SQL, Lua, R.
It's not going to work if you try and profile the import()
call - Deno does static analysis to find dynamic imports before running the script.
See preventing a grid blowout for details, or this quick fix:
grid-template-columns: minmax(0, 1fr) 300px;
The thing is, 1fr
I always thought behaved like 100%, but it doesn't - it won't shrink as much as an element with 100%
because the minimum width is auto
, not 0. The same goes for flex items, which is why I've often found that min-width: 0
is helpful when flex elements are misbehaving and not shrinking.