<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jim Montgomery</title>
    <description>The latest articles on DEV Community by Jim Montgomery (@jimmont).</description>
    <link>https://dev.to/jimmont</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F296047%2Fe414a54c-9b9e-4a88-9ea7-b0b90ce6968c.jpeg</url>
      <title>DEV Community: Jim Montgomery</title>
      <link>https://dev.to/jimmont</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jimmont"/>
    <language>en</language>
    <item>
      <title>Josef Müller-Brockmann poster</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Fri, 18 Feb 2022 12:38:08 +0000</pubDate>
      <link>https://dev.to/jimmont/josef-muller-brockmann-poster-1bj1</link>
      <guid>https://dev.to/jimmont/josef-muller-brockmann-poster-1bj1</guid>
      <description>&lt;p&gt;tooling around with svg to share my appreciation for Swiss Style, modern design history and catch up with a little tech: &lt;a href="https://www.jimmont.com/art/beethoven.html"&gt;https://www.jimmont.com/art/beethoven.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the interaction and viewport dynamic made for a fun exploration into how the original was made and looks in a new context&lt;/p&gt;

&lt;p&gt;more about the original designer Josef &lt;a href="https://en.wikipedia.org/wiki/Josef_M%C3%BCller-Brockmann"&gt;https://en.wikipedia.org/wiki/Josef_M%C3%BCller-Brockmann&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the svg excerpt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg viewBox="0 0 750 1076" version="1.1" style="width:100vw;height:100vh;"&amp;gt;
&amp;lt;title&amp;gt;Josef Müller-Brockmann 1955 Beethoven poster&amp;lt;/title&amp;gt;
&amp;lt;!-- remembering
Josef Müller-Brockmann
https://en.wikipedia.org/wiki/Josef_Muller-Brockmann
1955 Beethoven poster
--&amp;gt;
&amp;lt;style&amp;gt;
svg{background-color:#000;overflow:visible;}
:root{
    --circle: rgba(255,255,255,1);
    --pie: rgba(0,0,0,1);
    --stroke: #fff;
    --stroke-width: 3px;
}
text,tspan{font-family:arial,sans-serif;font-size: 11px; word-spacing: 0px;line-height:1.1;line-height: 1.1; white-space: pre; text-anchor:start;}
.align-right, .align-right *{text-anchor:end;}
#beethoven{font-size: 32px; font-weight: 700; line-height: 1;}

circle{fill:var(--circle, #fff);stroke:var(--stroke, #fff);stroke-width:var(--stroke-width);}
g.group{
    transform:rotate(0deg);
    transition:transform 3s;
}
g.group.on{
    /* transform:rotate(360deg); */
    animation: 3s rotations ease-in-out;
}
@keyframes rotations{
    0% {transform:rotate(0);}
    45% {transform:rotate(360deg);}
    90% {transform:rotate(0);}
    100% {}
}

path{fill:var(--pie, #000);stroke:var(--stroke, #fff);stroke-width:var(--stroke-width);}
#topdisc{fill:var(--pie, #fff);}
&amp;lt;/style&amp;gt;

&amp;lt;g style="transform:translate(203px, 770px);" id="discs"&amp;gt;

&amp;lt;rect width="60" height="60" bx:origin="0 0" fill="rgba(255,255,255,0.3)"/&amp;gt;
&amp;lt;/g&amp;gt;

&amp;lt;g style="transform:translate(198px, 781px);" id="texts"&amp;gt;
&amp;lt;g class="group"&amp;gt;
&amp;lt;text class="align-right" id="beethoven" x="0" y="-78"&amp;gt;beethoven&amp;lt;/text&amp;gt;

&amp;lt;text class="align-right" id="left-labels" x="0" y="0"&amp;gt;
&amp;lt;tspan x="0"&amp;gt;tonhalle&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="0" dy="6.6em"&amp;gt;leitung&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="0" dy="1.2em"&amp;gt;solist&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="0" dy="1.8em"&amp;gt;beethoven&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="0" dy="4.2em"&amp;gt;vorverkauf&amp;lt;/tspan&amp;gt;
&amp;lt;/text&amp;gt;

&amp;lt;text x="4" y="0"&amp;gt;
&amp;lt;tspan x="4"&amp;gt;grosser saal&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;dienstag, den 22, februar 1955,&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;20.15 uhr&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;4. extrakonzert&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;der tonhalle-gesellschaft&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.8em"&amp;gt;carl schuricht&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;wolfgang schneiderhan&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.8em"&amp;gt;ouverture zu -coriolan-,op. 62&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;violinkonzert in d-dur,op. 61&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;siebente sinfonie in a-dur,op. 92&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.8em"&amp;gt;tonhalle-kasse, hug, jecklin,&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;kuoni&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"&amp;gt;karten zu fr.3.50 bis 9.50&amp;lt;/tspan&amp;gt;
&amp;lt;tspan x="4" dy="1.2em"/&amp;gt;
&amp;lt;/text&amp;gt;
&amp;lt;/g&amp;gt;
&amp;lt;/g&amp;gt;
&amp;lt;script&amp;gt;
// &amp;lt;![CDATA[

// circle divided in 32 parts, 2π
const angleIncrement = 2*Math.PI/32;
// series x2, 1-32 =&amp;gt; 1, 2, 4, 8, 16, 32
// dr = (end - start) / 32 = (900-260)/32 = 20;
// see from looking at the image and calculation output the added space for each circle's border
// visually approximated small and large circles
// step small number to find a reasonable value, step larger one to find value /32 where it yields at whole number
// account for the offset, notice 1px border
// radius is dr * step + sum of 1 unit borders, so index * 1px border;
// radius = step * dr + i;
const dr = 10;

let arc, arcs, arclist = [
    [], // text in first
    // [start-unit, size]
    [[-2,5], [12,5]],       // 5, -9, 5 @1
    [[-4, 6], [8, 6]],      // 6, -6, 6 @2
    [[-7, 8], [4,12]],      // 7, -4, 8+? @4
    [[-8,25]],          // 20+??, -? ? @8
    [[-4, 22]],             // ? @16
    [[-9, 20]]              // ? @32
];

let i = 0
, step = 1
, parent = document.querySelector('#discs')
, r0 = 250 //c0.getBBox().width / 2
, circle = parent.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'circle')
, path = parent.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'path')
, group = parent.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'g')
, copy, g, off
, radius
;
group.classList.add('group');
function onpath(event){
    let node = event.composedPath().find(node=&amp;gt;node.matches&amp;amp;&amp;amp;node.matches('g.group'));
    if(!node) return;
    if(node.matches('path')) node = node.parentNode;

    const is = 'on';

    switch(event.type){
    case 'animationend':
        node.classList.remove(is);
    break;
    case 'transitionend':
        node.classList.remove(is);
    break;
    default:
        node.classList.add(is);
    }
}
function rotatable(node){
    'touchmove, touchstart, mouseover, mousedown, transitionend, animationend'.split(/[,\s]+/).forEach(event=&amp;gt;node.addEventListener(event, onpath));
};
rotatable(parent);
rotatable(document.querySelector('#texts'));
while(i &amp;lt; 7){
    off = i * 2;
    radius = r0 + (dr * step) + off;
    console.log(i, step, radius, `${r0}+${step * dr} +${off}`);
    arcs = arclist[ i ];
    let j = 0;
    while(arc = arcs[j++]){
        g = group.cloneNode(true);
        copy = path.cloneNode();
        copy.style.setProperty('d', dpath({radius, angleIncrement, arc}));
        //copy.setAttributeNS('http://www.w3.org/2000/svg', 'd', dpath({radius, angleIncrement, arc}));
        copy.setAttributeNS(null, 'd', dpath({radius, angleIncrement, arc}));
        g.setAttribute('id', `arc${i}-${j}`);
        g.append(copy);
        parent.prepend(g);
    }

    copy = circle.cloneNode();
    copy.setAttribute('id', `c${i}`);
    copy.setAttribute('r', radius);
    parent.prepend(copy);

    step *= 2;
    i++;
}
// arc = [start-relative-to-zero, size-in-angleIncrements];
function dpath({radius, angleIncrement, arc}){

    let a0, x0, y0, a1, x1, y1;
    const [start, size] = arc;
    a0 = angleIncrement * start;
    a1 = a0 + (angleIncrement * size);
    x0 = (Math.cos(a0) * radius);
    y0 = (Math.sin(a0) * radius);
    x1 = (Math.cos(a1) * radius);
    y1 = (Math.sin(a1) * radius);

    const largeArc = Math.abs(a1 - a0) &amp;gt; Math.PI ? 1 : 0;

    return `M0,0 L${x0},${y0} A${radius} ${radius} 0 ${ largeArc } 1 ${x1} ${y1} Z`;

    // Safari doesn't work with CSS d:path(...)
//  return `path('M0,0 L${x0},${y0} A${radius} ${radius} 0 ${ largeArc } 1 ${x1} ${y1} Z')`;
}

// ]]&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>svg</category>
      <category>design</category>
    </item>
    <item>
      <title>UI = f(state); native state management for the web</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Mon, 01 Feb 2021 04:28:14 +0000</pubDate>
      <link>https://dev.to/jimmont/ui-f-state-native-state-management-for-the-web-4b63</link>
      <guid>https://dev.to/jimmont/ui-f-state-native-state-management-for-the-web-4b63</guid>
      <description>&lt;p&gt;The primary APIs/tools for Web UI message passing on the frontend are &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event"&gt;Event&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage"&gt;postMessage()&lt;/a&gt;. Events have phases, security features and various useful traits, postMessage passes objects in memory around.&lt;/p&gt;

&lt;p&gt;Events can bubble, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements"&gt;can be encapsulated in shadow DOM&lt;/a&gt;, they can be dispatched on the global self for tight coupling, like for shared state across applications, they can be dispatched on specific elements and bubble up to any element along the way to consume and manipulate further as desired, separating concerns after the point of dispatching. This is how DOM elements work already. Whenever some user does something the various respective events notify of state changes, whatever they are, and the listeners can do their thing. Whether it’s global for storage events, ui-activity like scrolling, handled or unhandled promise rejections and on and on or for specific more specialized elements like forms, or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/customElements"&gt;custom elements&lt;/a&gt; extending the generic &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement"&gt;HTMLElement&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events"&gt;using custom events&lt;/a&gt; mixed and matched in whatever way makes sense.&lt;/p&gt;

&lt;p&gt;More related to this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://open-wc.org/guides/knowledge/events/"&gt;Knowledge: Events: Open Web Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://livebook.manning.com/book/web-components-in-action/chapter-14/v-9/"&gt;14 Events and application data flow · Web Components in Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://javascript.info/shadow-dom-events"&gt;JavaScript.info ~ Shadow DOM and events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A playlist where the first 2 videos touch on state management: &lt;a href="https://www.youtube.com/playlist?list=PLNM_ABHoF7B0qDu0GI09eCXimoL2AyMMq"&gt;https://www.youtube.com/playlist?list=PLNM_ABHoF7B0qDu0GI09eCXimoL2AyMMq&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A modern library that facilitates with lightweight API extensions for web UI’s is &lt;a href="https://lit-element.polymer-project.org/guide/events"&gt;LitElement&lt;/a&gt; and the included lit-html handles state changes to views—making &lt;a href="https://lit-html.polymer-project.org/guide/concepts#thinking-functionally"&gt;views a function of the state&lt;/a&gt; by applying a functional pattern to incoming state objects to templated views. Events are the native state communication system.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>article: 2020+ web performance</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Thu, 24 Dec 2020 08:31:15 +0000</pubDate>
      <link>https://dev.to/jimmont/article-2020-web-performance-li8</link>
      <guid>https://dev.to/jimmont/article-2020-web-performance-li8</guid>
      <description>&lt;p&gt;Interesting and at times hilarious article on web performance. &lt;/p&gt;

&lt;h1&gt;
  
  
  We rendered a million web pages to find out what makes the web slow
&lt;/h1&gt;

&lt;p&gt;» Yes, good old jQuery is at the top. JQuery was first released in 2006, which is 14 years ago in human years, but much longer in JavaScript years. Measured in Angular versions, it is probably hundreds of versions ago. 2006 was a different time. The most used browser was called Internet Explorer 6, the largest social network was MySpace, and rounded corners in web pages were such a revolution that people called it web 2.0. JQuery’s primary use case was cross-browser compatibility, which is a different beast in 2020 than it was in 2006. Still, 14 years later, a full half of the web pages in our sample loaded jQuery.&lt;br&gt;
Funnily enough, 2.2% of the websites threw an error because JQuery was not loaded.&lt;br&gt;
Judging by this top 10, our browsers are mostly running analytics, ads, and code to be compatible with old browsers. Somehow 8% of web sites define a setImmediate/clearImmediate polyfill for a feature that isn’t on track to be implemented by any browser. «&lt;/p&gt;

&lt;p&gt;read the rest at:&lt;br&gt;
&lt;a href="https://catchjs.com/Blog/PerformanceInTheWild"&gt;https://catchjs.com/Blog/PerformanceInTheWild&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;alternately at:&lt;br&gt;
&lt;a href="https://itnext.io/we-rendered-a-million-web-pages-to-find-out-what-makes-the-web-slow-72bbba9ade96"&gt;https://itnext.io/we-rendered-a-million-web-pages-to-find-out-what-makes-the-web-slow-72bbba9ade96&lt;/a&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>web</category>
    </item>
    <item>
      <title>hardware fingerprinting with Canvas, WebGL, AudioContext</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Wed, 25 Nov 2020 03:59:37 +0000</pubDate>
      <link>https://dev.to/jimmont/hardware-fingerprinting-canvas-webgl-audiocontext-290i</link>
      <guid>https://dev.to/jimmont/hardware-fingerprinting-canvas-webgl-audiocontext-290i</guid>
      <description>&lt;p&gt;EFF has a browser profiling tool which illuminates--hands on--known profiling techniques in fingerprinting browsers. Understanding how the few more effective aspects work is interesting and here are a few links to the various related resources, the video is especially useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/EVh84c0gVqE"&gt;excellent YouTube video surveying the techniques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://coveryourtracks.eff.org/learn"&gt;EFF background and tool&lt;/a&gt;, also similarly useful &lt;a href="https://amiunique.org/"&gt;AmIUnique.org&lt;/a&gt; and &lt;a href="https://browserleaks.com/"&gt;BrowserLeaks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Fingerprint_(disambiguation)"&gt;Wikipedia disambiguation on Fingerprint--includes the various possibilities under science+technology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;discussion in various Q&amp;amp;A: &lt;a href="https://meta.stackexchange.com/questions/113394/implement-some-form-of-browser-fingerprinting-to-help-suss-out-socks"&gt;1 suss sock puppets (false online identities)&lt;/a&gt;, &lt;a href="https://security.stackexchange.com/questions/12059/circumventing-device-fingerprinting"&gt;2 circumvention of fingerprinting&lt;/a&gt; and &lt;a href="https://gist.github.com/joepie91/5a9909939e6ce7d09e29"&gt;loosely related expectations around privacy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>privacy</category>
    </item>
    <item>
      <title>React + LitElement Have Beers 🍺🍺</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Fri, 20 Nov 2020 10:14:36 +0000</pubDate>
      <link>https://dev.to/jimmont/react-litelement-have-beers-4d75</link>
      <guid>https://dev.to/jimmont/react-litelement-have-beers-4d75</guid>
      <description>&lt;p&gt;&lt;a href="https://www.jimmont.com/code/components.html"&gt;Two simple beer listings show&lt;/a&gt; a React and LitElement implementation side by side. These show the nearly identical lifecycle API and feature set, including some benefits of the newer technology like encapsulation and how to use them together--which is especially useful when &lt;a href="https://labs.thisdot.co/blog/showcase-react-vs-lit-element-rendering-performance"&gt;more performance&lt;/a&gt; is needed or better &lt;a href="https://web.dev/web-components-io-2019/"&gt;developer/designer experience&lt;/a&gt; wanted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nb7oYFG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zxxp4w98itphnsf4t1b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nb7oYFG6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zxxp4w98itphnsf4t1b4.png" alt="screenshot-beer-listings"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webcomponents</category>
      <category>litelement</category>
    </item>
    <item>
      <title>the web platform: lighten the JSX load in React apps</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Mon, 16 Nov 2020 08:04:39 +0000</pubDate>
      <link>https://dev.to/jimmont/the-web-platform-lighten-the-jsx-load-in-react-apps-17id</link>
      <guid>https://dev.to/jimmont/the-web-platform-lighten-the-jsx-load-in-react-apps-17id</guid>
      <description>&lt;p&gt;We can simplify, modernize and accelerate UI work with React by translating templates at runtime as-is. Several years ago browsers implemented a new way of embedding expressions in strings called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template literals&lt;/a&gt; (&lt;code&gt;backticks with ${ expressions }&lt;/code&gt;), including tagging these expressions for specific handling. We can modernize our React apps by moving the template work in JSX build processes to the runtime using these template literals and the &lt;a href="https://github.com/developit/htm"&gt;HTM helper library&lt;/a&gt;. This removes the associated transformation cost in development, simplifying build processes while also mostly removing the need to maintain knowledge related to the differences between standard HTML and this XML dialect. The HTM library itself offers a list of additional conveniences over JSX that I've come to expect in conventional work like supporting self-closing tags, better fragment handling, etc. Here's a simplified example and linked working &lt;a href="https://gist.github.com/jimmont/3f27649c626e6b8a0c94175cc82e1cbb"&gt;gist&lt;/a&gt; and &lt;a href="https://jimmont.github.io/example/ReactHTM.html"&gt;demo&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const jsx = htm.bind(React.createElement);

class App extends React.Component{
    constructor(props){
        super(props);
        const count = Number(props.count) || 0;
        this.state = { count };
        this.update = this.update.bind(this);
    }
    update(e){
        let {count} = this.state;
        count++;
        this.setState({count});
    }
    render(){
        return jsx`
&amp;lt;label&amp;gt;
click ${ this.state.count }  &amp;lt;button onClick=${ this.update }&amp;gt; from ${ this.props.count } &amp;lt;/button&amp;gt;
&amp;lt;/label&amp;gt;
        `;
    }
}

ReactDOM.render(
    jsx`&amp;lt;${ App } count=1 key=2&amp;gt; &amp;lt;//&amp;gt;`,
    document.querySelector('[react]')
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give it a try to simplify and accelerate your development experience. There's also a previous &lt;a href="https://dev.to/ben/hyperscript-tagged-markup-htm-jsx-alternative-using-standard-tagged-templates-with-compiler-support-4nc8"&gt;late 2018 mention&lt;/a&gt; here on DEV.&lt;/p&gt;

&lt;p&gt;On The Web Platform: Following several several years of using frameworks and libraries I realized the high cost associated with this Catholic-wedding approach, especially when something naturally changes like updates, etc. As a result I began focusing on what patterns and trends were actively evolving in native browser support. This based on the premise that in browsers, the engineering and vetting of solutions is of a higher caliber than the in-the-wild constantly maturing community. As a result those native solutions will tend to be more stable and longer lived, and a better investment long-term.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>the web platform: validate email addresses, internationalized</title>
      <dc:creator>Jim Montgomery</dc:creator>
      <pubDate>Wed, 11 Nov 2020 04:20:54 +0000</pubDate>
      <link>https://dev.to/jimmont/the-web-platform-validate-email-addresses-internationalized-42pf</link>
      <guid>https://dev.to/jimmont/the-web-platform-validate-email-addresses-internationalized-42pf</guid>
      <description>&lt;p&gt;The following snippet checks email addresses using the &lt;a href="https://developer.mozilla.org/docs/Web/API/URL" rel="noopener noreferrer"&gt;URL interface&lt;/a&gt; and if it looks ok does a DNS lookup for the related MX record. It fully supports &lt;a href="https://en.wikipedia.org/wiki/Internationalized_domain_name" rel="noopener noreferrer"&gt;internationalized&lt;/a&gt; and valid character sets. The DNS lookup should work in browsers and Cloudflare workers, and the commented segment in Deno.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function validEmail(address, checkDomain=false){
    const emailPattern = /^[^@]{1,64}@[a-z0-9][a-z0-9\.-]{3,252}$/i;
    let email, valid = false, error, same = false, domain;
    try{
        // URL handles punycode, etc using browser implementation
        const url = new URL(`http://${ address }`);
        const { username, hostname } = url;
        email = `${username}@${hostname}`;
        same = address === email;
        valid = emailPattern.test( email );
        if(!valid) throw new Error(`invalid email ${ email }`);

        if(checkDomain){
            // function hasMX(dns){ return dns?.[0]?.exchange ? true: false; }
            // domain = await Deno.resolveDns(hostname, 'MX').then(hasMX).catch(hasMX);
            function hasMX(dns){ return dns?.Answer?.[0]?.data ? true: false; }
            domain = await fetch(`https://cloudflare-dns.com/dns-query?name=${ hostname }&amp;amp;type=MX`, {headers:{Accept: "application/dns-json"}}).then(res=&amp;gt;res.json()).then(hasMX).catch(hasMX);
        }
    }catch(fail){
        error = fail;
    };
    return {email, same, valid, error, domain};
}

[
 'user+this@はじめよう.みんな'
, 'stuff@things.eu'
, 'stuff@things'
, 'user+that@host.com'
, 'Jean+François@anydomain.museum','هيا@יאללה'
, '试@例子.测试.مثال.آزمایشی'
, 'not@@really'
, 'no'
].forEach(async address=&amp;gt;{
    let result = await validEmail(address);
    console.log(result, address);
});
[
  'someone@dev.to'
].forEach(async address=&amp;gt;{
    let result = await validEmail(address, true);
    console.log(result, address);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>validation</category>
      <category>email</category>
      <category>intl</category>
    </item>
  </channel>
</rss>
