{"id":15825321,"url":"https://github.com/mirdware/scalar","last_synced_at":"2025-03-15T02:31:06.698Z","repository":{"id":65513447,"uuid":"76261795","full_name":"mirdware/scalar","owner":"mirdware","description":"Javascript not intrusive","archived":false,"fork":false,"pushed_at":"2024-03-19T20:40:49.000Z","size":242,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-12T09:36:46.793Z","etag":null,"topics":["components","data-binding","dependency-injection","javascript","scalar","state-management","templates","web-components"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mirdware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-12T14:05:41.000Z","updated_at":"2024-08-17T03:16:23.000Z","dependencies_parsed_at":"2024-01-17T04:27:15.342Z","dependency_job_id":"2279d6c5-0ccc-4bfb-9316-4cf3fd8647d7","html_url":"https://github.com/mirdware/scalar","commit_stats":{"total_commits":95,"total_committers":2,"mean_commits":47.5,"dds":"0.052631578947368474","last_synced_commit":"e466c1d35992796c0873db98a833a6f77e834175"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirdware%2Fscalar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirdware%2Fscalar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirdware%2Fscalar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirdware%2Fscalar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mirdware","download_url":"https://codeload.github.com/mirdware/scalar/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243674752,"owners_count":20329154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["components","data-binding","dependency-injection","javascript","scalar","state-management","templates","web-components"],"created_at":"2024-10-05T09:07:44.950Z","updated_at":"2025-03-15T02:31:06.226Z","avatar_url":"https://github.com/mirdware.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scalar\nScalar nace de la necesidad de crear sistemas escalables, de alto rendimiento y no obstructivos usando los últimos estándares de programación web, lo cual incluye el uso de las últimas características basadas en [ECMAScript](https://www.ecma-international.org/ecma-262/8.0/index.html).\n\nEl desarrollo de aplicaciones con scalar se basa en componentes no obstructivos o de backend, lo cual quiere decir que su funcionamiento no depende enteramente de javascript; obviamente muchas de las decisiones de que tan obstructivo puede llegar a ser scalar depende en gran medida del desarrollador. Otra premisa de scalar es la separación entre contenido, estilo y comportamiento.\n\n## Instalación\nExisten dos formas de usar scalar en un proyecto; la primera es mediante node y npm ejecutando el comando `npm i scalar`, la segunda es usar el [CDN](https://unpkg.com/scalar).\n\n```html\n\u003ch1 data-bind=\"msg\" id=\"hello-world\"\u003e\u003c/h1\u003e\n\u003cscript src=\"https://unpkg.com/scalar\"\u003e\u003c/script\u003e\n\u003cscript defer\u003e\n  new scalar.Module()\n  .compose('#hello-world', ($) =\u003e ({\n    mount: () =\u003e $.msg = 'Hello world!!!'\n  })).execute();\n\u003c/script\u003e\n```\n\nEn ambiente de desarrollo es imprescindible contar con [node](https://nodejs.org/es/) y [git](https://git-scm.com/) en sus últimas versiones.\n\nClona o copia desde el repositorio principal de scalar.\n\n```bash\ngit clone git@github.com:mirdware/scalar.git\n```\n\nIngresa a la carpeta del proyecto y descarga las dependencias.\n\n```bash\ncd scalar \u0026\u0026 npm install\n```\n\nUna vez instaladas es posible ejecutar un servidor webpack con el comando `npm run serve`, construir el proyecto con `npm run build` o ambas mediante `npm start`.\n\n## Módulos\nUn módulo es un objeto javascript que se instancia de la clase Module de scalar, se deben proveer por constructor las dependencias para luego declarar cada uno de los componentes mediante el método `compose('#selector', customComponent)`, esto se logra enviando como primer parámetro el selector del elemento y como segundo la función o clase conductual.\n\nEl método `add(module)` se encarga de agregar un módulo junto a todos sus servicios al sistema de inyección de dependencias del módulo que invocó el método.\n\nMediante compose solo se declara el componente en el módulo pero no se ejecuta dentro de la estructura de la página; para esto se debe hacer uso el método `execute()`.\n\n```javascript\nimport { Module } from 'scalar';\nimport Message from './services/Message';\nimport formComponent from './components/form';\n\nconst module = new Module(Message);\nnew Module()\n.compose('#hello-world', formComponent)\n.add(module)\n.execute();\n```\n\nLa ejecución del componente genera un `compound object`(Objeto compuesto) que contiene las propiedades enlazadas a la plantilla mediante `data-bind` y/o `data-attr`, este enlace varia de uno a doble sentido según sea el caso.\n\n```html\n\u003cinput type=\"text\" value=\"scalar\" data-bind=\"name\" /\u003e\n\u003csc-hi data-attr=\"name:name\"\u003e\n  \u003cp slot=\"body\"\u003eProbando \u003ca href=\"\"\u003elink\u003c/a\u003e desde fuera.\u003c/p\u003e\n\u003c/sc-hi\u003e\n```\n\n### Servicios\nUn servicio no es más que un objeto común al ámbito del módulo al que pertenece. Este debe ser declarado al momento de realizar la instanciación del módulo al cual va a quedar asociado.\n\n```javascript\nimport { Module } from 'scalar';\nimport Message from './services/Message';\n\nconst module = new Module(Message);\n```\n\nUna vez declarado el servicio es posible usarlo mediante el método inject del compound object o de la función enviada a cada servicio, teniendo siempre en cuenta el no generar dependencias cíclicas.\n\n```javascript\nimport Service from './OtherService';\n\nclass Service {\n  constructor(inject) {\n    this _service = inject(OtherService);\n  }\n}\n```\n\nEs posible mockear o falsear las dependencias mediante el método `bind(Message, Fake)`, de esta manera cada vez que se solicite la dependencia Message se entregara una instancia de Fake.\n\n## Componentes\nExisten diferentes maneras de generar un componente; la primera es extendiendo de la clase Component de scalar con lo que deberá implementar el método listen que retorna un `behavioral object`(Objeto conductual).\n\n```javascript\nexport default class ToDo extends Component {\n  listen() {\n    return {\n      submit: () =\u003e add(this),\n      '.close': { click: (e) =\u003e remove(this, e) },\n      '.check': { click: (e) =\u003e crossOutItem(e) },\n      '#clean': { click: () =\u003e this.tasks = [] }\n    };\n  }\n}\n```\n\nPara generar web components el funcionamiento es muy similar al de componentes basados en clases, con la diferencia que se debe agregar el decorator `@customElement` con los estilos y template para dicho componente, más adelante se detallara el uso de este método.\n\nOtra manera es mediante `behavioral function`(función conductual) la cual es una función pura de javascript que retorna las acciones del componente; la función recibe como parámetro un objeto compuesto y retorna un objeto conductual.\n\n```javascript\nexport default ($) =\u003e ({\n  submit: (e) =\u003e {\n    if (!$.task) return;\n    $.tasks.push($.task);\n    $.task = \"\";\n  },\n  '.close': {\n    click: (e) =\u003e {\n      const index = e.target.parentNode.dataset.index;\n      $.tasks.splice(index, 1);\n    }\n  },\n  '#clean': { click: () =\u003e $.tasks = [] }\n});\n```\n\nAl ser una función javascript pura se pueden usar diferentes estilos de programación. En el ejemplo anterior vimos un retorno directo del objeto, pero también es posible usar clousures.\n\n```javascript\nexport default ($) =\u003e {\n  function remove(e) {\n    const index = e.target.parentNode.dataset.index;\n    $.tasks.splice(index, 1);\n  }\n\n  function add() {\n    if (!$.task) return;\n    $.tasks.push($.task);\n    $.task = \"\";\n  }\n\n  return {\n    submit: (e) =\u003e add,\n    '.close': { click: (e) =\u003e remove },\n    '#clean': { click: () =\u003e $.tasks = [] }\n  };\n};\n```\n\nIncluso es posible usar las últimas características de ECMAScript para encapsular llamadas a otras funciones en módulos.\n\n```javascript\nfunction remove($, e) {\n    const index = e.target.parentNode.dataset.index;\n    $.tasks.splice(index, 1);\n}\n\nfunction add($) {\n    if (!$.task) return;\n    $.tasks.push($.task);\n    $.task = '';\n}\n\nexport default ($) =\u003e ({\n  submit: (e) =\u003e add($),\n  '.close': { click: (e) =\u003e remove($, e) },\n  '#clean': { click: () =\u003e $.tasks = [] }\n});\n```\n\n### Definición del objeto conductual\nMediante javascript se establece el comportamiento de un componente por lo cual se debe retornar un objeto con selectores CSS o nombres de evento (click, submit, reset, blur, focus, etc) como llaves, en el primer caso su valor deberá ser otro objeto con similares características y en el segundo contendrá el manejador del evento, a esta estructura se le denomina objeto conductual.\n\nLos eventos lanzados por un objeto conductual tienen un comportamiento de burbuja y son pasivos, si se antepone el signo `_` a su nombre este prevendrá su acción por defecto y se volvera activo, si es necesario se puede retornar true para ejecutar el comportamiento del elemento pero esto no modificara el hecho que el evento a dejado de ser pasivo; si el signo aparece después del nombre quiere decir que sé está forzando la propagación en modo captura, es posible usar ambas características a la vez.\n\n```javascript\nreturn {\n  _submit: (e) =\u003e add($),\n  '.close': { _click: (e) =\u003e remove($, e) },\n  '#clean': { click: () =\u003e $.tasks = [] }\n}\n```\n\nEl evento `mount` es ejecutado tan pronto inicia el componente y cualquier cambio que se realice dentro de este hace parte del estado inicial por lo cual es ideal para enlazar propiedades y servicios.\n\nAparte de mount existe el evento especial `mutate` el cual notifica cuando un elemento del componente ha sido modificado, para escuchar el evento se debe enlazar al elemento que se transformara con la mutación de la propiedad.\n\n```javascript\nreturn {\n  mount: () =\u003e message.my = $.my,\n  '.input': { mutate: (e) =\u003e mask(e.target) }\n}\n```\n\n### Métodos del objeto compuesto\nEs posible hacer uso de servicios mediante el método `inject(Message)` enviando como parámetro la clase que fue proveída al módulo, si esta no fue declarada se retornara undefined.\n\nPara hacer uso de un arreglo dentro de un componente se debe establecer un data-key que sirva como índice del elemento, posteriormente se obtiene mediante el método `getIndex(e)` el cual recibe el evento como parámetro.\n\nUn componente puede generar otro mediante el método `compose($domElement, customComponent)`, este último se denomina **componente derivado**, ya que su creación no se realizó desde un módulo sino que deriva de un similar. Se puede hacer uso de los métodos de un derivado ya que compose retorna el objeto compuesto.\n\n```javascript\nconst index = $.getIndex(e);\nconst $domElement = await $.inject(Modal).open('https://sespesoft.com/resource', 'Recurso');\nconst response = await $.compose($domElement, modalCOmponet).send({ index });\n```\n\n### Solapamiento de componentes\nEl solapamiento (overloaping) se presenta cuando se define un componente sobre otro ya establecido.\n\n```javascript\nnew Module()\n.compose('.pageable', pageable)\n.compose('.check-table', checkTable)\nexecute();\n```\n\n```html\n\u003cdiv class=\"pageable\"\u003e\n    \u003cform action=\"https://sespesoft.com/resource\"\u003e\n        \u003cinput type=\"search\" name=\"name\" data-bind=\"name\"/\u003e\n        \u003cinput type=\"submit\" value=\"Buscar\"/\u003e\n    \u003c/form\u003e\n    \u003ctable class=\"check-table\" data-bind=\"data\"\u003e\n        \u003cscript type=\"text/template\"\u003e\n            \u003ctr\u003e\n              \u003ctd\u003e${data.one}\u003c/td\u003e\n              \u003ctd\u003e${data.two}\u003c/td\u003e\n              \u003ctd\u003e\u003cinput type=\"checkbox\" /\u003e\u003c/td\u003e\n            \u003c/tr\u003e\n        \u003c/script\u003e\n    \u003c/table\u003e\n\u003c/div\u003e\n```\n\nEn este caso tanto el componente pageable como checkTable hacen uso de la propiedad data, a esto hace referencia el solapamiento a compartir propiedades gracias a su ubicación dentro del DOM; un cambio en una propiedad afectara a la propiedad del componente solapado. Se debe tener cuidado al momento de solapar componentes pues es posible tener resultados inesperados, en muchas ocaciones lo recomendable es aislar cada comportamiento.\n\n### Aislamiento mediante web componentes\nEn la versión `0.3.0` de scalar se da soporte al standard de [web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components), lo cual se genera una dependencia hacia javascript; a pesar que esto va en contra de generar componentes no obstructivos se puede agregar o no estas caracteristicas e ir escalando según las necesidades del proyecto.\n\nLa implementación del [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) se realiza mediante el decorator `@customElement` el cual recibe las propiedades styles, template y type, este último es para soportar el estandard con el uso de diferentes elementos HTML.\n\n```javascript\n@customElement({\n    template: '\u003cstrong\u003eHola \u003cspan data-bind=\"name\"\u003emundo\u003c/span\u003e!!\u003c/strong\u003e' +\n    '\u003cslot name=\"body\"\u003e\u003cp\u003ePor favor de click \u003ca href=\"\"\u003eaquí\u003c/a\u003e\u003c/p\u003e\u003c/slot\u003e',\n    styles: 'strong{color:#f58731;} ' +\n    'img{vertical-align: middle; margin-right: 1em;} ' +\n    ':host{border: 1px solid; display: block; border-radius: 1em; padding: .5em; margin: .5em;}'\n})\nexport default class Greeting extends Component {}\n```\n\nComo se puede observar el web component debe extender de Component y no de HTMLElement como lo hace el estandard, esto es para que la libreria pueda manejar cosas como el [shadown DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) y ciertas funciones del ciclo de vida que se integran en el comportamiento normal de un backend component.\n\nEs importante mencionar que el componente puede hacer uso de todos los métodos del ciclo de vida del custom element como: `attributeChangedCallback(name, oldValue, newValue)`, `connectedCallback()` o `disconnectedCallback()`, al igual que del método `onInit()` el cual es implementado por la libreria y se ejcuta cuando el componente es montado; al basarse en el estandar es posible hacer uso de [slots y templates](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots).\n\nEl uso de `observedAttributes` se reemplaza por la declaración explicita de la priopiedad dentro de la clase.\n\n```javascript\nexport default class MultiSelect extends Component {\n  constructor() {\n    super();\n    this._currentFocus = -1;\n    this.placeholder = '';\n    this.required = false;\n    this.value = [];\n  }\n}\n```\n\nEl constructor debe llamar al padre y proceder a declarar las propiedades, cabe resaltar el uso del caracter `_` para iniciar ciertas declaraciones, estas son propiedades que no se exponen al custom element, al igual que aquellas que inicien con `$`, las propiedades deben inicializarse para indicar como debe observedAttributes tratar el nuevo valor, así cuando es booleano y se aplica al elemento este lo convertira a `true` o si es un objeto `[]` o `{}` se tratara de hacer un `JSON.parse`.\n\n```html\n\u003cmulti-select placeholder=\"Seleccionar tipo de items\" _current-focus=\"0\" required\u003e\n  \u003coption value=\"0\" selected\u003eCard\u003c/option\u003e\n  \u003coption value=\"1\" selected\u003eTable\u003c/option\u003e\n  \u003coption value=\"2\" selected\u003eColumn\u003c/option\u003e\n\u003c/multi-select\u003e\n```\n\nLa propiedad `_currentFocus` no sera enlazada al custom element. El paso de attributos dinamicos se sigue usando mediante `data-attr` como se haria con cualquier componente, cabe resaltar que es posible enviar datos complejos como objetos o arrays, los cuales seran codificados en JSON para enviar, por lo cual estos pasaran como valor y cualquier modifificación dentro del custom element no se vera reflejada en el componente padre que envio el objeto (inmutabilidad).\n\n```html\n\u003cauto-complete required=\"required\" placeholder=\"Countries\" data-attr=\"data:countries\"\u003e\u003c/auto-complete\u003e\n```\n\nLas unicas vias de comunicación entre custom element y componente padre son los atributos y [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent), por lo tanto el enlace en doble vía no es posible en este tipo de comunicación y se debe de hacer de manera explicita.\n\n```javascript\n{\n  'multi-select': { changed: (e) =\u003e $.multi = e.detail }\n}\n```\n\n### Integración entre components\nEs posible hacer uso de ambos tipos de componentes dentro de una misma aplicación, supongamos un `.extenal-component` compuesto.\n\n```html\n\u003csection class=\"external-component\"\u003e\n  \u003cinput type=\"text\" value=\"scalar\" data-bind=\"name\" /\u003e\n  \u003csc-hi data-attr=\"name:name\" /\u003e\n\u003c/section\u003e\n```\n\n## Plantillas\nLas plantillas (Templates) representan la parte más básica del sistema y se pueden clasificar en: prerenderizadas y JIT (Just In Time).\n\n### Prerenderizadas\nLas plantillas prerenderizadas son aquellas suministradas por el servidor y hacen parte integral del cuerpo de la respuesta, de esta manera se puede garantizar el funcionamiento de la aplicación aun si el cliente no activa JavaScript; en parte la idea de la librería es ir _\"escalando\"_ un proyecto según la limitación del cliente (accesibilidad).\n\nUna plantilla scalar podría contener atributos `data-bind` y/o `data-attr`, los primeros generan un enlace en dos direcciones entre el objeto compuesto y la plantilla, siempre y cuando el elemento al cual se enlaza pueda introducir información, en caso contrario dicho enlace se establecerá en una sola dirección; el segundo modifica los atributos del elemento según se modifique alguna propiedad y por su naturaleza es unidireccional.\n\nMediante data-bind se crea un enlace a una propiedad del componente, por lo tanto debe tener el formato de una [propiedad javascript](https://developer.mozilla.org/es/docs/Web/JavaScript/Data_structures#Objetos), mientras data-attr puede tener tantos atributos separados por `;` como se desee, un atributo es un par clave valor en donde la clave es el nombre del atributo y el valor la propiedad del componente o una expresión javascript que manejará los cambios de estado, en caso de ser una propiedad no definida en un data-bind esta se creara en el componente, si la propiedad se encuentra dentro de una expresión esto no será posible.\n\nCuando se desea declarar un objeto desde el sistema de plantillas se debe separar con `.` cada una de las propiedades del mismo, esto aplica también para modificaciones de atributos como estilos.\n\n```html\n\u003cdiv id=\"square\" data-attr=\"style: squareStyle\"\u003e\n    \u003cspan data-attr=\"classList: action\" class=\"open\"\u003e\u003c/span\u003e\n    \u003ch2 data-bind=\"my.msg\" data-attr=\"style.color:my.color\" style=\"color:#fff\"\u003eMensaje inicial\u003c/h2\u003e\n\u003c/div\u003e\n```\n### JIT\nEl soporte para plantillas JIT está aún en una etapa bastante temprana, pero se están haciendo progresos. Su principal uso se encuentra restringido al enlace de datos cuando la propiedad de un componente es compleja (principalmente arreglos) y su función es generar código HTML de manera dinámica. Una propiedad es definida como compleja cuando dentro se haya un script tipo `text/template`.\n\n```html\n\u003cul data-bind=\"tasks\"\u003e\n    \u003cscript type=\"text/template\"\u003e\n        \u003cli data-key=\"${index}\"\u003e\n            \u003cspan class=\"${data.checked}\"\u003e${data.content}\u003c/span\u003e\n            \u003ca href=\"#\" class=\"check\"\u003e✔\u003c/a\u003e\n            \u003ca href=\"#\" class=\"close\"\u003e[x]\u003c/a\u003e\n        \u003c/li\u003e\n    \u003c/script\u003e\n\u003c/ul\u003e\n```\n\nSiempre que se quiera manipular un arreglo desde el componente este debe estar indexado por `data-key` de esta manera es posible hacer uso del método getIndex.\n\nTambien existe la posibilidad de realizar un enlace directamente al template tomando de esta manera al elemento padre como base; esto es útil cuando un elemento debe tener un enlace con otra propiedad, pero su contenido se debe manejar dinamicamente (ej. selects dependientes).\n\n```html\n\u003cselect data-bind=\"select\"\u003e\n    \u003coption\u003eOne\u003c/option\u003e\n    \u003coption\u003eTwo\u003c/option\u003e\n    \u003coption\u003eThree\u003c/option\u003e\n    \u003cscript type=\"text/template\" data-bind=\"dependencies\"\u003e\n        \u003coption\u003e${data.name}\u003c/option\u003e\n    \u003c/script\u003e\n\u003c/select\u003e\n```\n\nSe puede interpolar código javaScript mediante el uso de la notación [template string](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/template_strings) `${}`; dentro de la plantilla es posible acceder a dos propiedades `index` y `data`, la primera indica el índice del array y la segunda la información contenida en el mismo.\n\n### Un/pairing mode\n\nAntes de la versión `0.3.0` la forma común de enlazar datos a las propiedades de un array era mediante emparejamiento (pairing), esto se da cuando el template y el contenido del elemento son _exactamente_ iguales y difieren solo en la iterpolación; de esta manera los datos interpolados que partan del objeto `data` y no sean expresiones se combierten en parte del array.\n\nEl uso de data-attr en la fase de emparejamiento puede generar comportamientos inesperados por lo cual se desanconseja su uso y se recomienda la interpolación de attributos.\n\nEn recientes versiones se puede hacer uso de una nueva tecnica de enlace para datos complejos `array.${index}.name` y en la actualidad es el método por defecto a utilizar para poblar dinamicamente el array.\n\nLa notación de punto podría generar error al usar directamente desde javascript pero no desde el data-bind; con esto el enlace se realiza directamente por lo cual no es necesario que el template y el contenido del elemento coincidan en lo absoluto (unpairing). Aunque ya no sea necesario realizar emparejamiento, la hidatación de la pantalla continua realizandose desde el template por lo cual este debe ser bastante parecido al cargue inicial.\n\nPara poder usar el modo de emparejamiento es necesario colocarlo explicitamente en el script de la plantilla mediante el atributo `data-pairing`.\n\n```html\n\u003cscript type=\"text/template\" data-pairing\u003e\n  \u003cli data-key=\"${index}\"\u003e\n    \u003cspan class=\"${data.checked}\"\u003e${data.content}\u003c/span\u003e\n    \u003ca class=\"check\" href=\"#\"\u003e✔\u003c/a\u003e\n    \u003ca class=\"close\" href=\"#\"\u003e[x]\u003c/a\u003e\n  \u003c/li\u003e\n\u003c/script\u003e\n```\n\n### Hidden DOM\n\nActualmente la idea de usar virtual DOM como mecanismo de actualización para las plantillas JIT se encuentra pospuesto, en su lugar se esta experimentando con el uso de un hidden DOM. El cual funciona como un [documentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) que no es adicionado al DOM en ningún momento, si no que sirve como referencia para saber exactamente cuales son los cambios que se deben realizar.\n\n# Todo\n* :bug: `required` dentro de la plantilla se empareja con `required=\"\"` fuera de la plantilla. _El error solo se presenta en paring mode_.\n* :bug: al usar interpolaciones seguidas en una plantilla `${var1} ${var2}`. _El error solo se presenta en paring mode_.\n* :bug: al realizar solapamientos. _Se re comienda no realizar solapamientos usando web components_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirdware%2Fscalar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmirdware%2Fscalar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirdware%2Fscalar/lists"}