<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>otsukare</title><link href="https://www.otsukare.info/" rel="alternate"></link><link href="https://www.otsukare.info/feeds/atom.xml" rel="self"></link><id>https://www.otsukare.info/</id><updated>2025-09-05T17:50:00+09:00</updated><subtitle>Thoughts after a day of work</subtitle><entry><title>Did you open a bug?</title><link href="https://www.otsukare.info/2025/09/05/open-bug-webdev" rel="alternate"></link><published>2025-09-05T17:50:00+09:00</published><updated>2025-09-05T17:50:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2025-09-05:/2025/09/05/open-bug-webdev</id><summary type="html">&lt;p&gt;What are the frictions which prevent you to open a bug?&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Wall with broken tiles." src="https://www.otsukare.info/images/20250905-bugs-reports.jpg"&gt;&lt;/p&gt;
&lt;p&gt;If you are a webdev…&lt;/p&gt;
&lt;p&gt;and you had an issue on the website you were working on, because of a web browser…&lt;/p&gt;
&lt;p&gt;Why didn't you file a bug on a browser bug tracker? What are the frictions?&lt;/p&gt;
&lt;p&gt;(not asking those who did, because they already do the right thing ❤️)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://issues.chromium.org/issues?q=status:open"&gt;Blink bug tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugzilla.mozilla.org"&gt;Gecko bug tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bugs.webkit.org/"&gt;WebKit bug tracker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or &lt;a href="https://webcompat.com/"&gt;Webcompat.com&lt;/a&gt;. A cross-browsers bug tracker.&lt;/p&gt;
&lt;p&gt;PS: do not hesitate to ask around you, your colleagues, mates, etc.&lt;/p&gt;
&lt;p&gt;This was &lt;a href="https://mastodon.cloud/@karlcow/115150006126574667"&gt;initially posted on mastodon&lt;/a&gt;, you can contact me there. Also on &lt;a href="https://github.com/karlcow"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Quick HTML test case</title><link href="https://www.otsukare.info/2025/06/13/quick-html-test-case" rel="alternate"></link><published>2025-06-13T15:30:00+09:00</published><updated>2025-06-14T16:38:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2025-06-13:/2025/06/13/quick-html-test-case</id><summary type="html">&lt;p&gt;Sometimes you just need a quick HTML test case. I often use data URL.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Blueprint of an old steam locomotive." src="https://www.otsukare.info/images/20250613-quick-action.jpg"&gt;&lt;/p&gt;
&lt;p&gt;For reporting a bug or an unexpected behavior, the simpler the test is, the better. You can create a very simple HTML file to demonstrate the issue or you can use an online code web app such as &lt;a href="https:jsfiddle.net/"&gt;jsfiddle&lt;/a&gt; or &lt;a href="https://codepen.io/"&gt;codepen&lt;/a&gt;. (I have a preference for codepen but I don't know why.) But &lt;strong&gt;most of the time&lt;/strong&gt;, I'm using &lt;code&gt;data:&lt;/code&gt; URL to share a simple piece of code for a test.&lt;/p&gt;
&lt;p&gt;Let's take this code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;opacity:clamp(50%,0%,70%)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;style&lt;/code&gt; attribute returns different values when we extract the value using &lt;code&gt;getPropertyValue()&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0.5&lt;/code&gt; in Safari Technology Preview  18.4 (220) 20622.1.14.5&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;calc(0.5)&lt;/code&gt; in Firefox Nightly 141.0a1 14125.6.5&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clamp(50%, 0%, 70%)&lt;/code&gt; in Google Chrome Canary 139.0.7233.0 7233.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to the &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=294363"&gt;WPT test&lt;/a&gt;, Firefox returns the right answer: &lt;code&gt;calc(0.5)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To see the returned value, we coud do :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;&amp;lt;!-- The code being tested. --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;opacity:clamp(50%,0%,70%)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="cm"&gt;&amp;lt;!-- Something that can hold the test result. --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="cm"&gt;&amp;lt;!-- the script extracting the value and writing the test result. --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;document.querySelector(&amp;quot;.log&amp;quot;).textContent=document.querySelector(&amp;quot;.test&amp;quot;).style.getPropertyValue(&amp;quot;opacity&amp;quot;);
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is very simple. I can put all of this on one line.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;opacity:clamp(50%,0%,70%)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;script&amp;gt;&lt;/span&gt;document.querySelector(&amp;quot;.log&amp;quot;).textContent=document.querySelector(&amp;quot;.test&amp;quot;).style.getPropertyValue(&amp;quot;opacity&amp;quot;);&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I just need to add the right data URL in front of it. This is HTML, so we add &lt;code&gt;data:text/html,&lt;/code&gt;. That's it. This will instruct the browser to parse the code in the URL bar to process it as HTML.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;data:text/html,&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;opacity:clamp(50%,0%,70%)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;script&amp;gt;&lt;/span&gt;document.querySelector(&amp;quot;.log&amp;quot;).textContent=document.querySelector(&amp;quot;.test&amp;quot;).style.getPropertyValue(&amp;quot;opacity&amp;quot;);&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then you can copy/paste this code in the URL bar of your favorite browser or more exactly in multiple browsers.&lt;/p&gt;
&lt;p&gt;Hope it helps! Yes, I opened a &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=294363"&gt;bug for the issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For those, who are wondering why I didn't use &lt;code&gt;id&lt;/code&gt; instead of &lt;code&gt;class&lt;/code&gt;. The &lt;code&gt;#&lt;/code&gt; sign in the &lt;code&gt;querySelector()&lt;/code&gt; would require to escape &lt;code&gt;#&lt;/code&gt;, because it would have unintended consequences on the parsing of the URL.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Les Liaisons Dangereuses Or The Wrong Love For Proxy Detections</title><link href="https://www.otsukare.info/2025/06/06/proxy-detections-are-wrong" rel="alternate"></link><published>2025-06-06T15:15:00+09:00</published><updated>2025-06-06T16:37:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2025-06-06:/2025/06/06/proxy-detections-are-wrong</id><summary type="html">&lt;p&gt;The Web is a pledge for universality. Web developers are sometimes facing the challenge of selecting specific behaviors for specific browsers or devices. Unfortunately it has bad consequences.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="a street sign with the following words: World Wide Love. LET'S KEEP THINGS FRIENDLY FOR OUR OWN GOOD." src="https://www.otsukare.info/images/20250606-love.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The temptation is high. The desire for shortcuts is permanent. But the story is often full of painful moments without any winners. "Les liaisons dangereuses" of detecting browsers and devices are common.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ce n’est pas à l’illusion d’un moment à régler le choix de notre vie. — &lt;a href="https://www.gutenberg.org/cache/epub/52006/pg52006-images.html"&gt;Les liaisons dangereuses&lt;/a&gt;. Choderlos de Laclos. 1782&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which can be translated as "it is not for the illusion of a moment to govern the choice of a lifetime."&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;window.installTrigger&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Firefox (Gecko) had the property &lt;code&gt;window.installTrigger&lt;/code&gt; to signal that a web extension could be installed. This was a Firefox-only property. Soon enough, obviously, people started to use it as a signal that the browser accessing the website was Firefox.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;installTrigger&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;window&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Firefox&lt;/span&gt;
}&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;others&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the property was retired, because it was not standard and used for things which were completely different from its initial purpose, websites started to break. It had to be &lt;a href="https://github.com/mozilla-firefox/firefox/blob/256ddfe73aaecf86420c55af1bdb23cb8755ea88/browser/extensions/webcompat/injections/js/bug1774005-installtrigger-shim.js#L8"&gt;shimmed&lt;/a&gt;. Gecko had to imitate the property so that some websites would continue to work.&lt;/p&gt;
&lt;h2&gt;Another example &lt;code&gt;-webkit-touch-callout&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;-webkit-touch-callout&lt;/code&gt; was &lt;a href="https://searchfox.org/wubkat/commit/b0f424ec866cf63a31760b6a84f185e4143ce375"&gt;implemented in 2013&lt;/a&gt; in WebKit to give the possibility for Web developers to opt out of the contextual menu given on iPhone during a long press. The long press on a link makes it possible to also get a preview of the page behind the link.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the contextual menu on an iPhone after a long press showing the preview of the page." src="https://www.otsukare.info/images/20250606-andor.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-webkit-touch-callout: none&lt;/code&gt; permits web developers to cancel this behavior when, for example, developing a web app they need to be able to long-press user gestures such as a drag and drop.&lt;/p&gt;
&lt;p&gt;But I discovered today that this was used as a proxy detection for iPhone in CSS. &lt;strong&gt;This is bad&lt;/strong&gt;. Some CSS stylesheets contain a combination of &lt;code&gt;@support&lt;/code&gt; and &lt;code&gt;-webkit-touch-callout: none&lt;/code&gt; to have a specific behavior in their CSS.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;@supports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;touch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;callout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* DON&amp;#39;T DO THAT! */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This has many implications for the future. Here are some examples of how it can become very sour.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One day, the &lt;a href="https://github.com/w3c/csswg-drafts/issues/12178"&gt;CSS WG may decide to standardize&lt;/a&gt; &lt;code&gt;touch-callout&lt;/code&gt; so that web developers can opt out of other browsers having contextual menus. Given the spread and the legacy of &lt;code&gt;-webkit-touch-callout&lt;/code&gt;, some browsers might have to alias the &lt;code&gt;-webkit&lt;/code&gt; version so it is working for websites not updated. Suddenly, the CSS targeting iPhone applies to all browsers.&lt;/li&gt;
&lt;li&gt;Or the opposite story of this where because the term is so misused and it will break so much stuff that a new term needs to be coined, leaving plenty of CSS on the Web with a useless term which is not working exactly like the initial idea. It also means that it forces WebKit to maintain the code for the old property or to shim it like Firefox did with the risk to have confusion in between the place where it was used rightly and where it was wrong.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are only a few examples of the complexity…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mohitk05/react-insta-stories/issues/183"&gt;fullscreen clickable with orb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kornelski/slip/issues/41"&gt;Looking for the same feature on Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lufte/lona/issues/16"&gt;To prevent text/image selection&lt;/a&gt; or &lt;a href="https://github.com/kitze/react-long/issues/20"&gt;this one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vaadin/flow/issues/6696"&gt;To prevent the orb for drag'n drop&lt;/a&gt; and &lt;a href="https://github.com/clauderic/dnd-kit/issues/791"&gt;another one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/telerik/kendo-themes/issues/4965"&gt;People complaining about framework disabling the menu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Do Not Misuse Terms&lt;/h2&gt;
&lt;p&gt;There are plenty of other examples of this type, such as the abuse of &lt;code&gt;maxTouchPoints&lt;/code&gt; (this one will be (not) "funny" if touch screens on desktop computers become more prevalent) or &lt;code&gt;window.standalone&lt;/code&gt; which created plenty of issues when web apps for desktop computers became a thing.&lt;/p&gt;
&lt;p&gt;We all know the &lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Testing/Feature_detection"&gt;benefits of feature detection&lt;/a&gt;, we made a lot of progress as a community to go away as much as possible from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Browser_detection_using_the_user_agent"&gt;User Agent detection&lt;/a&gt;. It's not perfect. There are always difficult trade-offs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;L’humanité n’est parfaite dans aucun genre, pas plus dans le mal que dans le bien. Le scélérat a ses vertus, comme l’honnête homme a ses faiblesses. — &lt;a href="https://www.gutenberg.org/cache/epub/52006/pg52006-images.html"&gt;Les liaisons dangereuses&lt;/a&gt;. Choderlos de Laclos. 1782&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Something along "Humanity is not perfect in any fashion; no more in the case of evil than in that of good. The criminal has his virtues, just as the honest man has his weaknesses."&lt;/p&gt;
&lt;p&gt;Stay away from proxy detections, aka using a feature of the Web platform which seems a solution, at a point in time, to detect a specific browser or device. It clutters the Web platform. It makes it very hard to have a better Web without plenty of hacks here and there.&lt;/p&gt;
&lt;p&gt;Use feature detections for what they are, detecting the feature to affect the behavior of this specific feature.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;See Also&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/"&gt;Detecting touch: it's the 'why', not the 'how'&lt;/a&gt; by Patrick H. Lauke and Robert Nyman. 2013.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Fixing rowspan=0 on tables on WebKit.</title><link href="https://www.otsukare.info/2025/02/21/rowspan-zero-table" rel="alternate"></link><published>2025-02-21T17:00:00+09:00</published><updated>2025-02-21T21:36:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2025-02-21:/2025/02/21/rowspan-zero-table</id><summary type="html">&lt;p&gt;A simple example of fixing a bug for WebKit about rowspan=0 on tables.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="stacked tables and chairs in the street." src="https://www.otsukare.info/images/20250221-tables.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Last week, I mentioned there were &lt;a href="/2025/02/14/contribute-webkit"&gt;easy ways to fix or help the WebKit project&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Find The Bug&lt;/h2&gt;
&lt;p&gt;In January, looking at the &lt;a href="https://searchfox.org/wubkat/search?q=FIXME&amp;amp;path=&amp;amp;case=false&amp;amp;regexp=false"&gt;&lt;code&gt;FIXME:&lt;/code&gt; mentions on the WebKit project&lt;/a&gt;, I found this piece of code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;HTMLTableCellElement::rowSpan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// FIXME: a rowSpan equal to 0 should be allowed, and mean that the cell is to span all the remaining rows in the row group.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rowSpanForBindings&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Searching on &lt;a href="https://bugs.webkit.org/"&gt;bugs.webkit.org&lt;/a&gt;, I found this bug opened by Simon Fraser on May 5, 2018: &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=185341"&gt;rowspan="0" results in different table layout than Firefox/Chrome&lt;/a&gt;. Would I be able to solve it?&lt;/p&gt;
&lt;h2&gt;Test The Bug&lt;/h2&gt;
&lt;p&gt;The first task is very simple. Understand what are the different renderings in between browsers.&lt;/p&gt;
&lt;p&gt;Simon had already created a &lt;a href="https://bugs.webkit.org/attachment.cgi?id=339629"&gt;testcase&lt;/a&gt; and Ahmad had created a screenshot for it showing the &lt;a href="https://bugs.webkit.org/attachment.cgi?id=461698"&gt;results of the testcase&lt;/a&gt; in Safari, Firefox and Chrome. This work was already done. If they had been missing, that would have been my first step.&lt;/p&gt;
&lt;h2&gt;Read The Specification&lt;/h2&gt;
&lt;p&gt;For having a better understanding of the issue, it is useful to read the specification related to this bug. In this case, the relevant information was in the HTML specification, where &lt;a href="https://html.spec.whatwg.org/multipage/tables.html#attr-tdth-rowspan"&gt;&lt;code&gt;rowspan&lt;/code&gt; attribute&lt;/a&gt; on &lt;code&gt;td&lt;/code&gt;/&lt;code&gt;th&lt;/code&gt; elements is described. This is the text we need:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;td&lt;/code&gt; and &lt;code&gt;th&lt;/code&gt; elements may also have a &lt;code&gt;rowspan&lt;/code&gt; content attribute specified, whose value must be a valid non-negative integer less than or equal to 65534. For this attribute, &lt;strong&gt;the value zero means that the cell is to span all the remaining rows in the row group&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Create More Tests&lt;/h2&gt;
&lt;p&gt;Let's take a normal simple table which is 3 by 3.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We might want to make the first cell overlapping the 3 rows of the tables. A way to do that is to set &lt;code&gt;rowspan="3"&lt;/code&gt; because there are 3 rows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;rowspand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a table were the first column will overlap the 3 rows. This is already working as expected in all rendering engines : WebKit, Gecko and Blink. So far, so good.&lt;/p&gt;
&lt;h2&gt;Think About The Logic&lt;/h2&gt;
&lt;p&gt;I learned from reading the specification that &lt;code&gt;rowspan&lt;/code&gt; had a maximum value: &lt;strong&gt;65534&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;My initial train of thoughts was:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;compute the number of rows the table.&lt;/li&gt;
&lt;li&gt;parse the value &lt;code&gt;rowspan&lt;/code&gt; value&lt;/li&gt;
&lt;li&gt;when the value is &lt;code&gt;0&lt;/code&gt;, replace it with the number of rows.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It seemed too convoluted. Would it be possible to use the maximum value for &lt;code&gt;rowspan&lt;/code&gt;? The specification was saying "span all the remaining rows in the row group".&lt;/p&gt;
&lt;p&gt;I experimented with a bigger &lt;code&gt;rowspan&lt;/code&gt; value than the number of rows. For example, put the value &lt;code&gt;30&lt;/code&gt; on a 3 rows table.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;rowspand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;30&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;                         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;                         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;B3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;C3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I checked in Firefox, Chrome, and Safari. I got the same rendering. We were on the right track. Let's use the maximum value for &lt;code&gt;rowspan&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I made a &lt;a href="https://codepen.io/webcompat/pen/wBwqzyq"&gt;test case with additional examples&lt;/a&gt; to be able to check in different browsers the behavior:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Rendering of the table bug in Safari." src="https://www.otsukare.info/images/20250221-table-test-bug.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Fixing The Code&lt;/h2&gt;
&lt;p&gt;We just had to try to change the C++ code. My patch was&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gh"&gt;diff --git a/Source/WebCore/html/HTMLTableCellElement.cpp b/Source/WebCore/html/HTMLTableCellElement.cpp&lt;/span&gt;
&lt;span class="gh"&gt;index 256c816acc37b..65450c01e369a 100644&lt;/span&gt;
&lt;span class="gd"&gt;--- a/Source/WebCore/html/HTMLTableCellElement.cpp&lt;/span&gt;
&lt;span class="gi"&gt;+++ b/Source/WebCore/html/HTMLTableCellElement.cpp&lt;/span&gt;
&lt;span class="gu"&gt;@@ -59,8 +59,14 @@ unsigned HTMLTableCellElement::colSpan() const&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;unsigned HTMLTableCellElement::rowSpan() const
&lt;span class="w"&gt; &lt;/span&gt;{
&lt;span class="gd"&gt;-    // FIXME: a rowSpan equal to 0 should be allowed, and mean that the cell is to span all the remaining rows in the row group.&lt;/span&gt;
&lt;span class="gd"&gt;-    return std::max(1u, rowSpanForBindings());&lt;/span&gt;
&lt;span class="gi"&gt;+    unsigned rowSpanValue = rowSpanForBindings();&lt;/span&gt;
&lt;span class="gi"&gt;+    // when rowspan=0, the HTML spec says it should apply to the full remaining rows.&lt;/span&gt;
&lt;span class="gi"&gt;+    // In https://html.spec.whatwg.org/multipage/tables.html#attr-tdth-rowspan&lt;/span&gt;
&lt;span class="gi"&gt;+    // &amp;gt; For this attribute, the value zero means that the cell is&lt;/span&gt;
&lt;span class="gi"&gt;+    // &amp;gt; to span all the remaining rows in the row group.&lt;/span&gt;
&lt;span class="gi"&gt;+    if (!rowSpanValue)&lt;/span&gt;
&lt;span class="gi"&gt;+        return maxRowspan;&lt;/span&gt;
&lt;span class="gi"&gt;+    return std::max(1u, rowSpanValue);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;}

&lt;span class="w"&gt; &lt;/span&gt;unsigned HTMLTableCellElement::rowSpanForBindings() const
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code&gt;rowspan&lt;/code&gt; was 0, just give the maximum value which is &lt;a href="https://github.com/WebKit/WebKit/blob/d74a24ca1f04fb3530d2f3ce6935d924542f2014/Source/WebCore/html/HTMLTableCellElement.h#L43"&gt;defined in &lt;code&gt;HTMLTableCellElement.h&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I compiled the code change and verified the results:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Rendering of the table bug in Safari but this time fixed." src="https://www.otsukare.info/images/20250221-table-test-fixed.jpg"&gt;&lt;/p&gt;
&lt;p&gt;(note for the careful reader the last table legend is wrong, it should be &lt;code&gt;rowspan="3"&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;This was fixed! A couple of tests needed to be rebaselined. I was ready to &lt;a href="https://github.com/WebKit/WebKit/pull/38398"&gt;send a Pull Request for this bug&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What Is Next?&lt;/h2&gt;
&lt;p&gt;The fix is not yet available on the current version of Safari, but you can experiment it with &lt;a href="https://developer.apple.com/safari/technology-preview/"&gt;Safari Technology Preview&lt;/a&gt; (&lt;a href="https://developer.apple.com/documentation/safari-technology-preview-release-notes/stp-release-213"&gt;STP 213 Release Notes&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The biggest part of fixing the bugs is researching, testing different HTML scenario without even touching the C++ code, etc. I'm not a C++ programmer, but time to time I can find bugs that are easy enough to understand that I can fix them. I hope this makes it easier for you to understand and encourage you to look at other bugs.&lt;/p&gt;
&lt;p&gt;Note also, that it is not always necessary to fix until modifying everything. Sometimes, just creating testscases, screenshots, pointing to the right places in the specifications, creating the WPT test cases covering this bug are all super useful.&lt;/p&gt;
&lt;p&gt;PS: Doing all this work, I found also about the behavior of &lt;code&gt;colspan&lt;/code&gt; which is interoperable (same behavior in all browsers), but which I find illogical comparing to the behavior of &lt;code&gt;rowspan&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Some Ways To Contribute To WebKit and Web Interoperability</title><link href="https://www.otsukare.info/2025/02/14/contribute-webkit" rel="alternate"></link><published>2025-02-14T15:35:00+09:00</published><updated>2025-02-14T15:55:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2025-02-14:/2025/02/14/contribute-webkit</id><summary type="html">&lt;p&gt;There are different ways to contribute to WebKit and the Web. These are a collection of some ideas to contribute.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Graffiti of a robot on a wall with buildings in the background." src="https://www.otsukare.info/images/20250214-bugs-webkit.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Someone asked me recently how to contribute to the WebKit project and more specifically how to find the low hanging fruits. While some of these are specific to WebKit, they can be easily applied to other browsers. Every browser engines projects have more bugs than they can handle with their teams.&lt;/p&gt;
&lt;p&gt;In no specific orders, some ideas for contributing.&lt;/p&gt;
&lt;h2&gt;Curate Old Bugs on the bug tracker&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Go through &lt;a href="https://bugs.webkit.org/buglist.cgi?order=bug_id&amp;amp;product=WebKit&amp;amp;query_format=advanced&amp;amp;resolution=---"&gt;old bugs of bugs.webkit.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Try to understand what the bug is about.&lt;/li&gt;
&lt;li&gt;Create simplified test case when there is none and add them as an attachment.&lt;/li&gt;
&lt;li&gt;If they show differences in between the browsers, take a screenshot when it’s visual in Safari (WebKit), Firefox (Gecko), Chrome (Blink).&lt;/li&gt;
&lt;li&gt;If there is no difference in between browsers, CC: me on the bug, and probably we will be able to close it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This might help reveal some old fixable bug or make it easier to fix it for another engineer. Some of them might be easy enough that you can start fix them yourself.&lt;/p&gt;
&lt;h2&gt;Find Out About Broken Stuff On WPT.&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Dive into all the &lt;a href="https://wpt.fyi/results/?label=master&amp;amp;label=experimental&amp;amp;aligned&amp;amp;q=safari%3Afail%20%28firefox%3Apass%20or%20chrome%3Apass%29"&gt;bugs which fail in Safari&lt;/a&gt;, but pass in Firefox and/or Chrome. (You can do similar search for things &lt;a href="https://wpt.fyi/results/?label=master&amp;amp;label=experimental&amp;amp;aligned&amp;amp;q=chrome%3Afail%20%28firefox%3Apass%20or%20safari%3Apass%29"&gt;failing in Chrome&lt;/a&gt; or &lt;a href="https://wpt.fyi/results/?label=master&amp;amp;label=experimental&amp;amp;aligned&amp;amp;q=firefox%3Afail%20%28chrome%3Apass%20or%20safari%3Apass%29"&gt;failing in Firefox&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;Understand what the tests is doing. You can check this with the WPT.live links and/or the associated commit.&lt;/li&gt;
&lt;li&gt;Check if the test is not broken and makes sense.&lt;/li&gt;
&lt;li&gt;Check if there is an associated bug on bugs.webkit.org. &lt;strong&gt;If not, open a new one&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;FIXME Hunt Inside WebKit Code&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://searchfox.org/wubkat/search?q=FIXME&amp;amp;path=&amp;amp;case=false&amp;amp;regexp=false"&gt;List all the FIXME&lt;/a&gt; which are flagged in the WebKit Source code.&lt;/li&gt;
&lt;li&gt;Not all of them are easy to fix, but some might be low hanging fruit. That will require to dive in the source code and understand it.&lt;/li&gt;
&lt;li&gt;Open a new bug on bugs.webkit.org if not yet existing.&lt;/li&gt;
&lt;li&gt;Eventually propose a patch.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Tests WebKit Quirks&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;There are a &lt;a href="https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Quirks.cpp"&gt;number Quirks in the WebKit project&lt;/a&gt;. These are in place to hotfix websites not doing the right thing.&lt;/li&gt;
&lt;li&gt;Sometimes these Quirks are not needed anymore. The site has made a silent fix. They didn't tell us about it.&lt;/li&gt;
&lt;li&gt;They need to be retested and flagged when there are not necessary anymore. This can lead to patches on removing the quirk when it is not needed anymore.&lt;/li&gt;
&lt;li&gt;Some of these quirks do not have the remove quirk bug counterpart. It would be good to create the bug for them. &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=284510"&gt;Example of a Remove Quirk Bug&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Triage Incoming Bugs On Webcompat.Com For Safari&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Time to time there are &lt;a href="https://github.com/webcompat/web-bugs/issues?q=is%3Aissue%20state%3Aopen%20label%3Abrowser-safari%20"&gt;bugs reported on webcompat.com for Safari&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;They require to be analyzed and understood.&lt;/li&gt;
&lt;li&gt;Sometimes, a new bug needs to be opened on &lt;a href="https://bugs.webkit.org/enter_bug.cgi?product=WebKit&amp;amp;GoAheadAndLogIn=Log%20in&amp;amp;component=New+Bugs"&gt;bugs.webkit.org&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Again, this is strongly explaining how to help from the side of WebKit. But these type of participation can be easily transposed for Gecko and Blink. If you have other ideas for fixing bugs, let me know.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Molly</title><link href="https://www.otsukare.info/2023/09/06/molly" rel="alternate"></link><published>2023-09-06T17:51:00+09:00</published><updated>2023-09-06T17:51:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-09-06:/2023/09/06/molly</id><summary type="html">&lt;p&gt;Molly Holzschlag passed away.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.tucsonsentinel.com/local/report/090523_molly_holzschlag/"&gt;Molly passed away at 60.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Portrait de Molly Holzschlag" src="https://www.otsukare.info/images/20230806-molly.jpg"&gt;&lt;/p&gt;
&lt;p&gt;A blog post of this nature is never easy. She was so larger than life that she puts a print on each of us, who have discovered the Web early on.&lt;/p&gt;
&lt;p&gt;My first discovery of Molly Holzschlag was through the &lt;a href="https://people.apache.org/~jim/NewArchitect/webtech/index.html"&gt;WebTechniques magazine published from 1996 to 2002&lt;/a&gt;. This was a real magazine about the Web. You would recognize early writers like Laura Lemay, Lynda Weinman, etc. She had a column there called Integrated Design. She started writing it on &lt;a href="https://people.apache.org/~jim/NewArchitect/webtech/1999/09/desi/index.html"&gt;Web Techniques. September 1999&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Style sheets are one of the most effective innovations for designers; they make it easier to manage style elements via a single, linked sheet. When the time comes for a minor style update, such as a change in the color of article headers, the change can be implemented throughout the site in a few seconds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then she was part of the &lt;a href="https://en.wikipedia.org/wiki/Web_Standards_Project"&gt;WaSP (Web Standards Project)&lt;/a&gt;, including Jeffrey Zeldmann and others, an effort to bring interop in between browsers and educate Web developers on using Web Standards.&lt;/p&gt;
&lt;p&gt;A &lt;a href="http://web.archive.org/web/20000818092018/http://www.molly.com/molly/index.html"&gt;capture of Molly's site in 2000&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was hired at W3C in July 2000 to work on improving the quality of W3C specifications. And I had a long time interest in also improving the knowledge of W3C specs for the French community.&lt;/p&gt;
&lt;p&gt;On May 2002, I was attending the &lt;a href="https://web.archive.org/web/20100710142031/http://www2002.org/"&gt;World Wide Web Conference in Hawaii&lt;/a&gt; and I met Molly there for the first time. We had a long discussion (seating on chairs near the pool) about evangelization efforts, the W3C, WasP and the role that each could play. Together with &lt;a href="https://olivier.thereaux.net/"&gt;Olivier Théreaux&lt;/a&gt; (working at W3C at that time), we had also a strong desire to have a better relationship of W3C with the Web developers community and were discussing similar efforts.&lt;/p&gt;
&lt;p&gt;We created the &lt;a href="https://lists.w3.org/Archives/Public/public-evangelist/"&gt;public-evangelist mailing-list at W3C&lt;/a&gt;. She introduced &lt;a href="https://lists.w3.org/Archives/Public/public-evangelist/2002Jul/0008.html"&gt;herself on the list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then I met her regurlaly in my professional career, on conferences, at meetings and we even worked together in the Opera Developer Relations Team in 2011.&lt;/p&gt;
&lt;p&gt;Today on Mastodon and blogs, you will see a lot of messages on how important she had been in the life of people from many continents, many places, for people who praised the Web profession as a craft.&lt;/p&gt;
&lt;p&gt;Thanks for all the magical memories and your unconditional love for the Web.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>The lucky day of me falling hard professionally</title><link href="https://www.otsukare.info/2023/08/31/career-mistakes" rel="alternate"></link><published>2023-08-31T08:05:00+09:00</published><updated>2023-08-31T21:25:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-08-31:/2023/08/31/career-mistakes</id><summary type="html">&lt;p&gt;Yes, you will do mistakes in your career. This one taught me a lot of things.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Let me tell you a story…&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pawn of lucky cat (manekineko) in the air with my reflection in the window" src="https://www.otsukare.info/images/20230831-manekineko.jpg"&gt;&lt;/p&gt;
&lt;p&gt;In my first professional year (~1995/1996) as a ~~web developer~~, well webmaster at that time, I was working on the BNP website. Yes, &lt;strong&gt;the&lt;/strong&gt; &lt;a href="https://mabanque.bnpparibas"&gt;BNP French bank website&lt;/a&gt;, except at that time it was only a couple of hundreds static web pages (maybe around 300).&lt;/p&gt;
&lt;p&gt;The client asked us to fix the footer on all these html files. The job was assigned to me.&lt;/p&gt;
&lt;p&gt;I opened the local website FTP folder with all the files in it. I started to look at the HTML and noticed a simple search and replace would not do it.&lt;/p&gt;
&lt;p&gt;Let's use &lt;strong&gt;Regex for parsing/fixing HTML&lt;/strong&gt;. Haha.&lt;/p&gt;
&lt;p&gt;Very proud of my regex, I executed it on all files. Sure I had done a good job! I dropped the folder in the FTP application and all files on the live site were replaced.&lt;/p&gt;
&lt;p&gt;Oooops!&lt;/p&gt;
&lt;p&gt;I had made a mistake in my regex. I replaced every characters in the HTML by character + space. The site was now displaying the raw ascii characters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;lt; H T M L &amp;gt;
&amp;lt; H E A D &amp;gt;
&amp;lt; T I T L E &amp;gt; B N P &amp;lt; / T I T L E &amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and so on. The roughly 300 files. I had no backup. Cold sweat.&lt;/p&gt;
&lt;p&gt;We were around 6 or 7 people working in this Web agency as webmasters. I asked everyone&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;to stop everything they were doing.&lt;/li&gt;
&lt;li&gt;to not visit the BNP website.&lt;/li&gt;
&lt;li&gt;to save locally every cached files in their browser history and/or their local backup if they had and send them to me.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On a couple of hours we have been able to recreate the site and with a bit of manual work too.&lt;/p&gt;
&lt;p&gt;That was one of my most formative mistakes at the beginning of the Web.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Work on a backup.&lt;/li&gt;
&lt;li&gt;Do not synchronize before checking locally.&lt;/li&gt;
&lt;li&gt;Install a local web server on your computer.&lt;/li&gt;
&lt;li&gt;Browser caching is cool!&lt;/li&gt;
&lt;li&gt;Teams are awesome. You are not alone. You can reach out for help.&lt;/li&gt;
&lt;li&gt;Create a better team process for working on sites.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags"&gt;&lt;strong&gt;Do not use Regex for parsing HTML&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Mistakes will happen. Learn from them.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Webcompat Outreach, Mon Amour…</title><link href="https://www.otsukare.info/2023/05/23/webcompat-outreach" rel="alternate"></link><published>2023-05-23T14:00:00+09:00</published><updated>2023-05-25T07:10:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-05-23:/2023/05/23/webcompat-outreach</id><summary type="html">&lt;p&gt;About some of the challenges of webcompat outreach and what you can do.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I was listening a &lt;a href="https://www.igalia.com/chats/baseline"&gt;podcast&lt;/a&gt; by &lt;a href="https://bkardell.com"&gt;Brian Kardell&lt;/a&gt; and &lt;a href="https://meyerweb.com"&gt;Eric Meyer&lt;/a&gt;. Toward the end, they are mentioning the challenges of outreach in the context of broken Web sites.&lt;/p&gt;
&lt;p&gt;Brian says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It would have to be, enough people would have to complain. A &lt;strong&gt;browser wouldn't tell a lie&lt;/strong&gt; if they could reach out and get you to update it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote in the past &lt;a href="https://www.otsukare.info/2013/11/08/ua-override"&gt;about the need for browsers to lie to websites&lt;/a&gt; and the consequences for both the websites.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Websites fails to support a browser A for a reason X. Sometimes not enough market share for them to care.&lt;/li&gt;
&lt;li&gt;The browser A lies to be able to get the right code path.&lt;/li&gt;
&lt;li&gt;The websites analytics show that browser A is not accessing the website.&lt;/li&gt;
&lt;li&gt;Goto 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;And if you wanted to update my website or your website, that would be relatively easy. They would just send us an email and we'd be like, 'Oh, crap, let me fix that right away.'&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's not that easy. It is still hard to contact individuals. It takes time. The person has sometimes no real control over their "personal website". And the Benefits/Cost Ratio is very low. (Note that Brian and Eric &lt;a href="https://mastodon.cloud/@bkardell@toot.cafe/110418187943254668"&gt;were talking about their actual personal websites&lt;/a&gt; and indeed this is easier to contact public tech savy people.)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But when it comes to Wells Fargo, or Yahoo, or some big site with lots and lots and lots of people who go there…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here it depends on the category of websites. Yahoo! is a lot easier to contact, than certain types of websites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bank&lt;/li&gt;
&lt;li&gt;Casino&lt;/li&gt;
&lt;li&gt;Illegal streaming&lt;/li&gt;
&lt;li&gt;certain Adult content&lt;/li&gt;
&lt;li&gt;Governments&lt;/li&gt;
&lt;li&gt;All sites which are flyers or one-off marketing stunts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another parameter: culture!&lt;/p&gt;
&lt;p&gt;The structure of business for creating websites and the relationships of the Web developers with their direct and indirect hierarchy is not the same depending on the regions of the world. For some Web developers it will be very hard to be able to challenge the decision making process with regards to a website. In some circumstances, the bottom-up approach of contacting will not work, and you would need to go to a top-down approach.&lt;/p&gt;
&lt;p&gt;Brian continues:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CNN.com, right. And can we actually reach them? Can we get them to change it? Even worse, for ones that are under the covers, they're the same, but you don't know. They resell, effectively. It's a website's package and it gets very, very hard to know who to reach. They're unresponsive, because they've sort of outsourced their website, really. So there's not always a person you can reach out to. But in the meantime, everybody's going to complain, so they'll lie. And those are the sites really. Those sites are going to be included every time. You know what I mean?The things that we estimate usage on are estimated from looking at the HP requests to lots and lots and lots of websites. And then it's extrapolated from there. But the set of websites is which ones are popularly loaded. And in the grand scheme of things, our websites are not destinations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So it's when I thought about the title of this post: &lt;strong&gt;Webcompat Outreach, Mon Amour&lt;/strong&gt;. Last time, I used that reference, it put me in hot waters, because the person, reading this in a comment, thought I was literal and actually calling her "Mon Amour", while I was making a reference to &lt;a href="https://en.wikipedia.org/wiki/Hiroshima_mon_amour"&gt;Hiroshima Mon Amour&lt;/a&gt;, a movie by Alain Resnais, and written by Marguerite Duras. Culture differences as mentioned earlier. This poetic movie is subtly revealing our tensions at a global and personal level.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Still from the movie where the main actress says: Sometimes we have to avoid thinking about the problems life presents. Otherwise we'd suffocate." src="https://www.otsukare.info/images/20230523-hiroshima-mon-amour.gif"&gt;&lt;/p&gt;
&lt;p&gt;Hence webcompat outreach where the simple minimal code mistakes or choices affects a large number of people. Each decisions we make have consequences on the balance of the ecosystem. We pour love into our art craft and still be constrained by the machinery of the administration.&lt;/p&gt;
&lt;p&gt;I have written about outreach multiple times. You do not need to work for a big company to be able to contact a website, and every invidual can help by communicating clearly to people handling the website presenting issues. This is not an impossible task. It just takes patience, courage and resilience.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://www.otsukare.info/2016/02/05/bug-ready-for-outreach-howto"&gt;what do you need to do before doing outreach&lt;/a&gt;, my last section, mentioned all the reasons why the outreach might fail. There are techniques to try to find people online and to track down who to contact. On the &lt;a href="https://webcompat.com/"&gt;webcompat.com&lt;/a&gt; website, I had written about &lt;a href="https://webcompat.com/contributors/site-outreach"&gt;different techniques to find a way to reach the right person&lt;/a&gt; and the attitudes you need to have:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Be tactful&lt;/strong&gt;: People we are trying to reach have their own set of constraints, bosses, economic choices etc. "Your web site is bad" will not lead anywhere, except NOT getting the site fixed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be humble&lt;/strong&gt;: We are no better, we also make mistakes in practice. Our own recommendations can become outdated as technical or economic circumstances change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let it go&lt;/strong&gt;: Sometimes outreach just doesn't work. The person at the end of the other line may say "no" or worse, may not answer. It can be very frustrating. It's okay. Accept it and move on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be passionate&lt;/strong&gt;: The passion is in being able to find the right contact in a company without harassing them. Every effort helps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Share with consideration&lt;/strong&gt;: Share any contact you attempted or made in the issue comments section. It helps everyone to know the status so they can pitch in or not repeat work. That said - be careful to not disclose private information such as names and emails. You may simply say: "I contacted someone at $COMPANY", "Someone from $COMPANY said this…"&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Web Inspector Search Regex</title><link href="https://www.otsukare.info/2023/05/09/web-inspector-regex" rel="alternate"></link><published>2023-05-09T10:20:00+09:00</published><updated>2023-05-09T10:57:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-05-09:/2023/05/09/web-inspector-regex</id><summary type="html">&lt;p&gt;Web Inspector Search feature allows to use regex expression.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Finding the right keyword in a search among thousand of lines of CSS, JavaScript, HTML code can be dreadful. There are solutions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A lot of bouddha sculpted in wood, which looks very similar" src="https://www.otsukare.info/images/20230509-bouddha.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I was searching for &lt;code&gt;navigator.userAgent&lt;/code&gt; on the NYTimes website. All developer tools have search features. In Safari &lt;a href="https://webkit.org/web-inspector/"&gt;Web Inspector&lt;/a&gt;, Command + Shift + F will start the search tab.&lt;/p&gt;
&lt;p&gt;The matched results for &lt;code&gt;userAgent&lt;/code&gt; are &lt;code&gt;userAgent&lt;/code&gt; but also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isInWebViewByUserAgent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;userAgentData&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getUserAgent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;userAgentIndicatesApp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UserAgentClientHints&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wanted to be able to reduce the search space. Let's try regex.&lt;/p&gt;
&lt;p&gt;So I searched for&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\.userAgent&lt;/code&gt; to match only the strings starting with a dot. We can't match only &lt;code&gt;navigator.userAgent&lt;/code&gt; because someone might have made a variable of it. But this is not enough. I also wanted to remove other references to an object with a trailing names, by avoiding any additional ASCII characters.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\.userAgent[^a-zA-Z]+&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That's it.&lt;/p&gt;
&lt;p&gt;To access this feature you need to go to Settings in Web Inspector, then General, then check Regular Expression in the search section.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the Web Inspector with the regex search for UserAgent" src="https://www.otsukare.info/images/20230509-web-inspector-regex.png"&gt;&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Blade Runner 2023</title><link href="https://www.otsukare.info/2023/02/03/blade-runner" rel="alternate"></link><published>2023-02-03T16:30:00+09:00</published><updated>2023-02-03T16:39:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-02-03:/2023/02/03/blade-runner</id><summary type="html">&lt;p&gt;Never Ending Story.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Graffiti of a robot on a wall with buildings in the background." src="https://www.otsukare.info/images/20230203-robot.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Webcompat engineers will never be over their craft. I've seen things you people wouldn't believe. Large websites broken off the shoulder of developer tools. I watched Compat-beams glitter in the dark near the Interoperability Gate. All those moments will be lost in time, like tears in rain. &lt;a href="https://www.youtube.com/watch?v=NoAzpa1x7jU"&gt;Time to die&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In other news: &lt;a href="https://webkit.org/blog/13706/interop-2023/"&gt;Pushing Interop Forward in 2023&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now we are pleased to announce this year’s Interop 2023 project! Once again, we are joining with Bocoup, Google, Igalia, Microsoft, and Mozilla to move the interoperability of the web forward.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Quirks, Site Interventions And Fixing Websites</title><link href="https://www.otsukare.info/2023/01/16/webkit-quirks" rel="alternate"></link><published>2023-01-16T23:11:00+09:00</published><updated>2023-01-16T23:12:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2023-01-16:/2023/01/16/webkit-quirks</id><summary type="html">&lt;p&gt;Quirks are here to fix broken websites. What does that mean?&lt;/p&gt;</summary><content type="html">&lt;p&gt;Jelmer recently asked : "&lt;a href="https://front-end.social/@jelmerdemaat@mastodon.social/109681646047565553"&gt;What is Site Specific Hacks?&lt;/a&gt;" in the context of the Web Inspector.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Red cinema building with windows and a sign cellphone repair." src="https://www.otsukare.info/images/20230116-repair.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Safari Technical Preview 161 shows a new button to be able to activate or deactivate Site Specific Hacks. But what are these?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Panel in the Web inspector helping to activate or deactivate some options." src="https://www.otsukare.info/images/20230116-webinspector.png"&gt;&lt;/p&gt;
&lt;h2&gt;Site Specific Hacks?&lt;/h2&gt;
&lt;p&gt;Site Specific Hacks are pieces of WebKit code (called Quirks internally) to change the behavior of the browser in order to repair for the user a broken behavior from a website.&lt;/p&gt;
&lt;p&gt;When a site has a broken behavior and is then not usable by someone in a browser, there are a couple of choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the broken behavior is wide spread across the Web, and some browsers work with it, the standard specification and the implementation need to be changed.&lt;/li&gt;
&lt;li&gt;If the broken behavior is local to one or a small number of websites, there are two non-exclusive options&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.otsukare.info/2015/05/11/how-to-contacts"&gt;Outreach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Quirks.cpp"&gt;Quirk&lt;/a&gt; (WebKit), &lt;a href="https://github.com/mozilla-extensions/webcompat-addon"&gt;Site Intervention&lt;/a&gt; (Gecko), Patch (Presto)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outreach improves the Web, but it is costly in time and effort. Often it's very hard to reach the right person, and it doesn't lead necessary to the expected result. Websites have also &lt;a href="https://www.otsukare.info/2014/11/04/web-agencies-priorities-skills"&gt;their own business priorities&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A site specific hack or a quirk in WebKit lingo means a fix to help the browser cope with a way of coding of the Website which is failing in a specific context. They are definitely bandaid and not a strategy of development. They should be really here to give the possibility for someone using a browser to have a good and fluid experience. Ideally, outreach would be done in parallel and we would be able to remove the site specific hack after a while.&lt;/p&gt;
&lt;h2&gt;A Recent Example : FlightAware Webapp&lt;/h2&gt;
&lt;p&gt;I recently removed a &lt;a href="https://github.com/WebKit/WebKit/pull/8233"&gt;quirk in WebKit&lt;/a&gt;, which was put in place in the past to solve an issue.&lt;/p&gt;
&lt;p&gt;The bug was manifesting for a WebView on iOS applications with devices where &lt;code&gt;window.devicePixelRatio&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;with this function&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerReused&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerReused&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;containerReused&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;div&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;absolute&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100%&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100%&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;absolute&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformOrigin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;top left&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which is comparing the equivalence of two strings: &lt;code&gt;i.canvas.style.transform&lt;/code&gt; with the value&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(matrix(0.333333, 0, 0, 0.333333, 0, 0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and &lt;code&gt;e&lt;/code&gt; with the value&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(matrix(0.3333333333333333, 0, 0, 0.3333333333333333, 0, 0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The matrix string was computed by:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Je&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;matrix(&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So these two string clearly are different, then the code above was never executing.&lt;/p&gt;
&lt;p&gt;in &lt;a href="https://drafts.csswg.org/cssom/#serialize-a-css-component-value"&gt;CSSOM specification for serialization&lt;/a&gt;, it is mentionned:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;number&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A base-ten number using digits 0-9 (U+0030 to U+0039) in the shortest form possible, using "." to separate decimals (if any), rounding the value if necessary to not produce &lt;strong&gt;more than 6 decimals&lt;/strong&gt;, preceded by "-" (&lt;code&gt;U+002D&lt;/code&gt;) if it is negative.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It was not always like this, in the past. The specification got changed at a point the implementations changed, and the issue surfaced once WebKit became compliant with the specification.&lt;/p&gt;
&lt;p&gt;The old code was like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderFrame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelRatio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layerStatesArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layerIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelTransform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;qe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inversePixelTransform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelTransform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Je&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelTransform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// cut for brevity&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Specifically this line could be fixed like this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelTransform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That would probably help a lot. Note that Firefox, and probably chrome may have had the same issue on devices where &lt;code&gt;window.devicePixelRatio&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Outreach worked and they changed the code, but in the meantime the quirk was here to help people have a good user experience.&lt;/p&gt;
&lt;h2&gt;Why Deactivating A Quirk In The Web Inspector?&lt;/h2&gt;
&lt;p&gt;Why does the Web Inspector give the possibility to deactivate the site specific hacks aka Quirks?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Web developers for the impacted websites need to know if their code fix solve the current. So it's necessary for them to be able to understand what would be the behavior of the browser without the quirk.&lt;/li&gt;
&lt;li&gt;Browser implementers and QA need to know if a quirk is still needed for a specific website. Deactivating them gives a quick way to tests if the quirk needs to be removed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Could You Help WebKit Having Less Quirks?&lt;/h2&gt;
&lt;p&gt;The main &lt;a href="https://github.com/WebKit/WebKit/blob/main/Source/WebCore/page/Quirks.cpp"&gt;list of Quirks&lt;/a&gt; is visible in the source code of WebKit. If you are part of a site for which WebKit had to create a quirk, do not hesitate to contact me on &lt;a href="https://github.com/karlcow"&gt;GitHub&lt;/a&gt; or by mail or on &lt;a href="https://mastodon.cloud/@karlcow"&gt;mastodon&lt;/a&gt;, and we could find a solution together to remove the Quirk in question.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="css"></category></entry><entry><title>"Thousand" Values of CSS</title><link href="https://www.otsukare.info/2022/10/25/css-values-definitions" rel="alternate"></link><published>2022-10-25T12:00:00+09:00</published><updated>2022-10-25T12:00:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-10-25:/2022/10/25/css-values-definitions</id><summary type="html">&lt;p&gt;Let's try to have a better grasp on the types of CSS values.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.w3.org/2022/09/TPAC/"&gt;W3C TPAC 2022&lt;/a&gt; in Vancouver is over. It was strange to meet after these 3 years away. There would be a lot more to say about this. During the &lt;a href="https://www.w3.org/Style/CSS/"&gt;CSS WG&lt;/a&gt; meetings, participants are talking about &lt;strong&gt;all kind of CSS values&lt;/strong&gt;. It's quickly confusing.&lt;/p&gt;
&lt;p&gt;The processing order is explained in details in the &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#value-stages"&gt;Cascading and Inheritance Level 5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="night on the beach in Vancouver." src="https://www.otsukare.info/images/20221025-vancouver.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Actual Value&lt;/h2&gt;
&lt;p&gt;There is not really a definition for the actual value.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A used value is in principle ready to be used, but a user agent may not be able to make use of the value in a given environment. For example, a user agent may only be able to render borders with integer pixel widths and may therefore have to approximate the used width. Also, the font size of an element may need adjustment based on the availability of fonts or the value of the font-size-adjust property. The &lt;strong&gt;actual value&lt;/strong&gt; is the used value after any such adjustments have been made.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#actual"&gt;4.6. Actual Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;p&gt;if I had to rewrite this, I would probably say:&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;actual value&lt;/em&gt; is the used value after any adjustments made depending for the computing environment context.&lt;/p&gt;
&lt;p&gt;Think for example, about rounding adjustments when drawing on a screen for a certain resolution.&lt;/p&gt;
&lt;h2&gt;Used Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;used value&lt;/strong&gt; is the result of taking the computed value and completing any remaining calculations to make it the absolute theoretical value used in the formatting of the document.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#used"&gt;4.5. Used Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;p&gt;Let's reuse the example of the specification.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, a declaration of &lt;code&gt;width: auto&lt;/code&gt; can’t be resolved into a length without knowing the layout of the element’s ancestors, so the computed value is &lt;code&gt;auto&lt;/code&gt;, while the used value is an absolute length, such as &lt;code&gt;100px&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Computed Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;computed value&lt;/strong&gt; is the result of resolving the specified value as defined in the “Computed Value” line of the property definition table, generally absolutizing it in preparation for inheritance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#computed"&gt;4.4. Computed Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;p&gt;For example, when we specify the &lt;code&gt;font-size&lt;/code&gt; of a paragraph, when the default font-size of the document is &lt;code&gt;16px&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="kt"&gt;em&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The computed value will be &lt;code&gt;32px&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;🚨 &lt;a href="https://w3c.github.io/csswg-drafts/cssom-1/#dom-window-getcomputedstyle"&gt;&lt;code&gt;window.getComputedStyle(elt)&lt;/code&gt;&lt;/a&gt; doesn't return systematically the computed value. It returns the resolved value (see below)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;width:auto;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;confusing?&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;para&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;usedValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;para&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The computed value will be &lt;code&gt;auto&lt;/code&gt;, but the the resolved value will be the current width of the parent element.&lt;/p&gt;
&lt;h2&gt;Specified Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;specified value&lt;/strong&gt; is the value of a given property that the style sheet authors intended for that element. It is the result of putting the cascaded value through the defaulting processes, guaranteeing that a specified value exists for every property on every element.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#computed"&gt;4.3. Specified Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;falls&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;and streams&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To extract the specified value&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;will return &lt;code&gt;red&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you need access to the full declaration, use &lt;code&gt;cssRule.cssText&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;cssText&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;will return &lt;code&gt;p.a { color: red; }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To not be confused with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssText&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which will return an empty string, because there is no style attribute on the element.&lt;/p&gt;
&lt;h2&gt;Cascaded Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;cascaded value&lt;/strong&gt; represents the result of the cascade: it is the declared value that wins the cascade (is sorted first in the output of the cascade). If the output of the cascade is an empty list, there is no cascaded value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#cascaded"&gt;4.2. Cascaded Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;falls&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;and streams&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;cascaded value&lt;/strong&gt; for &lt;code&gt;&amp;lt;p class="a"&amp;gt;&lt;/code&gt; is &lt;code&gt;red&lt;/code&gt;. Note that the used value will be &lt;code&gt;rgb(255, 0, 0)&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Declared Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Each property declaration applied to an element contributes a declared value for that property associated with the element.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#declared"&gt;4.1. Declared Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;h2&gt;Initial Value&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Each property has an initial value defined in the property’s definition table. If the property is not an inherited property and the cascade does not result in a value then the specified value of the property is its initial value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#initial-values"&gt;7.1 Initial Values, CSS Cascading and Inheritance Level 5&lt;/a&gt;, Editor’s Draft, 21 October 2022&lt;/p&gt;
&lt;p&gt;For example, the &lt;strong&gt;initial value&lt;/strong&gt; on &lt;a href="https://w3c.github.io/csswg-drafts/css-backgrounds/#background-color"&gt;&lt;code&gt;background-color&lt;/code&gt;&lt;/a&gt; is &lt;code&gt;transparent&lt;/code&gt;. This is the color that you can find in the default CSS.&lt;/p&gt;
&lt;h2&gt;Resolved Value&lt;/h2&gt;
&lt;p&gt;This time, we changed specification.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;getComputedStyle()&lt;/code&gt; was historically defined to return the "computed value" of an element or pseudo-element. However, the concept of "computed value" changed between revisions of CSS while the implementation of &lt;code&gt;getComputedStyle()&lt;/code&gt; had to remain the same for compatibility with deployed scripts. To address this issue this specification introduces the concept of a resolved value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in &lt;a href="https://w3c.github.io/csswg-drafts/cssom-1/#resolved-values"&gt;9. Resolved Values, CSS Object Model (CSSOM)&lt;/a&gt;, Editor’s Draft, 18 October 2022&lt;/p&gt;
&lt;p&gt;The resolved value is either the computed value or the used value. This is dependent of each property.&lt;/p&gt;
&lt;h2&gt;Relative value&lt;/h2&gt;
&lt;p&gt;This is not really defined, but this is mentioned in computed value explanations.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A specified value can be either absolute (i.e., not relative to another value, as in red or 2mm) or relative (i.e., relative to another value, as in auto, 2em). Computing a relative value generally absolutizes it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in the &lt;a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#example-29410c97"&gt;example 12 of the section about computed Value&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example anything such as &lt;code&gt;em&lt;/code&gt;, percentages, relative URLs, etc.&lt;/p&gt;
&lt;h2&gt;Absolute Value&lt;/h2&gt;
&lt;p&gt;Not defined but the term is used.The absolute value is a value which has no dependency on the environment, such as red or 3px.&lt;/p&gt;
&lt;p&gt;If I have forgotten some. Let me know.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="css"></category></entry><entry><title>Filter your mail in a dated space server side with Sieve</title><link href="https://www.otsukare.info/2022/06/20/dated-space-mailbox-with-sieve" rel="alternate"></link><published>2022-06-20T15:15:00+09:00</published><updated>2022-06-20T15:20:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-06-20:/2022/06/20/dated-space-mailbox-with-sieve</id><summary type="html">&lt;p&gt;Dated space mailboxes is one of the strategies to filter email with high volumes. Here the techniques with Sieve.&lt;/p&gt;</summary><content type="html">&lt;p&gt;When it comes to sort out your emails, there are many strategies. Since I have been working at W3C, I'm a fan of dated spaces. I apply this strategy to my emails using Sieve.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mailbox stuffed with old letters and papers." src="https://www.otsukare.info/images/20220620-mailbox-burp.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Dated Space?&lt;/h2&gt;
&lt;p&gt;A dated space is a way to organize the information by date folders. Here is an example on my folders.&lt;/p&gt;
&lt;p&gt;&lt;img alt="organization by dates of folders." src="https://www.otsukare.info/images/20220620-dated-folders.png"&gt;&lt;/p&gt;
&lt;p&gt;and here the same type of organization for mails.&lt;/p&gt;
&lt;p&gt;&lt;img alt="organization by dates of folders." src="https://www.otsukare.info/images/20220620-dated-mailbox.png"&gt;&lt;/p&gt;
&lt;h3&gt;Why would you do that?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;It creates a unique space&lt;/strong&gt;. The arrow time is irreversible so there is no issue with creating new folders.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It limits the number of items by folders&lt;/strong&gt;. When a folder has too many items, it becomes harder to find what you need.&lt;/li&gt;
&lt;li&gt;It is actually helpful, because &lt;strong&gt;our memory has a lot of anchors in time&lt;/strong&gt; and we can find easily stuff by remembering when we created it. (a location-based could be an interesting experiment and has useful applications in some circumstances such as photos for example, but that's for another blog post.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS search engines&lt;/strong&gt;: Smart folders based on keywords, types, etc. will make it easier to find stuff. And the files can now belong in multiple contexts. Everything everywhere all at once.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Dated Space For Mail With Sieve&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://sieve.info/"&gt;Sieve&lt;/a&gt; is a language for filtering e-mail messages. It resides on the server side. So it requires that your mail provider accepts that you can manage sieve rules for your own mail.&lt;/p&gt;
&lt;p&gt;I filter all my incoming mails indifferently of their nature to a dated space. Everything is mixed. And I restructure my emails folders with smart mailboxes. Then I can suppress folders which are not valid anymore, create new ones, all of this without touching any emails.&lt;/p&gt;
&lt;h3&gt;Sieve Script&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fileinto&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;date&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;mailbox&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;variables&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;# filter emails based on the date and move them to a folder.&lt;/span&gt;
&lt;span class="c1"&gt;# mail from June 2022, will be saved into /2022/06&lt;/span&gt;
&lt;span class="c1"&gt;# set values for month and year&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;currentdate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;year&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;year&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${1}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;currentdate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;month&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;month&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${1}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;# mv the message into the right mail folder&lt;/span&gt;
&lt;span class="n"&gt;fileinto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;${year}/${month}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It's a very simple script and works like a charm. Sieve is a very powerful language. It's possible to do all kind of classifications.&lt;/p&gt;
&lt;p&gt;Oh… and yes… my Inbox is obviously by the nature of the script always… 0.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="tools"></category></entry><entry><title>Get browsers version number on macOS (zsh)</title><link href="https://www.otsukare.info/2022/06/10/get-browsers-version-macos-zsh" rel="alternate"></link><published>2022-06-10T07:00:00+09:00</published><updated>2022-06-10T07:00:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-06-10:/2022/06/10/get-browsers-version-macos-zsh</id><summary type="html">&lt;p&gt;When testing in multiple browsers, it's not necessary pleasant to copy and paste the information in windows. Here a little zsh script.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm not sure why I had not written this before, but it kind of hit me when doing testing this week, that I could optimize a bit more my time.&lt;/p&gt;
&lt;p&gt;&lt;img alt="statues in the forest with a red beanny." src="https://www.otsukare.info/images/20220610-jizo.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This is a shell (zsh) script and macOS only. It reads the &lt;a href="https://gist.github.com/karlcow/b1d992df616bc6f4397fa96035731a20"&gt;version information of a list of browsers&lt;/a&gt; and spills them out in a nice and ready to be copied and pasted in a bug report.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/zsh&lt;/span&gt;

&lt;span class="nv"&gt;APP_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/Applications/&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;INFO_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.app/Contents/Info.plist&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;browsers&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Safari Technology Preview&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Firefox Nightly&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Google Chrome Canary&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Safari&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Firefox&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Google Chrome&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Microsoft Edge Canary&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;browser_name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;(@k)browsers&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;full_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APP_PATH&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;browser_name&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;INFO_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$full_path&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;browser_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;defaults&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$full_path&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;CFBundleShortVersionString&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;browser_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;browser_version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What it looks like once rendered. I need to update a couple of things.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Safari Technology Preview 15.4
Firefox Nightly 103.0a1
Safari 15.5
Firefox 99.0
Microsoft Edge Canary 104.0.1285.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="tools"></category></entry><entry><title>How to make « cidre » of Normandy</title><link href="https://www.otsukare.info/2022/05/16/normandy-cider" rel="alternate"></link><published>2022-05-16T21:00:00+09:00</published><updated>2022-05-16T21:44:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-05-16:/2022/05/16/normandy-cider</id><summary type="html">&lt;p&gt;Sometimes, things are just part of your cultural tradition. Here a rough explanation on how to prepare a drink from Normandy, my region of origin.&lt;/p&gt;</summary><content type="html">&lt;p&gt;While I'm living in Japan, I'm from the &lt;a href="https://en.wikipedia.org/wiki/Normandy"&gt;Normandy region&lt;/a&gt; in France. That's me as a child helping my grand father in an orchard.&lt;/p&gt;
&lt;p&gt;&lt;img alt="child filling bags with apples." src="https://www.otsukare.info/images/20220516-karl.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This is a region which is traditionally known for cows and dairy products (milk, butter, cheese like Camembert, Pont-L'evêque, Livarot, Neufchâtel, etc.) and also a region which led to the &lt;a href="https://fr.wikipedia.org/wiki/Cidre_de_Normandie"&gt;production of cidre&lt;/a&gt; (French only). The origin is not that clear but probably, people from Normandy have started to make « cidre » in the 12th century. Some competing stories have been developed about the origin. But people were growing apples for a long time already and probably were fermenting them. And a craft emerged.&lt;/p&gt;
&lt;p&gt;The Web is also rich of its individual crafts, developed along the way. Some techniques have been lost, some are thriving. A long series of errors and trials has been essential in perfecting the art of making Websites.&lt;/p&gt;
&lt;p&gt;Fast forward a couple of centuries, and here an image on &lt;strong&gt;my great grand father&lt;/strong&gt;, René. He is collecting the apples in a big bag from his field to prepare « cidre ».&lt;/p&gt;
&lt;p&gt;&lt;img alt="Man filling a bag of apples in an orchard." src="https://www.otsukare.info/images/20220516-rene.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The name of the apples is a long poetic list:&lt;/p&gt;
&lt;p&gt;Blanc Mollet, Girard, Cimetière de Blangy, Argile nouvelle, Fréquin rouge, Gros matois rouge, Bon Henri, Médaille d'or, Petit amer, Binet rouge, Bouquet, Joly rouge, Longue, Bedan, Bouteille, Moulin à vent, Grise Dieppois, Gilet rouge, Doux Veret (petit), Rouge Bruyère, Reine des Pommes, Doux-Evêque précoce, Marin Onfroy, etc.&lt;/p&gt;
&lt;p&gt;Each of them have their own qualities: sweetness, acidity, taste, … Once we have a good mix, we need to wash them carefully and then put them in the grinder.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My grand father&lt;/strong&gt;, Jean, working at the grinder and we can see in the background the press in wood.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Man near the grinder with apples in a big barrel." src="https://www.otsukare.info/images/20220516-jean.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Grinder engraving." src="https://www.otsukare.info/images/20220516-broyeur.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Once the apples have been grinded, we need to let them with the juice exposed to the air for around 8 to 12 hours in a deep container covered by a cloth. The oxydation work will start. The must will get a better color, will be sweeter. The yeast will develop more rapidly. Containers must be as clean as possible.&lt;/p&gt;
&lt;p&gt;Then will start the work with the press.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Press engraving." src="https://www.otsukare.info/images/20220516-press.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The must is layered in 15 to 20 centimeters high layers, separated by layers of straws that will drain the juice.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Press detail engraving." src="https://www.otsukare.info/images/20220516-press-installation.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Once the juice has been drawn, it is put in big barrels where the fermentation process starts. After a while, the juice will be put in bottle. My grand-father was used to go in the cave and to turn the bottles according to the moon phases. He had 3 types of « cidre » in his cave: Very sweet, rough, and something very rough that was basically impossible to drink. The colors were on the bottles: red, grey and blue, a simple spot of paint.&lt;/p&gt;
&lt;p&gt;These techniques are getting lost with the new generations and the industrializations. I wish I had spent more time with him for having a better understanding of the craft.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Different types of apples." src="https://www.otsukare.info/images/20220516-apples.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Now, I probably have a better understanding of the Web than the process of making « cidre ». It's probably why today is my first day working for &lt;a href="https://webkit.org/"&gt;Apple on the WebKit project&lt;/a&gt; to continue my journey in making the Web awesome for everyone: Web Compatibility, standards and interoperability.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gallica.bnf.fr/ark:/12148/bpt6k97981173/"&gt;Engravings coming from Le cidre by Labounoux and Touchard&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/13"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category><category term="job"></category></entry><entry><title>Mozilla, Bye!</title><link href="https://www.otsukare.info/2022/05/04/bye-mozilla" rel="alternate"></link><published>2022-05-04T21:00:00+09:00</published><updated>2022-05-10T17:30:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-05-04:/2022/05/04/bye-mozilla</id><summary type="html">&lt;p&gt;May 4 was my last at Mozilla after almost 9 years.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This year, 2022, May the 4th was my last day at Mozilla.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Trunk from an oak tree and its canopy." src="https://www.otsukare.info/images/20220504-chene.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Alors, l'arbre et son rêveur, ensemble, s'ordonnent, grandissent. Jamais l'arbre, dans le monde du songe, ne s'établit comme un être achevé.
— &lt;a href="http://classiques.uqac.ca/classiques/bachelard_gaston/poetique_de_espace_3e_edition/poetique_de_espace_3e_edition.pdf"&gt;Poétique de l'espace, Gaston Bachelard&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in English&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then, together, the tree and its dreamer, take their places, grow tall. Never, in the dream world, does a tree appear as a completed being.
— &lt;a href="https://archive.org/details/G.BachelardThePoeticsOfSpace/G.%2C%20Bachelard%2C%20The%20Poetics%20of%20Space/"&gt;The poetics of space, Gaston Bachelard&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I &lt;a href="https://www.otsukare.info/2013/08/01/why-now"&gt;started&lt;/a&gt; on July 2, 2013 on a 6 months contract at Mozilla to &lt;a href="https://en.wikipedia.org/wiki/Firefox_OS"&gt;work on Firefox OS&lt;/a&gt; on Web Compatibility issues. I was living in Montréal, Canada at the time.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/lmandel"&gt;Lawrence Mandel&lt;/a&gt; (now at Shopify) trusted and hired me. His first words on our Web Compatibility work at Mozilla were aligned with my ideas and stance for the open Web.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We are here to make the Web more open, not only for making the Web usable on Firefox products. — Lawrence Mandel&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After these 6 months, I moved to Japan and I'm still living there. I'm currently in Tokyo. On the span of 8 years and 10 months, I focused my energy on this mission inside the &lt;a href="https://wiki.mozilla.org/Compatibility"&gt;Web Compatibility&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A person should be able to use the Web with any devices and any browsers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was not alone. The success of a project never relies on a single individual, but a full team of people dedicated to make this mission a reality. At the very beginning, we were three coming from Opera Software, we all had an experience on Web compatibility issues: &lt;a href="https://miketaylr.com/posts/"&gt;Mike Taylor&lt;/a&gt;, &lt;a href="http://www.hallvord.com/"&gt;Hallvord R.M. Steen&lt;/a&gt; and me. Then &lt;a href="https://www.linkedin.com/in/stevenson-adam"&gt;Adam Stevenson&lt;/a&gt; joined. None of the initial team is still at Mozilla. I miss working with &lt;a href="https://www.linkedin.com/in/eric-tsai-9181603a"&gt;Eric Tsai&lt;/a&gt; too. Some people (open contributors) have also &lt;a href="https://webcompat.com/contributors"&gt;participated to the project&lt;/a&gt; like Abdul Rauf, Alexa Roman, Kate Manning, Guillaume Demesy, Reinhart Previano.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://webcompat.com/"&gt;webcompat.com&lt;/a&gt; was setup on purpose &lt;strong&gt;without Mozilla branding&lt;/strong&gt; to invite the &lt;a href="https://github.com/webcompat/webcompat.com/"&gt;participation of all browser implementers&lt;/a&gt; (Apple, Google, Microsoft, Opera, etc.) on solving issues resulting from website mistakes or interoperability issues. Mozilla put the main effort into it and in return webcompat.com helped Mozilla and Firefox Core team to fix a lot of issues.&lt;/p&gt;
&lt;p&gt;The current Web Compatibility team is composed of &lt;a href="https://overengineer.dev/"&gt;Dennis Schubert&lt;/a&gt; (Germany), &lt;a href="https://github.com/jgraham"&gt;James Graham&lt;/a&gt; (UK), &lt;a href="https://www.linkedin.com/in/kberezina"&gt;Ksenia Berezina&lt;/a&gt; (Canada), &lt;a href="https://www.linkedin.com/in/arbuzov-oana-0293abb5"&gt;Oana Arbuzov&lt;/a&gt; (Romania), &lt;a href="https://www.linkedin.com/in/raul-bucata-38657b1b3/"&gt;Raul Bucata&lt;/a&gt; (Romania) and &lt;a href="https://www.linkedin.com/in/thomas-wisniewski-85844b16/"&gt;Thomas Wisniewski&lt;/a&gt; (Canada). This team was distributed across three continents (two since I left), working around the clock to help solving Web compatibility issues. All the work done was in public, shared with others, written down and tracked in the open. This leveraged autonomy and responsibility from everyone in the team. Apart of a lack of a resource, my departure doesn't put in peril the work of the team. Even as I became the team manager 18 months ago, I was not a gatekeeper.&lt;/p&gt;
&lt;p&gt;There is the Webcompat team… then there is the amazing group of Core Engineers who have the open Web deep in their heart. Many left Mozilla, but some of them are still there and they were instrumental in solving interoperability issues.&lt;/p&gt;
&lt;p&gt;Emilio Cobos Álvarez, Daniel Holbert, Jonathan Kew, Masayuki Nakano, Makoto Kato, Brian Birtles, Boris Zbarsky, Hiroyuki Hikezoe, Botond Ballo, Olli Pettay, Henri Sivonen, Anne van Kesteren, Ting-Yu Lin, Cameron McCormack. These lists are dangerous, I keep forgetting people.&lt;/p&gt;
&lt;p&gt;I could talk about all the things which have been solved around text input, CSS flexbox, JavaScript features, DOM and SVG, … but this starts to be long.&lt;/p&gt;
&lt;p&gt;And finally the diagnosis ability of the Webcompat team would be nothing without the dedication of the &lt;a href="https://firefox-dev.tools/"&gt;devtools and performance teams&lt;/a&gt;. They helped us to work better, they develop amazing tools which are useful for the webcompat team and the web developers. They always care about what we do. Nicolas Chevobbe, Julien Wajsberg, Daisuke Akatsuka, Jan Odvarko (Honza), and many others …&lt;/p&gt;
&lt;p&gt;But as Bachelard said above:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Never, in the dream world, does a tree appear as a completed being.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The new chapter is starting on &lt;a href="https://www.timeanddate.com/eclipse/lunar/2022-may-16"&gt;May 16, 2022&lt;/a&gt;. More information on that later apart of the lunar eclipse.&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/12"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category><category term="job"></category></entry><entry><title>Encyclopedia Of Broken UserAgent String Detections</title><link href="https://www.otsukare.info/2022/01/14/broken-ua-detection" rel="alternate"></link><published>2022-01-14T17:17:00+09:00</published><updated>2022-02-16T21:14:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2022-01-14:/2022/01/14/broken-ua-detection</id><summary type="html">&lt;p&gt;Recording the way the User Agent string parsing is failing in scripts.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Did you detect the right user agent string?&lt;/p&gt;
&lt;p&gt;&lt;img alt="cat hidden in a bamboo forest." src="https://www.otsukare.info/images/20220114-cat-bamboo.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This is not a comprehensive encyclopedia, but these are patterns we have met in the past for identifying user agent strings which are broken or future fail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt; Do not use these !&lt;/strong&gt; and if your code is using one form of these, please change it. Tell me if you found new ones.&lt;/p&gt;
&lt;h2&gt;Comparing Strings Instead Of Numbers&lt;/h2&gt;
&lt;p&gt;This was explained in details in &lt;a href="https://miketaylr.com/posts/2021/03/firefox-version-520-works-in-slack.html"&gt;Slack is optimized for Firefox version 520&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The version number of the userAgent is extracted as a string, not an integer.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;browser_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;support_min_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;90&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;support_min_version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;too old&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;supported&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// too old instead of supported as a result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A better pattern here is to use integer&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;browser_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the &amp;quot;100&amp;quot; as a string came from a detection early on&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;support_min_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// integer not a string;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;support_min_version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;too old&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;supported&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// goes to supported as expected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Substring Slicing According To Position&lt;/h2&gt;
&lt;p&gt;The assumption here is that the substring representing the number is two characters after the slash. The &lt;code&gt;8&lt;/code&gt; is for &lt;code&gt;Firefox/&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0&amp;quot;&lt;/span&gt;
&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 67&lt;/span&gt;
&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;quot;10&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A better pattern for this one is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0&amp;quot;&lt;/span&gt;
&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 67&lt;/span&gt;
&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;quot;100.0&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Firefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// 100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Regex Matching Exactly Two Digits&lt;/h2&gt;
&lt;p&gt;This is a fairly common mistake, most of the detection algorithm have been fixed when browsers switched their versions from one digit to two digits, but there is still code out there relying on fixed lengths.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua_100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/91&amp;quot;, &amp;quot;91&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d{2})/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// [&amp;quot;Firefox/91&amp;quot;, &amp;quot;91&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)\./&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/91.&amp;quot;, &amp;quot;91&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/10&amp;quot;, &amp;quot;10&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d{2})/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// [&amp;quot;Firefox/10&amp;quot;, &amp;quot;10&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)\./&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A better pattern would be&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d+)/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/91&amp;quot;, &amp;quot;91&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d+)/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/100&amp;quot;, &amp;quot;100&amp;quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Detecting Firefox on iOS as Android.&lt;/h2&gt;
&lt;p&gt;Many sites have a grid for the minimum version number supported for each browsers. The current Firefox User Agent string on iOS has this pattern.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Mozilla/5.0 (iPhone; CPU OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/33.0 Mobile/15E148 Safari/605.1.15&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Notice that &lt;code&gt;FxiOS/33.0&lt;/code&gt; means Firefox on iOS version 33. Web developers often used a up to date library that will return something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;ua&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Mozilla/5.0 (iPhone; CPU OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/33.0 Mobile/15E148 Safari/605.1.15&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;browser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Firefox&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;33.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;major&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;33&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;engine&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;WebKit&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;605.1.15&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;os&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iOS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;14.4.2&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;device&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;vendor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Apple&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iPhone&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;mobile&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;cpu&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;gpu&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So far so good. The issue starts when the site says: "Oh. It's Firefox on Mobile, so it means this is Android. We support Firefox on Android starting Firefox/78". Then they block the access to the full site, or the video, or asking the user to upgrade their browsers while they are on the latest version of Firefox iOS.&lt;/p&gt;
&lt;p&gt;A better pattern is to detect the OS and/or the engine this browser is working on, and adjust your support matrix. An even better pattern is to have the site handling graceful degradation whichever the version of the browser.&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/11"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="useragent"></category><category term="webcompat"></category></entry><entry><title>Browser regression and tools</title><link href="https://www.otsukare.info/2021/11/17/bisecting-browser-regression" rel="alternate"></link><published>2021-11-17T09:31:00+09:00</published><updated>2021-11-17T22:19:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-11-17:/2021/11/17/bisecting-browser-regression</id><summary type="html">&lt;p&gt;Browsers have tools to find out which commit created a regression.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Sometimes a new release of a nightly version of a browser creates what we call a regression. How do we find out what exactly broke the code?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Illustration of surgery tools." src="https://www.otsukare.info/images/20211117-bistouri.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;What is a regression?&lt;/h2&gt;
&lt;p&gt;In simplified terms, there is a regression when a code used to work and is not working properly after a specific release. For websites, a webpage would stop having the right behavior after updating to a new version of the browser.&lt;/p&gt;
&lt;p&gt;Something was working with commit 𝑛 of the browser and it stopped working with commit 𝑛+1.&lt;/p&gt;
&lt;h2&gt;How do we try to catch regressions before production release?&lt;/h2&gt;
&lt;p&gt;All browsers have different versions. The production release is the one that most people are using. The one which is advertised for people to download on websites and stores. But there are also beta versions and &lt;strong&gt;nightly&lt;/strong&gt; versions.&lt;/p&gt;
&lt;p&gt;The nightly version is a fresh working build with the latest modifications of the day. It's not considered reliable for your main usage. Even if browser implementers try hard to keep them stable, they may break. They may even damage your browser profile. &lt;strong&gt;Use them only if you understand the consequences&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.google.com/chrome/canary/"&gt;Chrome Canary&lt;/a&gt; (Blink) - No nightly release notes?&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mozilla.org/en-US/firefox/all/#product-desktop-nightly"&gt;Firefox Nightly&lt;/a&gt; (Gecko) - &lt;a href="https://blog.nightly.mozilla.org/"&gt;Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webkit.org/downloads/"&gt;Safari Nightly&lt;/a&gt;  (WebKit) - &lt;a href="https://developer.apple.com/safari/technology-preview/release-notes/"&gt;Release Notes only for Safari Tech Preview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How do we find out the exact commit which has broken the browser?&lt;/h2&gt;
&lt;p&gt;You are now using commit 𝑛+𝑚 version which is broken. You want to find out the 𝑛+1 version which has broken the code.&lt;/p&gt;
&lt;p&gt;You start &lt;a href="https://en.wikipedia.org/wiki/Bisection_(software_engineering)"&gt;bisecting the code&lt;/a&gt;. Let's say this is happening in between version 10 and 20 of the code.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verify this is working with 10&lt;/li&gt;
&lt;li&gt;Check this is not working with 20.&lt;/li&gt;
&lt;li&gt;Split the group in two. Pick up 15. Does the bug reproduce?
    Yes. So the issue is in between 10 and 15
    No. So the issue is in between 16 and 20&lt;/li&gt;
&lt;li&gt;Take the new range and repeat and rinse, until you get a unique version.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That can become time consuming. There are tools to help with this task.The tool will download the nightly builds being tested and help figure out which specific commit in the code has broken the code.&lt;/p&gt;
&lt;h2&gt;Bisection tools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.chromium.org/developers/bisect-builds-py"&gt;Chrome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mozilla.github.io/mozregression/"&gt;Firefox&lt;/a&gt;. Probably the easiest to use of the 3. Well documented and even a version with a GUI&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebKit/WebKit/blob/main/Tools/Scripts/bisect-builds"&gt;Safari&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your turn! When you find out a broken Web page next time (when previously, it was working),  follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;open a bug&lt;/li&gt;
&lt;li&gt;Run a regression tool&lt;/li&gt;
&lt;li&gt;give the precise commit where it might have happened.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will speed up a lot the potential fix.&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/10"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="development"></category><category term="webcompat"></category></entry><entry><title>Webcompat issues and the bots!</title><link href="https://www.otsukare.info/2021/10/26/webcompat-automation" rel="alternate"></link><published>2021-10-26T21:43:00+09:00</published><updated>2021-10-26T21:53:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-10-26:/2021/10/26/webcompat-automation</id><summary type="html">&lt;p&gt;Some ideas and contexts around auto-discovering webcompat issues.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Some ideas and contexts around auto-discovering webcompat issues.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Graffiti of a robot on a wall." src="https://www.otsukare.info/images/20211026-robots.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Recently &lt;a href="https://briangrinstead.com/blog/"&gt;Brian Grinstead&lt;/a&gt; asked me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Are you familiar with &lt;a href="https://github.com/marco-c/autowebcompat"&gt;this&lt;/a&gt;?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which I answered: Yes since 2018. And I remembered the challenges and so probably it's worth to do a bit of history on identifying webcompat issues. The objectives being often:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How to massively test websites and their different renderings across browsers?&lt;/li&gt;
&lt;li&gt;How to reduce human time spent on manually testing the site?&lt;/li&gt;
&lt;li&gt;Can we discover the type of issues?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have been doing webcompat work since October 2010 (when I started working at Opera Software with the &lt;a href="https://www.youtube.com/watch?v=IZ6JrBqy0CU"&gt;amazing Opera devrel team&lt;/a&gt;). There's no perfect technique, but there are a couple of things you can try.&lt;/p&gt;
&lt;h2&gt;Screenshots Comparison&lt;/h2&gt;
&lt;p&gt;We often associate webcompat issues with sites which are not looking the same in two different browsers. It's a simplistic approximation but can help in some type of webcompat issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mobile versus desktop&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some websites will adjust their content depending on the user agent strings. They will either deliver a specific content, or redirect to a domain which is friendly for mobile or desktop. This can be directly detected with the homepage of the website. You could quickly identify if a site sends the same design/content to Firefox Android, Safari iOS or a blink browser on Android. This is less and less meaningful, as many websites in the last ten years have switched to responsive design where the content automatically adjusts depending on the size of the screen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rendering Issues&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is slightly more complex. There might be multiple issues with regards to rendering. I'll talk about the caveats later. This could potentially identify a wrong color, a wrong position of the boxes, a difference in details such as scrollbars or boxes radius, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a simple URLs list and using the &lt;a href="https://w3c.github.io/webdriver/webdriver-spec.html"&gt;webdriver API&lt;/a&gt;, it is possible to fetch websites for Gecko, WebKit and Blink and take a screenshot for each of them. It becomes very easy to test the top 1000 websites in a specific locale. You can discriminate visually quickly the screenshots which are different.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt; we said we wanted to be more effective. We can use a bit of maths for this. Let's make 𝑠¹ and 𝑠², the screenshots we want to compare, then we can use a simple library like &lt;a href="https://docs.python.org/3/library/difflib.html"&gt;difflib&lt;/a&gt; in python to compute the similarity of the images.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;diff_ratio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;difflib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quick_ratio&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then it becomes easy to define the &lt;code&gt;diff_ratio&lt;/code&gt; which is acceptable for the series of tests we run. After fixing a threshold this will identify the sites with potential issues. It will &lt;strong&gt;not identify the type of issues&lt;/strong&gt;. It will &lt;strong&gt;not provide a diagnosis&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And the method has some limitations which are interesting to understand if we want to be effective in pre-filtering the issues.&lt;/p&gt;
&lt;h2&gt;Some Limitations Around Screenshots Comparison&lt;/h2&gt;
&lt;p&gt;The screenshots might be different but that doesn't necessary mean there is a webcompat issue. Here some cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Anti-Tracking Mechanisms&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every browser has its own strategy with regards to tracking protection. These are browsers breaking websites on purpose to reduce users fingerprinting. Hence a screenshot for the same site might create different results.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A/B Testing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some sites test A/B scenario for a more profitable user experience. They will send two different versions of the site to different users. If one browser is one pool and the other browser in another pool at the moment of the tests, the screenshots will be different.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Android/iOS banner for apps&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Testing the rendering in between a browser on iOS and a browser on Android will create different results, as the banner for apps will display and link to different stores.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Content&lt;/strong&gt; (News sites/Social Network)&lt;/p&gt;
&lt;p&gt;There's a big category of websites where the content changes or offers rotations of the content in between each reload. Caroussels, ads, news article, user posts, etc. are all likely to modify the screenshots in between two queries in the same browser.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tier 1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some sites provide a different experience to different browsers. This one is more subtle to deal with. They rely more on a business decision. Compare for example the results of Google search on Firefox Android and Google Chrome. Google Chrome definitely receives the Tier 1. Other browsers receive different content. The diagnosis here is not technical, but business priorities.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Quick summary about autowebcompat.&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/marco-c/autowebcompat"&gt;autowebcompat&lt;/a&gt;, that Brian was mentionning, is a nice project from &lt;a href="https://marco-c.github.io/"&gt;Marco Castelluccio&lt;/a&gt; to attempt to auto-detect web compatibility issues. Basically the code tries to learn if screenshots for a similar set of interactions in two different browsers create the same end result. The silverlining being that if there is a difference, there's probably something to better understand. The project used the issues already reported on &lt;a href="https://webcompat.com/"&gt;webcompat.com&lt;/a&gt;. In that sense it's already biaised by the fact that the issues have already been identified as being different. But it make possible to train a model on learning on what creates a webcompat issue.&lt;/p&gt;
&lt;h2&gt;Training A Bot To Identify Valid Issues&lt;/h2&gt;
&lt;p&gt;Recently, &lt;a href="https://github.com/ksy36"&gt;Ksenia&lt;/a&gt; (Mozilla Webcompat team) adjusted &lt;a href="https://hacks.mozilla.org/2019/04/teaching-machines-to-triage-firefox-bugs/"&gt;BugBug&lt;/a&gt; to make it work on GitHub. It helped the webcompat team to move away from the &lt;a href="https://webcompat-ml.readthedocs.io/en/latest/index.html"&gt;old ML classifier&lt;/a&gt; to the BugBug infrastructure.&lt;/p&gt;
&lt;p&gt;It identifies already reported issues and closes the ones which have similar features than previous invalid bugs. Invalid here means not a webcompat issue. Some sites are broken in all browsers, that doesn't create a webcompat issue.&lt;/p&gt;
&lt;h2&gt;Compatipede, Another Project For Auto Webcompat&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/seiflotfy/compatipede"&gt;Compatipede&lt;/a&gt; is a project which predates autowebcompat (started in October 2013!) with the intent to identify more parameters and extend the scope of tests.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Equal redirects&lt;/li&gt;
&lt;li&gt;CSS style compatibility&lt;/li&gt;
&lt;li&gt;Source code compatibility&lt;/li&gt;
&lt;li&gt;Other custom tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was quite interesting as it was trying to explore the unseen issues and avoid the pitfalls of screenshots.&lt;/p&gt;
&lt;p&gt;It had also a modular architecture providing a &lt;a href="https://github.com/seiflotfy/compatipede/tree/master/plugins"&gt;system of custom plugins&lt;/a&gt; to run probes on the payloads sent by the website.&lt;/p&gt;
&lt;h2&gt;SiteCompTester&lt;/h2&gt;
&lt;p&gt;With the same spirit than Compatipede, &lt;a href="https://github.com/hallvors/sitecomptester-extension"&gt;SiteCompTester&lt;/a&gt; was an extension which made possible to target some type of issues and would surface bugs associated with a specific list of known issues. This makes it easier to diagnose a website.&lt;/p&gt;
&lt;h2&gt;Template Extraction Mining&lt;/h2&gt;
&lt;p&gt;The variability of content may be avoided by using a mechanism such as &lt;a href="https://github.com/paulsmith/templatemaker"&gt;templatemaker&lt;/a&gt;. This is a clever little tool which extracts the common features of a series of text and extract a template.&lt;/p&gt;
&lt;p&gt;So let's say for a news website, we could imagine running template maker with one browser for a couple of days and extract its templates. And do the same in parallel with another browser. Then we would compare the templates instead of comparing two unique rendering of the websites. That would probably makes it possible to have a better understanding of certain features variability. This could be applied to markup, to JavaScript, to HTTP headers.&lt;/p&gt;
&lt;h2&gt;Webcompat Auto-Detection Caveats&lt;/h2&gt;
&lt;p&gt;The issue with auto-detection of webcompat issues is that we don't know what is broken before someone experience it in real life. The level of interactions it requires is really delicate.&lt;/p&gt;
&lt;p&gt;And it's why the people working on triaging and diagnosis in the &lt;a href="https://wiki.mozilla.org/Compatibility"&gt;Mozilla webcompat team&lt;/a&gt; are top-notch.
* &lt;a href="https://github.com/softvision-oana-arbuzov"&gt;Oana&lt;/a&gt; and &lt;a href="https://github.com/softvision-raul-bucata"&gt;Raul&lt;/a&gt; are triaging the issues after poor description by most users.
* &lt;a href="https://github.com/ksy36"&gt;Ksenia&lt;/a&gt;, &lt;a href="https://github.com/denschub"&gt;Dennis&lt;/a&gt; and &lt;a href="https://github.com/wisniewskit"&gt;Thomas&lt;/a&gt; are diagnosing relentlessly minified obfuscated code to decipher what is breaking in the current site.&lt;/p&gt;
&lt;h2&gt;Auto-Discovery Of Webcompat&lt;/h2&gt;
&lt;p&gt;The auto-discovery may work in very specific use cases when we know what we try to identify as an issue. Let's say we already identify a pattern in one bug and we want to understand to which extend this bug is affecting other websites. Then using a framework going through the sites and searching for this pattern &lt;strong&gt;might reveal&lt;/strong&gt; potential webcompat issues.&lt;/p&gt;
&lt;p&gt;Targeted surveys are the key to understand the priority of some issues.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="automation"></category><category term="webcompat"></category></entry><entry><title>When iOS will allow other browsers</title><link href="https://www.otsukare.info/2021/09/27/ios-browsers-non-webkit" rel="alternate"></link><published>2021-09-27T09:20:00+09:00</published><updated>2021-09-27T10:00:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-09-27:/2021/09/27/ios-browsers-non-webkit</id><summary type="html">&lt;p&gt;What happens when/if iOS authorizes other rendering engines?&lt;/p&gt;</summary><content type="html">&lt;p&gt;User agent sniffing is doomed to fail. It has this thick layer of opacity and logic, where you are never sure that you will really get in the end.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Stuffed animal through the opaque glass of a window." src="https://www.otsukare.info/images/20210927-opacity.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This happens all the time and will happen again. It's often not only technical, but business related and just human. But let's focus on the detection of Firefox on iOS. Currently, &lt;strong&gt;on iOS, every browsers are using the same rendering engine&lt;/strong&gt;. The one which is mandated by Apple. Be Chrome, Firefox, etc, &lt;a href="https://duckduckgo.com/?q=WKWebView+browsers+chrome+firefox+ios&amp;amp;ia=web"&gt;they all use WKWebView&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the patterns of user agent detections goes like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Which browsers?
    Firefox, Chrome, Safari, etc.&lt;/li&gt;
&lt;li&gt;Which device type?
    Mobile, Desktop, Tablet&lt;/li&gt;
&lt;li&gt;Which browser version?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You have 30s to guess what is missing in this scenario?&lt;/p&gt;
&lt;p&gt;⁞&lt;/p&gt;
&lt;p&gt;⁞&lt;/p&gt;
&lt;p&gt;⁞&lt;/p&gt;
&lt;p&gt;Yes, the OS. Is it iOS or Android? The current logic for some developers is that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Safari + mobile = iOS&lt;/li&gt;
&lt;li&gt;Firefox + mobile = Android&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As of today, Firefox&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on iOS is version 37&lt;/li&gt;
&lt;li&gt;on Android is version 94&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So if the site has &lt;a href="https://github.com/webcompat/web-bugs/issues/67610"&gt;minimum version support grid&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;safari&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firefox&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;49&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firefox&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mobile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tablet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;safari&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;safari&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;android&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here the site sees Firefox… so it must be Android, so it must be Gecko. They have set their minimum support for version 49. Firefox is then considered outdated. Safari minimum version on their grid is 8. So Firefox iOS (WebKitView) would have no issues!&lt;/p&gt;
&lt;h2&gt;Fast Forward To The Future.&lt;/h2&gt;
&lt;p&gt;When Apple authorizes different rendering engines on iOS (yes, I'm on the optimistic side, because I'm patient), I already foresee a huge webcompat issue. The web developers (who are currently right) will infer in some ways that &lt;strong&gt;Firefox on iOS can only be WebKitWebView&lt;/strong&gt;. So the day Gecko is authorized on iOS, we can expect more breakages and ironically some of the webcompat bugs, we currently have will go away.&lt;/p&gt;</content><category term="work"></category><category term="useragent"></category><category term="webcompat"></category></entry><entry><title>Today is my Mozilla 8 years anniversary</title><link href="https://www.otsukare.info/2021/06/21/mozilla-eight-years" rel="alternate"></link><published>2021-06-21T18:40:00+09:00</published><updated>2021-06-21T22:00:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-06-21:/2021/06/21/mozilla-eight-years</id><summary type="html">&lt;p&gt;I have been working 8 years at Mozilla in Webcompat. What a team!&lt;/p&gt;</summary><content type="html">&lt;p&gt;Eight years ago, I have started working at Mozilla.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Archer on a stone wall decoration." src="https://www.otsukare.info/images/20210621-archer.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Hiring, a long process&lt;/h2&gt;
&lt;p&gt;In &lt;a href="https://www.linkedin.com/in/karldubost/"&gt;my employment history&lt;/a&gt;, I have never tried to spread a large net to try to land a job, except probably for my first real job in 1995. I have always carefully chosen the company I wanted to work for. I probably &lt;strong&gt;applied ten times&lt;/strong&gt; on the course of 10 years before landing a job at Mozilla.&lt;/p&gt;
&lt;p&gt;When the Web Compatibility team was created, I applied to one of the positions available in 2013. In April 2013, from Montreal, I flew to Mountain View for a series of job interviews with different Mozilla employees. Most of the interviews were interesting but I remember one engineer was apparently not happy interviewing me and it didn't go very well. I don't remember who, but it left me with a bitter taste at the time. A couple of days later &lt;strong&gt;I was notified that I was not taken&lt;/strong&gt; for the job. While disappointing, I was not surprised. I usually do not perform well during interviews, specifically when you have to demonstrate knowledge instead of articulating the way you work with knowledge. I find interviews a kind of theater.&lt;/p&gt;
&lt;p&gt;But Mozilla came back to me and proposed me a 6 months contract, still in the Mozilla Web Compatibility team but for another role. It was not what I was initially interested by, but why not? It's when I met Lawrence Mandel, who would be my future manager if I landed the job. I liked the contact right away. &lt;strong&gt;I got an offer in June 2013&lt;/strong&gt;. I signed.&lt;/p&gt;
&lt;p&gt;Fast forward 8 years, I'm currently the manager of the Web Compatibility team.&lt;/p&gt;
&lt;h2&gt;Without people, no Web Compatibility!&lt;/h2&gt;
&lt;p&gt;The Web Compatibility team started with 3 persons: Mike Taylor, Hallvord R. M. Steen and myself and at its peak we were probably 10 persons, depending on how we count. We are currently 7 persons including myself. Talking about my 8 years anniversary &lt;strong&gt;doesn't make sense without mentioning the work of the team&lt;/strong&gt;. My work is insignificant if we don't take the globability of what the team is achieving.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Figures on a stone wall decoration." src="https://www.otsukare.info/images/20210621-figures.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« Et par contre, si je communique à mes hommes l’amour de la marche sur la mer, et que chacun d’eux soit ainsi en pente à cause d’un poids dans le cœur, alors tu les verras bientôt se diversifier selon leurs mille qualités particulières. Celui-là tissera des toiles, l’autre dans la forêt par l’éclair de sa hache couchera l’arbre. L’autre, encore, forgera des clous, et il en sera quelque part qui observeront les étoiles afin d’apprendre à gouverner. Et tous cependant ne seront qu’un. Créer le navire ce n’est point tisser les toiles, forger les clous, lire les astres, mais bien donner le goût de la mer qui est un, et à la lumière duquel il n’est plus rien qui soit contradictoire mais communauté dans l’amour. »&lt;/p&gt;
&lt;p&gt;Antoine de Saint-Exupéry. « Citadelle. »&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since the beginning of 2021,&lt;/p&gt;
&lt;p&gt;&lt;a href="https://overengineer.dev/blog/"&gt;Dennis&lt;/a&gt; has drastically reduced the number of old &lt;a href="https://github.com/webcompat/web-bugs/issues?q=is%3Aopen+is%3Aissue+milestone%3Aneedsdiagnosis"&gt;diagnosis&lt;/a&gt; that were on top (or at the bottom?) of our pile. He is also now the module owner for &lt;a href="https://wiki.mozilla.org/Compatibility/Interventions_Releases"&gt;Site Interventions&lt;/a&gt;, which help Mozilla to hotfix websites. When a site is broken and the outreach is unlikely to be successful, this one of the ways we have to fix the website on the fly so the people can continue to enjoy using troubled websites.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jgraham"&gt;James&lt;/a&gt; is the mind and the smooth operator behind &lt;a href="https://web-platform-tests.org/"&gt;Web Platform Tests&lt;/a&gt; at Mozilla. He is doing an amazing job at encouraging Mozilla engineers to develop more Web Platform tests. He makes sure that everything is synchronized with other vendors. Web Platform Tests are essential to be able to discover bugs in specifications and differences in implementations. He is also the core person for the &lt;a href="https://w3c.github.io/webdriver-bidi/"&gt;work on BiDi&lt;/a&gt; at Mozilla. BiDi is another important part of the puzzle of Web Compatibility. Testing manually websites is costly. Webdriver comes here to make it possible for automating the tests of websites functionalities. If the cost is lower, web developers can test their websites in more than one browser and discover and fix their webcompatibility issues before we discover them.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ksy36"&gt;Ksenia&lt;/a&gt; is the owner of &lt;a href="https://github.com/webcompat/webcompat.com/"&gt;webcompat.com&lt;/a&gt; and webcompat ML bot. The &lt;a href="https://github.com/webcompat/webcompat.com/blob/89de7a00b2bc3981a918a588fbdc34d4c0a68234/docs/ml-process.md"&gt;ML bot&lt;/a&gt; helps us to pre-filter the bug and determine if it's a valid webcompat issue. We receive around 700 and 800 bugs a week and that's a lot for our small team. We would not be able to manage without the bot. Tiredlessly she has improved the tools used for minimizing the boring part of the work we do and at the same time, found solutions for helping bug reporters to have a better experience.&lt;/p&gt;
&lt;p&gt;Softvision team: &lt;a href="https://github.com/softvision-oana-arbuzov"&gt;Oana&lt;/a&gt; and &lt;a href="https://github.com/softvision-raul-bucata"&gt;Raul&lt;/a&gt;. I have a lot of respect for the people at Softvision helping Mozilla to do the triage of bugs. This task is sisyphean. Every week, 700 to 800 bugs come in. Luckily enough we have a bot for pre-triage, but when bugs are evaluated being valid. They decipher the old runes of bug reports to understand what the bug reporter suffered and they make it something more compelling for people who will be diagnosing. Previously, we had Ciprian and Sergiu.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/wisniewskit"&gt;Thomas&lt;/a&gt; is the architect of the Site Interventions. He is also making sure that sites continue to work when tracking protection is blocking things. He has implemented lately &lt;a href="https://blog.mozilla.org/security/2021/03/23/introducing-smartblock/"&gt;SmartBlock&lt;/a&gt;. Thomas is this giant person who can touch everything in the Webcompat team, but still super caregiver when we do not understand something. He explains what he does and this is gold. It means that people can grow, evolve and be a better part of themselves.&lt;/p&gt;
&lt;h3&gt;Contributors And Interns&lt;/h3&gt;
&lt;p&gt;The project would be nothing without the contributors and interns who worked with us on making the site, the tools, the process better:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/haseebgit"&gt;Abdul&lt;/a&gt;, &lt;a href="https://github.com/calexity"&gt;Alexa&lt;/a&gt;, &lt;a href="https://github.com/brizental"&gt;Beatriz&lt;/a&gt;, &lt;a href="https://github.com/cch5ng"&gt;Carol&lt;/a&gt;, &lt;a href="https://github.com/deepthivenkat"&gt;Deepthi&lt;/a&gt;, &lt;a href="https://github.com/magsout"&gt;Guillaume&lt;/a&gt;, &lt;a href="https://github.com/laghee"&gt;Kate&lt;/a&gt;, &lt;a href="https://github.com/marimeireles"&gt;Mariana&lt;/a&gt;, &lt;a href="https://github.com/lockettm"&gt;mesha&lt;/a&gt;, &lt;a href="http://github.com/reinhart1010"&gt;Reinhart&lt;/a&gt;, and more…&lt;/p&gt;
&lt;h3&gt;Those Who Were&lt;/h3&gt;
&lt;p&gt;And there are those who have been in the webcompat team and have been participants to its success: &lt;a href="https://miketaylr.com/"&gt;Mike&lt;/a&gt;, &lt;a href="https://github.com/adamopenweb"&gt;Adam&lt;/a&gt;, &lt;a href="https://github.com/MDTsai"&gt;Eric&lt;/a&gt;, &lt;a href="https://github.com/hallvors"&gt;Hallvord&lt;/a&gt;, &lt;a href="https://github.com/zoepage"&gt;Ola&lt;/a&gt;. I could write a lot more about it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« En ce qui concerne donc mon voisin, j’ai observé qu’il n’était point fertile d’examiner de son empire les faits, les états de choses, les institutions, les objets, mais exclusivement les pentes. Car si tu examines mon empire tu t’en iras voir les forgerons et les trouveras forgeant des clous et se passionnant pour les clous et te chantant les cantiques de la clouterie. Puis tu t’en iras voir les bûcherons et tu les trouveras abattant des arbres et se passionnant pour l’abattage d’arbres, et se remplissant d’une intense jubilation à l’heure de la fête du bûcheron, qui est du premier craquement, lorsque la majesté de l’arbre commence de se prosterner. Et si tu vas voir les astronomes, tu les verras se passionnant pour les étoiles et n’écoutant plus que leur silence. Et en effet chacun s’imagine être tel. Maintenant si je te demande : « Que se passe-t-il dans mon empire, que naîtra-t-il demain chez moi ? » tu me diras : « On forgera des clous, on abattra des arbres, on observera les étoiles et il y aura donc des réserves de clous, des réserves de bois et des observations d’étoiles. » Car myope et le nez contre, tu n’as point[…] »&lt;/p&gt;
&lt;p&gt;Antoine de Saint-Exupéry. « Citadelle. »&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Challenging The Comfort Of My Current Position&lt;/h2&gt;
&lt;p&gt;When working long enough at a company that you like, it becomes easy to feel comfortable. So every couple of years, I put myself in the position of looking for another job, even eventually having job interviews with some companies. I try to limit these interviews to the strict necessary by carefully selecting the companies I apply to.&lt;/p&gt;
&lt;p&gt;I want to be in a position where I have to choose in between staying at Mozilla and discovering a new area with interesting people and interesting areas of work. Sometimes areas that I have probably poor knowledge of. This is slightly tricky because many companies have a tendency to recruit people ready to fit in the machinery instead of people with an ability to work and learn.&lt;/p&gt;
&lt;p&gt;So far I have been 8 years at Mozilla, but I want to continue to make Mozilla a choice to stay instead of a place which is comfortable. So I will continue to explore new opportunities as I have always done.&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/9"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Browser Wish List - Tabs and bookmarks are the same thing</title><link href="https://www.otsukare.info/2021/05/10/tabs-bookmarks-ui" rel="alternate"></link><published>2021-05-10T11:28:00+09:00</published><updated>2021-05-10T21:13:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-05-10:/2021/05/10/tabs-bookmarks-ui</id><summary type="html">&lt;p&gt;I would love to have a better bookmarks and tabs management. This morning a simple sketch on what it would look like.&lt;/p&gt;</summary><content type="html">&lt;p&gt;My browser is my like an office room with desk and shelves, where the information is accessible. Information is stacked, accessible, sometimes open and browsable at glance and some deep on the shelves. But how would I want to have access it in the browser.&lt;/p&gt;
&lt;p&gt;Currently we bury the information of tabs and bookmarks in a big bind of context without giving any help for managing apart of having to go through the list of pages one by one. No wonder why people feel overwhelmed and try to limit the number of tabs they have opened. Because big numbers rely on external tools (Tree Style Tabs, Sidebery, Containers, etc) which do not go far enough to manage the tabs.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Binder of pages" src="https://www.otsukare.info/images/20210510-folder.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Some contexts&lt;/h2&gt;
&lt;p&gt;It started with a message from &lt;a href="https://glandium.org/blog/"&gt;Glandium&lt;/a&gt; sharing an article from Joseph Chee Chang with the title: &lt;a href="https://joe.cat/CHI-browser-tabs/"&gt;When the Tab Comes Due&lt;/a&gt;. Tabs! &lt;a href="/2020/07/07/browser-tabs-time-machine"&gt;Love Tabs&lt;/a&gt;. Reading the PDF brought some strong nodding.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tabs should better reflect users’ complex task structures.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One potential design space is to bootstrap such mental model repre-sentations with minimal user effort by identifying their intentionsusing their navigation patterns. For example, a set of tabs openedfrom a search engine query is likely to support the same information needs; or, a set of tabs opened from a top-10 list article arelikely competing options under the same category. Capturing andorganizing tabs using such structures has the potential of betterorienting users and providing better support for task progressionand resumption.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Allow users to externalize their thoughts and synthesize information across tabs.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;More directly, a recent survey showed thataround half of their participants (49.4%, N=89) use spreadsheets togather evidence and take notes across multiple online informationsources to compare options (e.g., products or destinations) to helpthem make decisions. However, current browsers treat tabs asindividual silos and provide little support for cross-referencing andcollecting information between webpages. Using external tools,such as word documents and spreadsheets, creates a disconnectin users’ workspace, and can incur high cognitive and interactioncosts when trying to copy and paste information to synthesize themin a separate document&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Sketch&lt;/h2&gt;
&lt;p&gt;The article made me think about tabs &lt;strong&gt;and bookmarks&lt;/strong&gt;, in our browsers UIs, these are separated. Probably it should not be. &lt;strong&gt;A bookmark is just a closed context, and a tab is just an opened context&lt;/strong&gt;. But they are basically the same. The UI to access them is completely different, the information to filter them is also totally different. &lt;strong&gt;Why?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So I was thinking how could both world be mixed together.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make the bookmarks more visual though thumbnails.&lt;/li&gt;
&lt;li&gt;Make the tabs manageable through trees and categories and gives them the concept of dates (created and last opened) and show these dates.&lt;/li&gt;
&lt;li&gt;Add on top of this full text search on the full set (or subcategory) of tabs/bookmarks (we need a new name).&lt;ul&gt;
&lt;li&gt;Search "Gardening" for tabs opened in between February 2021 and May 2021.&lt;/li&gt;
&lt;li&gt;Search "Curry" for tabs in my Thailand category&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Give the notion of views&lt;ul&gt;
&lt;li&gt;By tree (the sketch below)&lt;/li&gt;
&lt;li&gt;By timeline (Year, month, days). Think photo management software. Sure I opened this tab after this date, during this trip, etc.&lt;/li&gt;
&lt;li&gt;By geolocation (tabs opened when I was at home or in this cafe) Sometimes we memorize the information through the external context we where in.&lt;/li&gt;
&lt;li&gt;By labels or keywords that you may have added.&lt;/li&gt;
&lt;li&gt;By automatic classification of content. Machine Learning is all the rage, why not using the capabilities that OS provides more and more for running Machine learning to classify the content or even embark one.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Sketch for tabs bookmarks" src="https://www.otsukare.info/images/20210510-tabs-bookmarks-large.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/8"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Get Ready For Three Digits User Agent Strings</title><link href="https://www.otsukare.info/2021/04/20/ua-three-digits-get-ready" rel="alternate"></link><published>2021-04-20T17:20:00+09:00</published><updated>2021-05-31T11:43:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-04-20:/2021/04/20/ua-three-digits-get-ready</id><summary type="html">&lt;p&gt;In 2022, Firefox and Chrome will reach a version number with three digits: 100. It's time to test. Help us!&lt;/p&gt;</summary><content type="html">&lt;p&gt;In 2022, Firefox and Chrome will reach a version number with three digits: &lt;code&gt;100&lt;/code&gt;.
&lt;strong&gt;It's time to get ready&lt;/strong&gt; and extensively test your code, so your code doesn't return &lt;code&gt;null&lt;/code&gt; or worse &lt;code&gt;10&lt;/code&gt; instead of &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Durian on sale" src="https://www.otsukare.info/images/20210420-durian.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Some contexts&lt;/h2&gt;
&lt;p&gt;The browser user agent string is &lt;a href="/2014/03/31/ua-detection-use-cases"&gt;used in many circumstances&lt;/a&gt;, on the server side with the &lt;code&gt;User-Agent&lt;/code&gt; HTTP header and on the client side with &lt;code&gt;navigator.userAgent&lt;/code&gt;. Browsers &lt;a href="/2013/11/08/ua-override"&gt;lie about it&lt;/a&gt;. Web apps and websites detection &lt;a href="/2013/12/04/future-fail-js"&gt;do not cover all cases&lt;/a&gt;. So browsers have to &lt;a href="/2021/01/22/site-interventions-and-webdriver"&gt;modify the user agent&lt;/a&gt; string on a site by site case.&lt;/p&gt;
&lt;h2&gt;Browsers Release Calendar&lt;/h2&gt;
&lt;p&gt;According to the &lt;a href="https://wiki.mozilla.org/Release_Management/Calendar"&gt;Firefox release calendar&lt;/a&gt;, during the first quarter of 2022 (probably March), Firefox Nightly will reach version 100. It will set Firefox stable release version around May 2022 (if it doesn't change until then).&lt;/p&gt;
&lt;p&gt;And &lt;a href="https://chromiumdash.appspot.com/schedule"&gt;Chrome release calendar&lt;/a&gt; sets a current date of March 29, 2022.&lt;/p&gt;
&lt;h2&gt;What Mozilla Webcompat Team is doing?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/denschub"&gt;Dennis Schubert&lt;/a&gt; started to &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1672445"&gt;test JavaScript Libraries&lt;/a&gt;, but this tests only the libraries which are up to date. And we know it, the Web is a legacy machine full of history.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://wiki.mozilla.org/Compatibility#Core_Team"&gt;webcompat team&lt;/a&gt; will probably automatically test the top 1000 websites. But this is very rudimentary. It will not cover everything. Sites &lt;a href="https://github.com/webcompat/web-bugs/issues/67866"&gt;always break in strange ways&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What Can You Do To Help?&lt;/h2&gt;
&lt;h3&gt;Browse the Web with a &lt;code&gt;100&lt;/code&gt; UA string&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Change the user agent string of your favorite browser. For example, if the string is &lt;code&gt;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0&lt;/code&gt;, change it to be &lt;code&gt;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If you notice something that is breaking because of the UA string, file a report on &lt;a href="https://webcompat.com/"&gt;webcompat&lt;/a&gt;. Do not forget to check that it is working with the normal UA string.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Automatic tests for your code&lt;/h3&gt;
&lt;p&gt;If your web app has a JavaScript Test suite, add a profile with a browser having &lt;code&gt;100&lt;/code&gt; for its version number and check if it breaks. Test &lt;strong&gt;both Firefox and Chrome&lt;/strong&gt; (mobile and desktop) because the libraries have different code paths depending on the user agent. Watch out for code like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Firefox/100.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  [&amp;quot;Firefox/10&amp;quot;, &amp;quot;10&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d{2})/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// [&amp;quot;Firefox/10&amp;quot;, &amp;quot;10&amp;quot;]&lt;/span&gt;
&lt;span class="nx"&gt;ua_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Firefox\/(\d\d)\./&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//  null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Compare version numbers as integer not string&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://miketaylr.com/posts/2021/03/firefox-version-520-works-in-slack.html"&gt;Compare integer, not string&lt;/a&gt; when you have decided to have a minimum version for supporting a browser, because&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;99&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;99&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;80&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/7"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Maximizing Possible Outcomes In Simple Interfaces</title><link href="https://www.otsukare.info/2021/03/29/dumb-down-danger" rel="alternate"></link><published>2021-03-29T12:00:00+09:00</published><updated>2021-03-29T12:00:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-03-29:/2021/03/29/dumb-down-danger</id><summary type="html">&lt;p&gt;Let's keep the possibility of hackability when simplifying interfaces&lt;/p&gt;</summary><content type="html">&lt;p&gt;Facing a complex system agency, designers (be graphics, software engineers, architects, etc.) will attempt to reduce the complexity by simplifying the interactions with the system. The percentage of interactions with the new design becomes the tool for measuring the efficacy of the new choices.&lt;/p&gt;
&lt;p&gt;&lt;img alt="faucets and soaps" src="https://www.otsukare.info/images/20210329-robinets.jpg"&gt;&lt;/p&gt;
&lt;p&gt;But what do we measure? Do we measure the success of the design or do we measure that we created only one way to do a task, and funnels a variety and diversity of interactions through the funnel of one way of doing things. We should be wary and careful of what we measure and the complexity of individuals in front of a system.&lt;/p&gt;
&lt;p&gt;When we simplify a system of interactions to a certain minimalism, we often trade choices for reductionism. We maximize the simplicity to the point of dumbing everything down. But do we always help? Creativity, emergence of patterns often lie in the hackability of a system. When we reduce the options for someone to use the system in unexpected ways, we remove the possibility for people to own a craft, a skill. We make them serve the system, instead of the system serving them.&lt;/p&gt;
&lt;p&gt;We should try to create simple interfaces that maximize the possibility for people to create (creative entropy), being empowered, being autonomous.&lt;/p&gt;
&lt;h2&gt;See Also&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=CSru1QjpydI"&gt;Odyssée de l'hiver - Christian Fauré&lt;/a&gt; (French)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fvsch.com/calculators"&gt;Designing Calculator Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/6"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry><entry><title>Working With A Remote Distributed Team (Mozilla Edition)</title><link href="https://www.otsukare.info/2021/03/16/working-tips-remote-team" rel="alternate"></link><published>2021-03-16T17:35:00+09:00</published><updated>2021-03-16T17:35:00+09:00</updated><author><name>Karl Dubost</name></author><id>tag:www.otsukare.info,2021-03-16:/2021/03/16/working-tips-remote-team</id><summary type="html">&lt;p&gt;These are my requirements and tips when working in a remote distributed team at Mozilla.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The &lt;a href="https://www.mozilla.org/"&gt;Mozilla&lt;/a&gt; &lt;a href="https://wiki.mozilla.org/Compatibility"&gt;Webcompat team&lt;/a&gt; has always been an internationally distributed team from the start (7+ years). I have been working this way for the last 20 years with episodes of in-office life.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Desk in a passage" src="https://www.otsukare.info/images/20210316-bureau.jpg"&gt;&lt;/p&gt;
&lt;h2&gt;Priorities Of Scope&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;When sending messages to talk about something, always choose the most open forum first.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;It's &lt;strong&gt;always easier to restrict a part of a message to a more private discussion&lt;/strong&gt;. Once a discussion starts in private, making its content available to a larger sphere extends the intimacy, privacy, secrecy. It becomes increasingly harder to know if we can share it more broadly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Everything you say, write, think might be interesting for someone out there&lt;/strong&gt; in another Mozilla team, someone in Mozilla contributors community, someone out there in the world. I can't count the number of times I have been happy to learn through people discussing in the open, sharing what they do internally. It's inspiring. It extends your community. It solidifies the existence of your organization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When the scope is broad, the information becomes more resilient.&lt;/strong&gt; More people know the information. You probably had to use a publishing system involving the persistence of the information.&lt;/p&gt;
&lt;h2&gt;Information Broadly Accessible&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Give it a URI, so it exists!&lt;/strong&gt; or in the &lt;a href="https://en.wikipedia.org/wiki/Cogito,_ergo_sum"&gt;famous words&lt;/a&gt; of Descartes: "URI, ergo sum".&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;URI is this thing which starts with &lt;code&gt;http&lt;/code&gt; or &lt;code&gt;https&lt;/code&gt; that you are currently using to read this content. Once you gave a URI to a piece of content, you access to plenty of features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can share through different medium (messages, mails, etc.)&lt;/li&gt;
&lt;li&gt;You make the information easily searchable&lt;/li&gt;
&lt;li&gt;You make the information more resilient with regards to time. Imagine someone joining your team later on. Or you have left and your email account which was cointaining all the interesting information is gone.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You may want to create a &lt;a href="https://www.w3.org/Consortium/Persistence"&gt;URI persistence policy&lt;/a&gt; at the organization level.&lt;/p&gt;
&lt;h2&gt;Messages How?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Context is everything!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This applies to basically all messaging style (chat, email, etc.)&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;If you send a message addressing someone, think about this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Who?&lt;/strong&gt; Use the person handle in a shared chat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What?&lt;/strong&gt; The topic you would like to discuss with enough context to make it possible for the person to answer. Share URIs to online documents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When?&lt;/strong&gt; If there is a deadline, give it. It's a lot easier to reply at the appropriate time and remove the stress on both ends of the message.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: I have written, a long time ago, a &lt;a href="https://www.la-grange.net/2014/03/04/bien-gerer-mail"&gt;special guide for working with emails in French&lt;/a&gt; and it has been &lt;a href="http://www.koalie.net/Translations/Working-with-email/working-with-email.html"&gt;translated in English&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mozilla is a distributed community with a lot of different cultures (social, country, education, beliefs) and across all timezones. At Flickr, &lt;a href="http://web.archive.org/web/20070425213445/http://www.hchamp.com/"&gt;Heather Champ&lt;/a&gt; had a good reminder for the community: "Don't be a creep."&lt;/p&gt;
&lt;p&gt;You may (will probably) do terrible blunders with regards to someone else. Address them right away when the person is making a comment about them. And if necessary, apologize in the same context, you made the mistake. When you are on the receiving part of the offensive message, address them with the person who made them right away in private. Seek for clarification and explain how it can have been hurtful. If it repeats, bring it up to the hierarchy ladder and/or &lt;a href="https://www.mozilla.org/en-US/about/governance/policies/participation/"&gt;follow the community guidelines&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Chat (Matrix, IRC, Slack, …)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prefer [Public] over [Team channels] over [one to one] messages.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose Matrix over Slack.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reply in threads.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;When sending messages to share things about your work at Mozilla, use matrix over slack. It will be more accessible to the community and it will allow more participation.&lt;/p&gt;
&lt;p&gt;That said be mindful. These systems do not have built-in web archives. That's a strength and a weakness. The strength part is that it allows a more casual tone on discussing stuff without realizing that you are saying today could become embarassing in 10 years. The weakness part is that there is valuable work discussions going on sometimes in chat. So if you think a discussion on chat was important enough that it deserves a permanent record, publish it in a more permanent and open space. (Exactly this blog post which started by a discussion on slack about someone inquiring about Team communications at Mozilla.)&lt;/p&gt;
&lt;h2&gt;Reading Emails&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Read Only Emails Sent To You.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;Ah emails… the most loved hating subject. I understand that mail clients can be infuriating, but mails are really an easy task. Probably the issue with emails is not that much the emails themselves, but the way we treat them. Again see my &lt;a href="http://www.koalie.net/Translations/Working-with-email/working-with-email.html"&gt;guide for working with emails&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I end up all my working days with all messages &lt;strong&gt;marked as read&lt;/strong&gt;. I don't understand what INBOX 0 means. So here my recipes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deactivate mail notifications from all services&lt;/strong&gt; except if you intent to keep these notifications as archived helping you to work with (example: github issue messages are my offline database that I can search.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Put all my mail for a month in a monthly folder&lt;/strong&gt;. This month all my mails are going to &lt;code&gt;/2021/03&lt;/code&gt; mailbox.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create virtual/smart mailboxes&lt;/strong&gt; for each context where you need to access the emails. The benefit? The same email is then accessible from different contexts. Quick Tip to make the mailbox more performant, limit it to the last 6 weeks. smart mailboxes are easy to create, easy to destroy with changing contexts. Currently in Mail.app, I have around 50 to 100 smart mailboxes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a virtual mailbox which catches the messages where you are in To: or Cc:&lt;/strong&gt;. &lt;em&gt;This&lt;/em&gt; is your real inbox. You will discover that you do not receive that many emails in fact. This is the thing you should reply to. Mark as read everything else.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not read the emails which are not directly addressed to you&lt;/strong&gt;. This is difficult to understand for many people. But that's the good way of handling the volume. Think about your email as an archive of content which is searchable and the smart mailboxes as filter on what you might be interested in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use an online archived mailing-list&lt;/strong&gt;. Do not send emails to a group of people with giant list of &lt;code&gt;Cc:&lt;/code&gt;. This is bad. It encourages top replies to keep context. There is always someone missing who needs to be added later. It doesn't resist time at all. &lt;strong&gt;Information belongs to the organization/context you are  working on&lt;/strong&gt;, not the people. You will be leaving one day the organization. New people will join. The information needs to be accessible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With these, you will greatly reduce your burden. And one last thing, probably which is conter-intuitive. For work, do not use emails on your mobile phone. Mail clients on mobile are not practical. Typing on a virtual keyboard on a small screen for emails is useless. Mails require space.&lt;/p&gt;
&lt;h2&gt;Meetings Organizations&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Meetings are for discussions&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;If it's about information sharing, there are many ways of doing it in a better way. Publish a blog post, write it on a wiki, send it to the mailing-list of the context of your information. But do not create a meeting to just have one person talking all the time. Meetings are here for the interactions and picking ideas.&lt;/p&gt;
&lt;p&gt;Here some recommendations for good meetings:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Have a regular non mandatory meeting time&lt;/strong&gt;. What does it mean? The time is blocked, but if there is no agenda, there is no meeting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Have a published agenda&lt;/strong&gt; at a regular URI where people can contribute to the agenda. On the Webcompat team, everyone can add an &lt;a href="https://pad.0b101010.services/mozilla-webcompat-meeting-agenda"&gt;agenda item to our public agenda&lt;/a&gt;, even contributors. Try to have the agenda, at least 24h before the time of the meeting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Have a scribe and a chair&lt;/strong&gt;. The chair is the person who will be charge of animating the discussion during the meeting. The scribe will be the person taking notes of what is being said. The minutes are being taken live on the system and everyone can see what is being taken, hence can fix them. We &lt;a href="https://wiki.mozilla.org/Compatibility/Meetings/Scribes"&gt;rotate scribes and chairs&lt;/a&gt; at every meeting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publish the meeting minutes online&lt;/strong&gt;. This is important. it gives a regular URL that you can refer to in the future, that you can revisit or share with someone else in a different context. Webcompat has an archive of &lt;a href="https://wiki.mozilla.org/Compatibility/Meetings"&gt;all minuted meetings&lt;/a&gt; on Mozilla wiki. Example: &lt;a href="https://wiki.mozilla.org/Compatibility/Meetings/2021-03-02"&gt;Minutes of March 2, 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Break out big groups&lt;/strong&gt;. When there is a meeting with a lot of people in one room and a couple of people online, the meeting is unbalanced and the body language (we social beings) take over and people online may become excluded. Separate the big local group in smaller groups or really as individuals so that everyone is like a remote person.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allow for people to participate&lt;/strong&gt; once the meeting has finished. There are bug trackers, minutes, mailing-lists, etc. Give a deadline for commenting.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Meeting Times&lt;/h3&gt;
&lt;p&gt;In a distributed team, the shape of Earth comes to crash into the fixed time reality of a meeting. You will not be able to satisfy everyone, but there are things to avoid the usual grumpiness, frustrations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you organize a meeting from the US West Coast time, Fridays are forbidden. It's already Saturday in Asia-Pacific&lt;/li&gt;
&lt;li&gt;If you organize a meeting from Asia-Pacific time, Mondays are forbidden. The US West Coast is still on Sunday.&lt;/li&gt;
&lt;li&gt;Create a doodle to understand the distribution of time of people who can participate. Some people do not necessary work along the 9 to 5 schedule, some like to participate at night, some prefer very early meetings&lt;/li&gt;
&lt;li&gt;If you can't fit everyone in one meeting because of time zones. Create two meetings or rotate the burden of meeting time.&lt;/li&gt;
&lt;li&gt;Minutes the meeting, this will become handy for people who can't attend.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Wiki, Google Documents, Blog Post&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Publish Online with a wide accessible scope&lt;/strong&gt; if possible.&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;First rule at the start. If you create a Google docs, do not forget to set the viewing and sharing rights for the document. Think long term. For example, the wiki at Mozilla has been here for a longer time than Google Docs. Mozilla controls the URI space of the wiki, but not so much the one of Google Docs.&lt;/p&gt;
&lt;p&gt;Having an URI for your information is key as said above.&lt;/p&gt;
&lt;h2&gt;Comments&lt;/h2&gt;
&lt;p&gt;If you have more questions, things I may have missed, different take on them. Feel free &lt;a href="https://github.com/karlcow/otsukare.info/issues/5"&gt;to comment…&lt;/a&gt;. Be mindful.&lt;/p&gt;
&lt;p&gt;Otsukare!&lt;/p&gt;</content><category term="work"></category><category term="webcompat"></category></entry></feed>