<?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: Giovane Cardoso</title>
    <description>The latest articles on DEV Community by Giovane Cardoso (@gcnovout).</description>
    <link>https://dev.to/gcnovout</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%2F583379%2F4f99e1d3-95ee-4158-8466-ed1318711aa4.png</url>
      <title>DEV Community: Giovane Cardoso</title>
      <link>https://dev.to/gcnovout</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gcnovout"/>
    <language>en</language>
    <item>
      <title>Vue.js in 2023 – Some tips you should know.</title>
      <dc:creator>Giovane Cardoso</dc:creator>
      <pubDate>Wed, 21 Jun 2023 20:18:03 +0000</pubDate>
      <link>https://dev.to/gcnovout/vuejs-in-2023-some-tips-you-should-know-55e3</link>
      <guid>https://dev.to/gcnovout/vuejs-in-2023-some-tips-you-should-know-55e3</guid>
      <description>&lt;p&gt;In next, I'll suggest many tricks to improve your experience with using Vue.js. &lt;/p&gt;

&lt;h2&gt;
  
  
  Vite + Unplugin
&lt;/h2&gt;

&lt;p&gt;It's common to find developers who complain about the “verbosity” of the framework. However, when using Vite with a few more addendums, it is possible to shorten the syntax a lot, leaving the project much cleaner than what is normally found.&lt;/p&gt;

&lt;p&gt;Below, a comparison between a common use with Vue 2 x an example using Vue 3+, &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;, &lt;a href="https://github.com/antfu/unplugin-auto-import"&gt;unplugin-auto-import&lt;/a&gt; and &lt;a href="https://github.com/antfu/unplugin-vue-components"&gt;unplugin-vue-components&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Common:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;ComponentOne&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;ComponentTwo&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;upper&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ComponentThree&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ComponentFourth&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ComponentOne&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ComponentOne.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ComponentTwo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ComponentTwo.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ComponentThree&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ComponentThree.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ComponentFourth&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ComponentFourth.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ComponentOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ComponentTwo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ComponentThree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ComponentFourth&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reimagined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;ComponentOne&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;ComponentTwo&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;upper&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ComponentThree&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ComponentFourth&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Using unplugin-auto-import, keep attention in file names for don't override other .vue files. I recommend that you choose a structure that guarantees naming that will not cause conflicts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;Decoupling methods using mixins has always been torture. However, with Vue 3 it is possible to use the API separately and reuse methods with ease:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// in .vue file&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useHook&lt;/span&gt;&lt;span class="p"&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="nx"&gt;hook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  teleport
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/guide/built-ins/teleport.html"&gt;&lt;/a&gt; is a built-in component that allows us to “teleport” a part of a component's template into a DOM node that exists outside the DOM hierarchy of that component.&lt;/p&gt;

&lt;p&gt;It's a very useful feature to reposition elements that are global or that need to be in another part of the tree at some point. A generic usage is to send an element to the root and position it absolutely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Teleport&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;UserInfoModal&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"open"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Teleport&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Using a state manager (&lt;a href="https://vuex.vuejs.org/"&gt;Vuex&lt;/a&gt;, &lt;a href="https://pinia.vuejs.org/"&gt;Pinia&lt;/a&gt;) in conjunction with teleport enables greater control and reability of elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  defineModel
&lt;/h2&gt;

&lt;p&gt;Since &lt;a href="https://blog.vuejs.org/posts/vue-3-3"&gt;Vue 3.3.x&lt;/a&gt;, it is possible to create material components and similar features.&lt;/p&gt;

&lt;p&gt;Before, the common case is propping with &lt;code&gt;modelValue&lt;/code&gt; and emitting the changed value to the top component, “simulating” a reactive prop:&lt;/p&gt;

&lt;p&gt;Common:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"cmp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmits&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelValue&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;defineModel&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"modelValue"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Simple, isn't it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Nuxt 3
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nuxt.com/"&gt;Nuxt&lt;/a&gt; it's a Vue framework that you probably know or have heard of. It is currently in a great phase, with a solid ecosystem due to the &lt;a href="https://nuxt.com/modules"&gt;modules&lt;/a&gt; and with several features, that will surely add to your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  VueUse
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vueuse.org/"&gt;VueUse&lt;/a&gt; is a collection of essential vue composition utilities. It's a great choice if you're looking for ready-made solutions to common problems, and it can save you a good few hours of development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;Vue.js is at it's your best when it comes to productivity and used concisely, it has everything to add to your work (and please don't rewrite an entire system just because of these tips). Thanks for reading!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>UnunuraCSS - How I Built "my own TailwindCSS"</title>
      <dc:creator>Giovane Cardoso</dc:creator>
      <pubDate>Wed, 17 May 2023 19:23:42 +0000</pubDate>
      <link>https://dev.to/gcnovout/ununuracss-how-i-built-my-own-tailwindcss-10a9</link>
      <guid>https://dev.to/gcnovout/ununuracss-how-i-built-my-own-tailwindcss-10a9</guid>
      <description>&lt;p&gt;If you don't know, &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; is a &lt;em&gt;CSS framework&lt;/em&gt; with the aim of providing classes for primary use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ununura.com/#/"&gt;UnunuraCSS&lt;/a&gt;, means "unique" in Esperanto (individual or unmarried, depending on the context, but that's beside the point), got its name because every class generated by &lt;em&gt;framework&lt;/em&gt; is totally unique and not supported by other classes. Its main objective is to offer an alternative with more &lt;em&gt;build-in&lt;/em&gt; functionalities, a shortened syntax and more practical configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example in Tailwind&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-2xl text-white font-roboto font-bold flex flex-col flex-wrap align-center justify-between&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Example in Ununura&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text[3rem white roboto 700] f[col wrap ai-center jc-between]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, how did I build?&lt;/p&gt;

&lt;h3&gt;
  
  
  On-Demand
&lt;/h3&gt;

&lt;p&gt;The main inspiration for this &lt;em&gt;framework&lt;/em&gt; is &lt;a href="https://github.com/unocss/unocss"&gt;UnoCSS&lt;/a&gt; and his article &lt;a href="https://antfu.me/posts/reimagine-atomic-css"&gt;Reimagine Atomic CSS&lt;/a&gt;. Before reading the article, I recommend knowing more about UnoCSS and its philosophy.&lt;/p&gt;

&lt;p&gt;Its main idea is to generate CSS on demand, which is basically to inspect all possible classes of an ecosystem as a whole, create the scope of the given classes according to the necessary specifications, and insert them into a single global .css file or the &lt;em&gt;SFC (Single File Component)&lt;/em&gt; of the read file depending on the &lt;em&gt;framework&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example, we have the following case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// index.html
&lt;span class="nt"&gt;&amp;lt;aside&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-bold-and-large other-class-here"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
// ...
&lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;text-bold-and-large&lt;/code&gt; can be a manually declared class in any CSS file, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bold&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;large&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="nx"&gt;rem&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;But the point of UnunuraCSS is to build a specification IF it exists, that is, it is not a common class, and that it is valid, respecting the following sequence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read all files that may or may not have CSS classes;&lt;/li&gt;
&lt;li&gt;If any, transform the appropriate sequence to a new specification;&lt;/li&gt;
&lt;li&gt;Transform the title to a nomenclature supported by CSS 3 and convert your template in the pre-processing of each file;&lt;/li&gt;
&lt;li&gt;Generate a global CSS with the generated classes that cannot be inserted in the same file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This sequence is executed thanks to &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;, which by following the &lt;a href="https://rollupjs.org/"&gt;Rollup&lt;/a&gt; specification, it is possible to do these tasks in a simple plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ununuracss:core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pre&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isVueFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UnunuraScopedSFCFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSvelteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UnunuraScopedSFCFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;resolveId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;VIRTUAL_CSS_INJECT_FILENAME&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;RESOLVED_VIRTUAL_CSS_INJECT_FILENAME&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;RESOLVED_VIRTUAL_CSS_INJECT_FILENAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UnunuraGlobalGenerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ununura&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;handleHotUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;reloadServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ununura&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&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;blockquote&gt;
&lt;p&gt;enforce: It will be executed before all other rollup plugins and in the pre-processing stage, that is, before any transformation performed by internal instances or other rollup plugins.&lt;/p&gt;

&lt;p&gt;transform: Receives the file content (code) and the file path (id). Our objective in this step is to execute what is necessary for each type of file and its support (.vue, .svelte, .jsx...), ignoring files that cannot have classes (or Ununura does not offer explicit support) and converting to a new template. As Ununura does not use the default &lt;code&gt;className&lt;/code&gt; titles (explained in Key-Resources), here is also the implementation of the new titles.&lt;/p&gt;

&lt;p&gt;resolveId: Resolve &lt;code&gt;\0&lt;/code&gt;, recommended by Vite, for creating a virtual CSS file (ununura.css). All other id's are ignored.&lt;/p&gt;

&lt;p&gt;load: The creation of ununura.css file and the classes that will be globally in the application.&lt;/p&gt;

&lt;p&gt;handleHotUpdate: Every change in a valid file, that is, which may have had a CSS change, is triggered and the virtual CSS is rewritten:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reloadServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ViteDevServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnunuraCoreOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;virtualModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleGraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getModuleById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESOLVED_VIRTUAL_CSS_INJECT_FILENAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;virtualModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reloadModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;virtualModule&lt;/span&gt;&lt;span class="p"&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;blockquote&gt;
&lt;p&gt;Because everything runs in pre-processing time, it is not necessary to deal with each library (such as using @vue/compiler-sfc), it is only necessary to respect the specification of each &lt;em&gt;SFC&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  AST
&lt;/h3&gt;

&lt;p&gt;To search for classes, a &lt;a href="https://en.wikipedia.org/wiki/Depth-first_search"&gt;deep-first search&lt;/a&gt; is done in the &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;syntax abstraction tree&lt;/a&gt; from all valid files, fetching the &lt;code&gt;className&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; attribute by default from embedded HTML's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classesFromRawHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;adapters&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;UnunuraASTNode&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ast from rehype package&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fromHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fragment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnunuraASTNode&lt;/span&gt;&lt;span class="p"&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;const&lt;/span&gt; &lt;span class="nx"&gt;insert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UnunuraASTNode&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;children&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="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;template&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// .vue sfc&lt;/span&gt;

        &lt;span class="nx"&gt;adapters&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="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;className&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&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;ast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Certain files have adapters to run the classes without the need for a &lt;em&gt;runtime&lt;/em&gt;. For example, Ununura supports the &lt;code&gt;:class=[...]&lt;/code&gt; of &lt;code&gt;.vue&lt;/code&gt; in both ternary and object format. If needed, a separate &lt;em&gt;runtime&lt;/em&gt; is also offered.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DFS&lt;/em&gt; is not one of the best alternatives, but if you're not the type of programmer who writes a .vue over 3000 (three thousand) lines of code, it won't be a problem in development mode (much less in development mode). production, as the build time is practically instantaneous).&lt;/p&gt;

&lt;p&gt;Certain specifications use means other than AST, such as &lt;code&gt;.[jt]sx&lt;/code&gt; using &lt;code&gt;@babel/parser&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A general &lt;em&gt;buffer&lt;/em&gt; is used for the registration of all classes and a temporary &lt;em&gt;buffer&lt;/em&gt; for the registration of the classes of each attribute, where this temporary buffer is used for the verification of unique keys by each attribute and the creation of rules , such as responsiveness and custom themes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Key-Resources
&lt;/h4&gt;

&lt;p&gt;Unlike standard CSS classes, Ununura transforms the following two definitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Key-Unique Resource: &lt;code&gt;class="flex:col text:white"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Key-Multiple Feature: &lt;code&gt;class="flex[col wrap] text[white 1.1rem]"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, these two shapes are not supported by default by CSS. So, in addition to the tool having to create the CSS given its key, which indicates the group it belongs to, and given its resources, which say what the key actually is, it is necessary to convert each key-resources to a title " minified" (&lt;em&gt;slug&lt;/em&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="nd"&gt;:col&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col&lt;/span&gt; 
&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="nd"&gt;:white&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white&lt;/span&gt; 

&lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;col&lt;/span&gt; &lt;span class="nt"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col-wrap&lt;/span&gt; 
&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;white&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;rem&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white-11rem&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internally, all classes are generated to follow the concept of &lt;em&gt;Only Scoped&lt;/em&gt;, where every class generated in the same application (disregarding &lt;em&gt;micro-frontend&lt;/em&gt; federations), being totally unique in its selectors, such as &lt;code&gt;@media&lt;/code&gt;, will not be affected by other contexts, where in each title the current line of &lt;code&gt;className&lt;/code&gt; and the name of the referenced file are also inserted. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="nd"&gt;:col&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col-1-app&lt;/span&gt;
&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="nd"&gt;:white&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white-1-app&lt;/span&gt;

&lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;col&lt;/span&gt; &lt;span class="nt"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col-wrap&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.flex-col-wrap-2-app&lt;/span&gt; 
&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;white&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;rem&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white-11rem&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.text-white-11rem-2-app&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Because it is not valid at runtime, it was necessary to create a simple &lt;em&gt;lexer&lt;/em&gt; to differentiate the spacing of each class with the spacing of each resource.&lt;/p&gt;

&lt;p&gt;Not all supporters have the same idea, where some keys in particular can take advantage of the resource space to use as a sequence, and even incorporate other supporters in themselves, as is the case with the gradient:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gr[90deg rgba-200-200-200-0.5 0% rgba-100-200-0-0.35 30% rgba-255-100-50-0.8 100%]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Each key can have more than one variation, like text-font, flex-f, rounded-r, ...&lt;/p&gt;

&lt;p&gt;As it is possible to have a virtual .css file, it is possible to insert classes and pre-definitions without the need to be treated in the common flow, such as having the functionality to "reset the css" in the class:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reset:meyer ...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* ununura.css */&lt;/span&gt;
&lt;span class="c"&gt;/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/&lt;/span&gt;

&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;vertical-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;baseline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Supporters
&lt;/h4&gt;

&lt;p&gt;To validate each resource and its proper context, a system of supporters is used, where each resource is classified in different ways by each key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getResourceText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnunuraIdentifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UnunuraGenerateContext&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getSupportedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getSupportedFontSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontFamily&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getSupportedFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getSupportedFontWeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setterHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;setterRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;setterRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`font-size: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;setterRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`font-weight: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;setterRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`font-family: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;getFontFamilyCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\'&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\'`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;ununura&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;fontStack&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_FONT_STACK&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resolveCssClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;blockquote&gt;
&lt;p&gt;Supporters can infer rules by default, like the case of the unit supporter which, in the absence of a unit, it suffixes &lt;code&gt;px&lt;/code&gt; and multiplies the numerical value by &lt;code&gt;1.0&lt;/code&gt; (this can be overridden in the settings):&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w:100% md(w:768)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w:100% md(w:768px)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Each supporter can accept different resource bases, like &lt;em&gt;color&lt;/em&gt; which accepts several ways to enter a color, or &lt;code&gt;fontFamily&lt;/code&gt; which accepts default browser fonts and fonts extended by configuration file:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg:rgb-255-200-0 text:red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font:arial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// with extended configuration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg:primary text[arial primary 1.2rem]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font:roboto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Even though every resource search is O(n), a key will hardly have more than 10 (ten) resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Context
&lt;/h4&gt;

&lt;p&gt;In addition to the default context, it is possible to infer specific rules using &lt;code&gt;()&lt;/code&gt; as the attached context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text:white md(text:black) dark(text:black md(text:white))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Because of validation by the temporary buffer, all keys in default context have to be inserted at the beginning.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;class="md(hover(dark(xl(active(light(xl(focus(sepia(bg:rgba-0-0-0-0.1))))))))"&lt;/code&gt; is valid, but each context group is resolved only once, that is, in this case only md, hover and dark will be considered rules. It would be nice, but it is not practical to have more than one specific group for identical context rules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Globals
&lt;/h4&gt;

&lt;p&gt;Globals are special resources that every key has access to, serving as a helper when generating your class, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="o"&gt;[!&lt;/span&gt; &lt;span class="nt"&gt;red&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;red&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nt"&gt;important&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;[?&lt;/span&gt; &lt;span class="nt"&gt;flex-1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;Removes&lt;/span&gt; &lt;span class="nt"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;before&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;content-a_some_test&lt;/span&gt; &lt;span class="nt"&gt;col-3&lt;/span&gt; &lt;span class="o"&gt;...])&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"a some test"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Runtime
&lt;/h4&gt;

&lt;p&gt;As mentioned in the AST section, the &lt;em&gt;framework&lt;/em&gt; provides a &lt;em&gt;runtime&lt;/em&gt;, which is basically a &lt;em&gt;MutationObserver&lt;/em&gt; that recompiles the classes if necessary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="nx"&gt;list&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="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;childList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;injectStyle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addedNodes&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="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;_node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

        &lt;span class="nx"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attributes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;_node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

      &lt;span class="nx"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_node&lt;/span&gt;&lt;span class="p"&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;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;MO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&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;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;childList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subtree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;blockquote&gt;
&lt;p&gt;The &lt;em&gt;runtime&lt;/em&gt; is not coupled to avoid compatibility problems with the post-processing of each project, having to be inserted individually by the &lt;code&gt;ununura-runtime&lt;/code&gt; package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Extra
&lt;/h4&gt;

&lt;p&gt;The engine offers other features, such as integration with &lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt;, &lt;em&gt;CLS Fallback&lt;/em&gt; with &lt;a href="https://github.com/danielroe/fontaine"&gt;FontaineCSS&lt;/a&gt;, use of &lt;a href="https://github.com/system-fonts/modern-font-stacks"&gt;Modern Font Stack&lt;/a&gt;, styles for syntax customization, malleable configuration, support for other frameworks like &lt;a href="https://nuxtjs.org/"&gt;Nuxt&lt;/a&gt; and &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt;, among other features.&lt;/p&gt;

&lt;p&gt;The project is &lt;a href="https://github.com/Novout/ununuracss"&gt;fully open source&lt;/a&gt;, and if in doubt, &lt;a href="https://ununura.com/#/docs/install"&gt;see the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Did you like the article? Consider using the tool in some project, I guarantee you will like it :)
&lt;/h5&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>tailwindcss</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How I Built a 100% Client-Side Word Processor</title>
      <dc:creator>Giovane Cardoso</dc:creator>
      <pubDate>Wed, 17 May 2023 19:19:47 +0000</pubDate>
      <link>https://dev.to/gcnovout/how-i-built-a-100-client-side-word-processor-41fi</link>
      <guid>https://dev.to/gcnovout/how-i-built-a-100-client-side-word-processor-41fi</guid>
      <description>&lt;p&gt;After launching version 1.1 of &lt;a href="https://github.com/Novout/betterwrite"&gt;betterwrite.io&lt;/a&gt; (and probably the last major one), deciding to write on a trajectory that lasts for almost 2 (two) years and which may last longer.&lt;/p&gt;

&lt;p&gt;Warning from before that this project is not an example of &lt;em&gt;software&lt;/em&gt; architecture, given its many technology changes, &lt;em&gt;features&lt;/em&gt; that have been completely removed, forgotten or built without use; &lt;em&gt;typos&lt;/em&gt;, dubious decisions and missed conversations.&lt;/p&gt;

&lt;p&gt;Treat the word processor as a mere project for personal use, built by just one person and gone further than it should have. So, you won't be annoyed by the following review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--taJ0rzEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20dr1we5czjma5i8ry5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--taJ0rzEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20dr1we5czjma5i8ry5n.png" alt="Better Write Cover" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Word Processor Focused on Creative Writing
&lt;/h3&gt;

&lt;p&gt;The idea came up during the peak of the &lt;em&gt;COVID-19&lt;/em&gt; pandemic, where I divided my time between &lt;em&gt;freelances&lt;/em&gt; without much desire and procrastination in the sheer boredom of social isolation.&lt;/p&gt;

&lt;p&gt;Without further details, the idle time made me want to continue or start something personal that might or might not be useful for my work, but one factor was decisive for choosing a project that involved both programming and writing: the slowness of &lt;em&gt;Google Documents&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Cursed Canvas
&lt;/h4&gt;

&lt;p&gt;As much as there are other considerably good options on the market, such as &lt;em&gt;Microsoft Word&lt;/em&gt;, &lt;em&gt;Overleaf&lt;/em&gt;, thousands of &lt;em&gt;WYSIWYG&lt;/em&gt; editors that transform markdown into PDF and even &lt;em&gt;notepad++&lt;/em&gt;, at the end of the day, being hostage to practicality and tools from &lt;em&gt;Google Docs&lt;/em&gt; was a daily action.&lt;/p&gt;

&lt;p&gt;But a problem was recurrent: When surpassing about 100 (one hundred) pages with large paragraphs and color and spacing customizations, the editor was considerably slow and required me to separate the project into other files and join them only at the end.&lt;/p&gt;

&lt;p&gt;Consisting of a single canvas, all manipulation, and transformation depends on it, which means that even what is not being displayed is being considered valid in the context. Treating as a unit, not as a block, has its advantages, such as free customization and extensibility, but inserting a line break, page break or changing text positions shouldn't be costly.&lt;/p&gt;

&lt;p&gt;These difficulties, added to the fact that practically all extensions (which considerably improve the editor as a whole) broke every &lt;em&gt;release&lt;/em&gt; (like the beloved Dark Theme) made me decide: build my own or continue an existing project that was precisely what I wanted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Obviously &lt;em&gt;Google Docs&lt;/em&gt; is much more robust than &lt;em&gt;Betterwrite&lt;/em&gt;, in addition to being generalist. Comparing them directly doesn't make much sense, as they have completely different focuses (and investments).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Fontaine Editor — A modern, multi-platform manuscript editor.
&lt;/h4&gt;

&lt;p&gt;An initiative of this scale is a difficult idea to take seriously, especially when whoever is building the tool has already had several projects abandoned for several different reasons, but when finding &lt;a href="https://github.com/EndaHallahan/Fontaine-Editor"&gt;Fontaine&lt;/a&gt; I ended up changing my opinion a little.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fontaine&lt;/em&gt; consisted of a manuscript editor and provided control tools and an easy-to-use interface. However, the project was stopped, and its status did not allow me to use it due to the lack of document export.&lt;/p&gt;

&lt;p&gt;Having it discontinued unfinished was a clear negative sign, but its simplicity in displaying relevant information, even though it was not of a high level of complexity, gave me enough courage to start a project with &lt;a href="https://vuejs.org/"&gt;&lt;em&gt;Vue 2&lt;/em&gt;&lt;/a&gt;, &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt;, &lt;a href="http://pdfmake.org/"&gt;PDFMake&lt;/a&gt; and &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVP
&lt;/h3&gt;

&lt;p&gt;The above version, &lt;em&gt;v0.1.2&lt;/em&gt;, was the first versioned (recovered for this, thanks &lt;em&gt;git tag&lt;/em&gt;) and developed relatively quickly (rushing), consisting of a block editor where each line was a &lt;code&gt;&amp;lt;textarea /&amp;gt;&lt;/code&gt; that barely worked properly, a cloud save with a &lt;code&gt;.json&lt;/code&gt; via the &lt;em&gt;SDK&lt;/em&gt; of &lt;em&gt;Dropbox&lt;/em&gt; (one of &lt;em&gt;features&lt;/em&gt; removed), shortcuts for each sidebar item (also removed), a list of chapters and the dreamed PDF generator.&lt;/p&gt;

&lt;h4&gt;
  
  
  Event System
&lt;/h4&gt;

&lt;p&gt;Firstly, the entire logic of the application consists of issuing events anonymously and carrying out each job individually. Using &lt;a href="https://github.com/developit/mitt"&gt;mitt&lt;/a&gt; for this, all events of a given set (currently called plugin) are registered by a key and called even though they are not inside a &lt;code&gt;setup()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registered plugins have access to stores (&lt;em&gt;pinia stores&lt;/em&gt;) and &lt;em&gt;vue hooks&lt;/em&gt;, making it possible to decouple each functionality and facilitate maintenance.&lt;/p&gt;

&lt;p&gt;The following is the flow of the PDF:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PDFPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;PluginTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;createPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf&lt;/span&gt;&lt;span class="dl"&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;PluginPDFBase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PluginPDFSet&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PluginEntityInputInitial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;emitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PluginTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PluginEmitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PluginTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PluginContentOn&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;emitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin-input-watch-initial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PluginTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PluginLoggerDefault&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// in pdf monorepo&lt;/span&gt;
&lt;span class="nx"&gt;On&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;externals&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;PluginPDFGenerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emitter&lt;/span&gt;&lt;span class="p"&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;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PDFDocOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// App.vue
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;router-view&amp;gt;&amp;lt;/router-view&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;PWAPrompt&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStart&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/use/start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemePlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ImporterPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-importer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PDFPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-exporter-pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DocxPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-exporter-docx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TxtPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-exporter-txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HtmlPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-exporter-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AnnotationsPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-annotations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EpubPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-write-plugin-exporter-epub&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="nx"&gt;useStart&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;ThemePlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;ImporterPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;PDFPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;DocxPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;EpubPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;TxtPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;HtmlPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;AnnotationsPlugin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As you can see, this system enabled the migration to mono-repositories, using &lt;a href="https://turbo.build"&gt;turborepo&lt;/a&gt; and &lt;a href="https://lerna.js.org/"&gt;lerna&lt;/a&gt; to adjust the flow and enable the decentralization of internal packages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  The PDF Generator
&lt;/h4&gt;

&lt;p&gt;Speaking of the generator, it implied &lt;em&gt;10 (ten) mb&lt;/em&gt; of &lt;em&gt;.tff&lt;/em&gt; in the &lt;em&gt;bundle&lt;/em&gt; and had an unbearable &lt;em&gt;bug&lt;/em&gt; when attaching external sources (and which continued for a long time), which consisted of not allowing the use for being a &lt;em&gt;readonly&lt;/em&gt; method and that made its customization usable only in a development environment. However, it was (and still is, as it has not been completely rewritten) useful to me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the time I didn't know about &lt;a href="https://www.typescriptlang.org/tsconfig#skipLibCheck"&gt;&lt;em&gt;skipTsLibCheck&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/betterwrite/pdfeasy"&gt;pdfeasy&lt;/a&gt; was built to replace &lt;a href="http://pdfmake.org/#/"&gt;pdfmake&lt;/a&gt;, but since &lt;em&gt;pdfmake&lt;/em&gt; received updates that tweaked the most of the problems ended up being maintained.&lt;/p&gt;

&lt;p&gt;The other generators implemented follow a flow very similar to that of the PDF.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Model-Entity
&lt;/h4&gt;

&lt;p&gt;As much as it has undergone severe changes in the new versions, the concept is the same: a list of entities, and each entity consists of blocks of different types such as paragraphs, list, image, line/page break, among others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  //...
  &lt;span class="nt"&gt;&amp;lt;EditorEntityDefault&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(element, index) in CONTEXT.entities"&lt;/span&gt;
    &lt;span class="na"&gt;:id=&lt;/span&gt;&lt;span class="s"&gt;"`entity-${index}`"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;
    &lt;span class="na"&gt;:entity=&lt;/span&gt;&lt;span class="s"&gt;"element"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  // ...
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its big difference to &lt;em&gt;block-style&lt;/em&gt; editors is that each event is emitted individually, and each event entry is triggered only when needed.&lt;/p&gt;

&lt;p&gt;For example, text blocks do not use &lt;em&gt;Vue&lt;/em&gt;'s &lt;em&gt;v-model&lt;/em&gt;, &lt;a href="https://github.com/Novout/betterwrite/blob/main/docs/ENTITY_MODEL.md"&gt;explained in this file&lt;/a&gt;, where the value of each &lt;code&gt;el.innerHTML&lt;/code&gt; (new blocks use &lt;em&gt;contenteditable&lt;/em&gt; in place of &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt;) is computed only when a newline is added or another chapter is loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;save&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

  &lt;span class="nx"&gt;CONTEXT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may seem like a silly approach, but this allows massive bodies of entities being rendered in the same chapter to have fluid typing in text entries, which is a common problem in &lt;em&gt;WYSIWYG&lt;/em&gt; editors.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The display sidebar is only changed when a block needs to be updated, which is a limitation of this approach, but something to overlook.&lt;/p&gt;

&lt;p&gt;The list uses the key-index of the list itself for each entity to infer which block is at the front or back in O(1), such as adding an extra empty line after a page/line break or for deleting multiple items.&lt;/p&gt;

&lt;p&gt;The find/replace text uses a different list view as it has a different view proposition:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;EditorBaseRenderFinder&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"ABSOLUTE.shortcuts.finder"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;EditorBaseRenderSwitcher&lt;/span&gt; &lt;span class="na"&gt;v-else-if=&lt;/span&gt;&lt;span class="s"&gt;"ABSOLUTE.shortcuts.switcher"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;EditorBaseRenderDefault&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAbsoluteStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/store/absolute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ABSOLUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAbsoluteStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Other features follow a similar philosophy, such as the annotations markdown editor that uses &lt;em&gt;debounce time&lt;/em&gt; to save changes and automatic saving that only occurs in case of context destruction:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// annotations monorepo&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vueuse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useDebounceFn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// editor.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inForcedSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EDITOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;autosave&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onSaveProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EDITOR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cloudAutosave&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;online&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saveProject&lt;/span&gt;&lt;span class="p"&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;useEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;inForcedSave&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;onBeforeRouteLeave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;inForcedSave&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;h4&gt;
  
  
  100% Client-Side
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Betterwrite&lt;/em&gt; has a simple concept as an application: only static files, that is, without the need for &lt;a href="https://solutionshub.epam.com/blog/post/what-is-server-side-rendering"&gt;SSR&lt;/a&gt;. This is only possible due to the &lt;em&gt;polyfills&lt;/em&gt; that allow the import and generation of documents using the API of the browsers themselves. By &lt;em&gt;Vite&lt;/em&gt;, &lt;a href="https://github.com/niksy/node-stdlib-browser"&gt;node-stdlib-browser&lt;/a&gt; was used to accomplish this task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-inject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Plugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viteStdlib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-stdlib-browser/helpers/esbuild/shim&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;global&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-stdlib-browser/helpers/esbuild/shim&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-stdlib-browser/helpers/esbuild/shim&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As the word processor uses most &lt;em&gt;polyfills&lt;/em&gt;, it turns out to be worth injecting them all at once.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another important point is the migration of the SDK from &lt;em&gt;Dropbox&lt;/em&gt; to &lt;a href="https://supabase.com/"&gt;Supabase&lt;/a&gt;, which made it possible to authenticate users and save the project in the cloud &lt;a href="https://subase.com/security"&gt;safely on the client-side&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even the word processor, being static, is hosted for free. Thank you &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you want more information about &lt;em&gt;100% Client-Side&lt;/em&gt;, &lt;a href="https://github.com/Novout/betterwrite/tree/main/docs"&gt;see the application's technical documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Progress
&lt;/h3&gt;

&lt;p&gt;When I decided to go ahead with this project, I made some drastic changes that (feel) paid off.&lt;/p&gt;

&lt;p&gt;To validate the editor and his idea, some book would have to serve as a guinea pig, and that is why &lt;a href="https://www.amazon.com/-/es/Giovane-Silva-Cardoso/dp/6500469992"&gt;Restos da Geada - Entre Plano&lt;/a&gt; was chosen. &lt;em&gt;Self-publish&lt;/em&gt;, being my first book released in my name that was completed, consequently gave me the freedom to do whatever I wanted with the editor (like losing paragraphs due to editor error without fearing deadlines). It was started in &lt;em&gt;Google Docs&lt;/em&gt;, but was migrated to &lt;em&gt;Betterwrite&lt;/em&gt;, having its project initialized in &lt;em&gt;v0.0.1&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A war survivor, he was responsible for compatibility between versions, the need for authentication, all the &lt;em&gt;features&lt;/em&gt; focused on creativity and the ability to place images on break lines.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A curious fact is that support for importing in other extensions only existed in &lt;em&gt;v0.10&lt;/em&gt;, so a &lt;em&gt;copy-paste&lt;/em&gt; of &lt;em&gt;raw HTML&lt;/em&gt; between blocks exclusively for this task was implemented, &lt;em&gt;feature&lt;/em&gt; also removed .&lt;/p&gt;

&lt;p&gt;Another curious fact is that your project was lost in a test in production, but it was recovered in an old locally saved project (&lt;code&gt;.bw&lt;/code&gt;) and its values ​​were copied from &lt;code&gt;.json&lt;/code&gt; by hand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Electron
&lt;/h4&gt;

&lt;p&gt;Before adopting &lt;a href="https://en.wikipedia.org/wiki/Progressive_web_app"&gt;PWA&lt;/a&gt;, &lt;a href="https://www.electronjs.org/pt/"&gt;Electron&lt;/a&gt; was implemented almost completely (with support to other operating systems and automatic updates), but due to some limitations of &lt;em&gt;Vue&lt;/em&gt; (and the &lt;em&gt;Vite&lt;/em&gt; plugin) it was decided to "throw out" the entire implementation and make room for a hybrid application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The PWA went hand in hand by allowing caching in &lt;em&gt;service-worker&lt;/em&gt; certain requests (gstatic) and required files (a &lt;code&gt;.ttf&lt;/code&gt; font for &lt;em&gt;pdfmake&lt;/em&gt; and a &lt;em&gt;typeface&lt;/em&gt; font used by *threejs * on the landing).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  WindiCSS
&lt;/h4&gt;

&lt;p&gt;The project was migrated from &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; to &lt;a href="https://windicss.org/"&gt;WindiCSS&lt;/a&gt; due to the delayed release of &lt;em&gt;TailwindCSS 3.0&lt;/em&gt;, with &lt;a href="https://headlessui.com/"&gt;HeadlessUI&lt;/a&gt; being a big part of &lt;em&gt;material design&lt;/em&gt;. The &lt;em&gt;hot-reload&lt;/em&gt; saved me hours in development mode.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A migration to &lt;a href="https://ununura.com/#/"&gt;a proprietary Atomic CSS lib&lt;/a&gt; almost occurred, but the process was paused.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Bundle Size
&lt;/h4&gt;

&lt;p&gt;The size of the final application was never of great concern, but when migrating to &lt;em&gt;PWA&lt;/em&gt;, the loading time was drastically off the curve (negatively).&lt;/p&gt;

&lt;p&gt;It is currently acceptable for your proposal, but it can be improved.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The actual cache can reach up to 20 (twenty) mb depending on usage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  1.1
&lt;/h4&gt;

&lt;p&gt;Its &lt;em&gt;major&lt;/em&gt; version has been released, but &lt;em&gt;1.1&lt;/em&gt; is the true stable version, fixing chronic application problems and bringing with it the editor's true initial objective: &lt;strong&gt;the focus on creativity&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>vue</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Desenvolvimento de Jogos para Programadores(as) WEB - Parte 1</title>
      <dc:creator>Giovane Cardoso</dc:creator>
      <pubDate>Tue, 23 Feb 2021 14:46:23 +0000</pubDate>
      <link>https://dev.to/gcnovout/desenvolvimento-de-jogos-para-programadores-as-web-parte-1-29ae</link>
      <guid>https://dev.to/gcnovout/desenvolvimento-de-jogos-para-programadores-as-web-parte-1-29ae</guid>
      <description>&lt;h3&gt;
  
  
  Sumário
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;Game Loop&lt;/li&gt;
&lt;li&gt;Tick&lt;/li&gt;
&lt;li&gt;UI&lt;/li&gt;
&lt;li&gt;Ciclo de Vida&lt;/li&gt;
&lt;li&gt;ECS&lt;/li&gt;
&lt;li&gt;Informações Adicionais&lt;/li&gt;
&lt;li&gt;Parte 2 - PixiJS&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Introdução
&lt;/h3&gt;

&lt;p&gt;Neste artigo vamos buscar trazer a familiarização com DOM a forma que jogos funcionam internamente, assim conseguindo relacionar conceitos que um desenvolvedor(a) WEB possui com o que está sendo proposto.&lt;/p&gt;

&lt;p&gt;Este artigo é recomendado para desenvolvedores(as) que possuem um bom conhecimento de DOM e sobre gerenciamento de estado, mas nada impede de seguir os exemplos já que tem muitos link's auxiliares :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Loop
&lt;/h3&gt;

&lt;p&gt;Os loops de jogo são o exemplo perfeito de um &lt;strong&gt;padrão de programação para jogos&lt;/strong&gt;. Quase todo jogo tem um, e relativamente poucos programas fora dos jogos os usam.&lt;/p&gt;

&lt;p&gt;Podemos fazer um paralelo entre os &lt;em&gt;loop's&lt;/em&gt; convencionais com os &lt;strong&gt;Event Listeners&lt;/strong&gt; do &lt;em&gt;&lt;a href="https://tableless.com.br/entendendo-o-dom-document-object-model/"&gt;DOM&lt;/a&gt;&lt;/em&gt;, onde sempre estão esperando uma alteração para emitir um evento:&lt;/p&gt;

&lt;p&gt;Loop convencional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;InstanceManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;escutarComando&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InputManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;carregarTeclado&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;ul&gt;
&lt;li&gt;&lt;p&gt;InstanceManager: Seria o gerenciador responsável pela instância atual da aplicação e do que está sendo exibido. Nele poderíamos acessar a vida de um jogador, o tempo atual de jogo e os itens que estão no mapa, por exemplo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;InputManager: Seria o gerenciador responsável pela captura e emissão de dados que o sistema recebe, como por exemplo a entrada de dados do teclado/mouse.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dispararTeclado&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ou event.key&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Com um &lt;em&gt;Event Listener&lt;/em&gt;, conseguimos escutar eventos a qualquer momento e realizar o que queremos de forma separada, sem a necessidade de um loop fixo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nos exemplos iremos utilizar apenas JavaScript para melhor compreensão da semântica.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tick
&lt;/h3&gt;

&lt;p&gt;Você deve ter se perguntado: &lt;strong&gt;Se este loop não está bloqueando a entrada, o quão rápido ele gira?&lt;/strong&gt; A Cada volta no loop o estado do jogo avança em alguma quantidade, chamamos isso de &lt;em&gt;tick&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Podemos fazer um paralelo diretamente com &lt;strong&gt;FPS(Frames por Segundo)&lt;/strong&gt;. Por exemplo, se um jogo estiver renderizando 60 "fotos" por segundo, quer dizer que, no melhor dos casos, temos o nosso loop sendo percorrido a 60 ticks por segundo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;É importante ressaltar o &lt;strong&gt;frame-time&lt;/strong&gt;, que é o tempo normalmente contado em milissegundos entre a demora de renderização de um frame a outro, normalmente não é 100% exato. Por exemplo, podemos ter um jogo em que o &lt;em&gt;frametime&lt;/em&gt; é alto devido a placa de vídeo em não conseguir renderizar a tempo a qualidade das texturas, ou o processador não conseguir calcular a ação de todos os &lt;em&gt;sprites&lt;/em&gt; a tempo. Normalmente &lt;em&gt;game-engines&lt;/em&gt; possuem recursos para normalizar esse tipo de situação.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se quiser entender um pouco mais afundo sobre &lt;em&gt;frame-times&lt;/em&gt;, &lt;a href="https://www.clubedohardware.com.br/topic/1230664-an%C3%A1lise-de-frametimes-e-porque-isso-importa-introdu%C3%A7%C3%A3o-aos-01-e-1-%E2%80%9Clows%E2%80%9D/"&gt;recomendo este fórum&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No JavaScript, faz mais sentido em utilizar &lt;code&gt;setInterval()&lt;/code&gt; do que o &lt;code&gt;while&lt;/code&gt; para executar estes loops, assim garantido um tickrate "esperado".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UI
&lt;/h3&gt;

&lt;p&gt;Para o terror dos &lt;em&gt;backend&lt;/em&gt; de plantão, "a regra de negócio dos jogos é feita no lado do cliente", e a interface é executada durante o &lt;em&gt;tick&lt;/em&gt;, recebendo apenas as novas informações (se tiver) para renderizar alguma coisa.&lt;/p&gt;

&lt;p&gt;As ferramentas gráficas modernas de construção de interfaces para jogos ficam "parados" até receber algum evento:&lt;/p&gt;

&lt;p&gt;Loop tradicional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evento&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;esperandoEvento&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Se o evento retornar algo, verifica se a tecla 'I' do teclado foi pressionado&lt;/span&gt;
    &lt;span class="nx"&gt;InstanceManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderizarInventario&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Irá renderizar o inventário pelo tick atual, se o usuário parar de pressionar, o inventário é fechado.&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;DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keypress&lt;/span&gt;&lt;span class="dl"&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inventario&lt;/span&gt; &lt;span class="o"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt; &lt;span class="p"&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;body&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;inventario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inventario&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="c1"&gt;// Se a tecla 'I' for pressionada, adicionamos o inventário ao DOM, ao contrário, retiramos do DOM se ele estiver sendo renderizado.&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Se quisermos que o inventário seja renderizado até o usuário fechar manualmente, deixamos um booleano &lt;code&gt;true&lt;/code&gt; quando &lt;code&gt;keypress&lt;/code&gt; for acionado, e &lt;code&gt;false&lt;/code&gt; quando &lt;code&gt;keyup&lt;/code&gt; for acionado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os teclados possuem uma "trava" por padrão, esperando um tempo após o evento de pressionar para acionar outros eventos de 'keydown'. Podemos burlar da mesma forma do evento acima, usando um booleano. Em game-engines já temos este problema solucionado, agora para jogos na web as lib's &lt;a href="https://pixijs.io/"&gt;Pixi.js&lt;/a&gt; e &lt;a href="https://p5js.org/"&gt;P5.js&lt;/a&gt; também possuem formas internas de evitar este problema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://keycode.info/"&gt;Neste site&lt;/a&gt;, podemos encontrar o keyCode de cada tecla de uma maneira facilitada. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;keyCodes&lt;/strong&gt; não são padronizados, seja de navegador para navegador ou de sistema para sistema, recomendo fortemente em que procure a melhor forma de criar seu sistema de escuta.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;É possível construir UI para jogos com HTML e CSS?&lt;/em&gt; Sim! Uma das grandes tecnologias do mercado e utilizada pelas empresas como Riot Games (VALORANT), Ubisoft (The Division), entre outras, é feito com HTML/CSS/C++. Por mais que seja uma tecnologia "á encomenda", temos a opção do &lt;a href="https://ultralig.ht/"&gt;Ultralight&lt;/a&gt;, também sendo HTML/CSS/C++.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ciclo de Vida
&lt;/h3&gt;

&lt;p&gt;Os &lt;em&gt;loop's&lt;/em&gt; precisam possuir um padrão de código a ser executado, para evitar verificações dessincronizadas e a exibição de itens incorretamente. Para jogos em &lt;em&gt;real-time&lt;/em&gt;, essa diferença pode parecer ser minúscula, mas para jogos por turno, por exemplo, pode causar de renderizar algo que sequer existe no contexto.&lt;/p&gt;

&lt;p&gt;A seguir temos a forma padrão utilizada e que é recomendada:&lt;/p&gt;

&lt;p&gt;Por Imagem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t1AoPP6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ixWG8rA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t1AoPP6o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/ixWG8rA.png" alt="Imagem exibindo o ciclo de vida de um jogo padrão" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por Código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;entradaDeDados&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;atualizar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;renderizar&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;ul&gt;
&lt;li&gt;&lt;p&gt;entradaDeDados(): Aonde seria escutado a entrada de ações externas, como teclado e mouse. No DOM, não teríamos necessidade de colocar dentro de um loop, como mostrado no começo do artigo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;atualizar(): Aqui seria realizado todas as "regras de negócio" internas, como se o jogador levou dano, se um item foi adicionado no mapa, etc. Aqui também podemos realizar requisições HTTP e a serialização de dados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;renderizar(): irá buscar se possui novas informações, se não, continua renderizando as antigas informações.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ECS (Entity Component System)
&lt;/h3&gt;

&lt;p&gt;Traduzido diretamente como &lt;a href="https://pt.wikipedia.org/wiki/Entity-component-system"&gt;Sistema de Componente e Entidade&lt;/a&gt;, é a forma que &lt;em&gt;game-engines&lt;/em&gt; guardam e fornecem informações reativas para os nossos jogos. Na WEB são os Gerenciadores de Estado (Vuex do Vue, Redux/MobX do React), por seguirem a ideia de &lt;a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern"&gt;Pub/Sub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fluxo do Vuex:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MdYcVtJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/nooN3QV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MdYcVtJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/nooN3QV.png" alt="Vuex" width="733" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fluxo de um ECS Genérico:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ssLYL2Re--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OXzNerK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ssLYL2Re--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OXzNerK.png" alt="ECS" width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No JavaScript, temos um ECS simples chamado de &lt;a href="https://github.com/adngdb/entity-system-js"&gt;Ensy&lt;/a&gt;, e um criado para &lt;a href="https://medium.com/@clevyr/entity-component-system-for-react-js-e3ab6e9be776"&gt;React.js&lt;/a&gt;, mas longe de ser o ideal. Devido a isso, para jogos HTML5 se tem a necessidade de criar a própria logística interna. &lt;a href="https://webassembly.org/"&gt;WebAssembly&lt;/a&gt; pode ser uma boa alternativa para conseguir utilizar um ECS robusto.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Informações Adicionais
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Os Ciclos de Vida de um jogo padrão se comparado ao DOM pode mudar drasticamente dependendo da implementação desejada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se tratando de jogos HTML5, por mais que temos os &lt;a href="https://crypt.codemancers.com/posts/2020-02-17-concurrency_in_javascript_browser/"&gt;WebWorkers&lt;/a&gt;, JavaScript continua sendo single-thread, limitando a forma que podemos tratar eventos e a quantidade de &lt;em&gt;sprites&lt;/em&gt; a serem computadas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Realizar requisições HTTP sem paralelismo pode ser um problema bem grande, principalmente se estiver no loop.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Parte 2 - PixiJS
&lt;/h3&gt;

&lt;p&gt;Ainda não está disponível :(&lt;/p&gt;




&lt;p&gt;Este artigo foi escrito por Giovane Cardoso. &lt;a href="https://twitter.com/NovoutT"&gt;Twitter&lt;/a&gt; - &lt;a href="https://github.com/Novout"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webgl</category>
      <category>javascript</category>
      <category>gamedev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
