#TIL - Today I Learned

CSS’s :where()

The :where() pseudo selector helps you writing cleaner code on the one hand. Instead of writing:

1
2
3
4
5
.wrapper h1,
.wrapper h2,
.wrapper h3 {
color: red;
}

… you can do:

1
2
3
.wrapper :where(h1, h2, h3) {
color red;
}

On the other hand, it is a so called forgiving selector, which rougly means, if one of the selectors in a selector list isn’t valid, it works nevertheless.

IIS: Allow Plus sign in Url’s

Due to security reasons IIS only allows the + sign in query strings. But sometimes you may have an image file like landscape + night.jpg, which won’t be shown on your website.

The solution is, to allow unescaped plus signs in web.config and also do a rewrite to UrlDecode the requested Uri:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<configuration>
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="True" />
</security>
<rewrite>
<rules>
<rule name="RewriteUserFriendlyURL1" stopProcessing="false">
<match url="\+" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="{UrlDecode:{REQUEST_URI}}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Source

Optional Chaining on Methods and Indexes

In ECMAScript 2020 the optional chaining operator was introduced into JavaScript. The question mark right behind the property name helps to prevent null reference exceptions:

1
2
3
4
5
const foo = { bar: null };

foo.bar.prop // TypeError: Cannot read properties of undefined = NullReferenceException

foo?.bar?.prop // undefined

This works also on methods calls and index access:

1
2
foo.doSomething.?()
foo.aList.?[0]

Important: The parentheses for the parameter listing or the index expression must be preceded by a period!

Convert backslash into forward slash

While developing Node.js on Windows and dealing with paths, like path.join, the folder separator will be a backslash always. But on the web a forward slash is recommended. Most browsers have no problem showing an image with a relative path like /images\my-image.jpg, but it is not ideal.

Replacing backslashes with foreward slashed seems easy, but it has its pitfalls, because JS uses the backslash for escaping. A safe way to address backslashes on replacing is to use its octal representation \134:

1
let myPath = path.join(root, "images", "my-image.jpg").replace(/\134/g,"/");

Another way to get correct paths, you can use Node’s path methods normalize or resolve.

Debugging Hexo with VSCode

If you want to debug your own Hexo generators within VSCode, you have to create an entry in your ./.vscode/launch.json, which points to Hexo CLI with the argument generate:

1
2
3
4
5
6
7
8
9
10
11
12
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "hexo generate",
"program": "${workspaceFolder}/node_modules/hexo-cli/bin/hexo",
"args": [
"generate"
]
}
]

display: contents

Some HTML elements does not have a visual styling, because their purpose is to ‘group’ others. But those wrappers have sometimes a negative effect on styling with techniques like grid or flex.

display: contents makes those elements a hidden ghost if needed, for easier styling of its children.

1
2
3
4
5
6
7
8
9
10
11
<style>
.box-content { display: contents }
</style>

<div class="box">
<div class="box-content">
<h2><!-- Title --></h2>
<p><!-- Description --></p>
</div>
<img src="image.jpg" alt="">
</div>

… will be parsed by the browser like:

1
2
3
4
5
<div class="box">
<h2><!-- Title --></h2>
<p><!-- Description --></p>
<img src="image.jpg" alt="">
</div>

Execute ES6 module with node.js

When executing a script designed as an ES6 module (f.e. node my-module.js), it will fail with the error Cannot use import statement outside a module.

Add "type": "module" to package.json and it will work.

Async Delay using Timeout

A little helper function to delay the execution of a script asynchonously

1
2
3
4
5
const delay = ms => new Promise((resolve, reject) => {
setTimeout(_ => resolve(), ms)
});

await delay(1000);

Detect Touch Input Devices

As of the W3C draft of Media Queries Level 5, touch devices can be detected by using the hover and the pointer media feature:

1
2
3
4
5
6
7
8
9
/* smartphones, touchscreens */
@media (hover: none) and (pointer: coarse) {
/* ... */
}

/* mouse, touch pad */
@media (hover: hover) and (pointer: fine) {
/* ... */
}

Module Script Access

When using <script type="module">, which allows to dynamically include ES6 modules via import, and bootstrapping the app in the script via var app = new App();, there is no access to app in developer tools or links with javascript: app.myFunc(). It has to be made visible by window.app = New App();.