[{"data":1,"prerenderedAt":516},["ShallowReactive",2],{"es-main-blog_es-\u002Fes\u002Fblog\u002Flint-tailwind-css-v4-with-eslint\u002F":3,"es-alternative-blog_en-\u002Fblog\u002Flint-tailwind-css-v4-with-eslint":234,"blog_es-related-\u002Fes\u002Fblog\u002Flint-tailwind-css-v4-with-eslint\u002F":463},{"id":4,"title":5,"body":6,"date":218,"description":219,"extension":220,"image":221,"meta":222,"navigation":111,"path":223,"readingTime":224,"schemaOrg":221,"seo":225,"stem":226,"tags":227,"toc":232,"updatedAt":221,"__hash__":233},"blog_es\u002Fes\u002Fblog\u002F0006.lint-tailwind-css-v4-with-eslint.md","@angelblanco\u002Feslint-config 3.0 ya disponible, ahora con Tailwind CSS",{"type":7,"value":8,"toc":214},"minimark",[9,26,46,49,54,57,86,93,149,166,170,179,198,205,210],[10,11,12,19,20,25],"p",{},[13,14,18],"a",{"href":15,"rel":16},"https:\u002F\u002Fgithub.com\u002Fangelblanco\u002Feslint-config",[17],"nofollow","@angelblanco\u002Feslint-config 3.0"," ya está disponible en npm. Ahora puedes pasar el linter por tus clases de ",[13,21,24],{"href":22,"rel":23},"https:\u002F\u002Ftailwindcss.com\u002F",[17],"Tailwind CSS",".",[10,27,28,29,33,34,39,40,45],{},"Cuando empecé este blog y ",[13,30,32],{"href":31},"\u002Fes\u002Fblog\u002Fcreate-your-eslint-config\u002F","creé mi propia configuración de ESLint"," en 2025, todavía no había un plugin de ",[13,35,38],{"href":36,"rel":37},"https:\u002F\u002Feslint.org\u002F",[17],"ESLint"," para Tailwind CSS v4. En noviembre de 2026 estoy actualizando mis repositorios open source, y ",[13,41,44],{"href":42,"rel":43},"https:\u002F\u002Fgithub.com\u002Ffrancoismassart\u002Feslint-plugin-tailwindcss",[17],"eslint-plugin-tailwindcss"," por fin está listo.",[10,47,48],{},"Es impresionante cuánto puede cambiar en un año el stack que usas, pero de eso escribiré en próximos artículos.",[50,51,53],"h2",{"id":52},"activa-el-lint-de-tailwind-css","Activa el lint de Tailwind CSS",[10,55,56],{},"Instala el plugin (necesita Tailwind CSS v4):",[58,59,64],"pre",{"className":60,"code":61,"language":62,"meta":63,"style":63},"language-bash shiki shiki-themes catppuccin-latte catppuccin-mocha","pnpm add -D eslint-plugin-tailwindcss\n","bash","",[65,66,67],"code",{"__ignoreMap":63},[68,69,72,76,80,83],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"sMmZK","pnpm",[68,77,79],{"class":78},"sgueU"," add",[68,81,82],{"class":78}," -D",[68,84,85],{"class":78}," eslint-plugin-tailwindcss\n",[10,87,88,89,92],{},"Después activa la opción ",[65,90,91],{},"tailwind"," e indícale tu fichero CSS de entrada:",[58,94,99],{"className":95,"code":96,"filename":97,"language":98,"meta":63,"style":63},"language-js shiki shiki-themes catppuccin-latte catppuccin-mocha","import eslintConfig from '@angelblanco\u002Feslint-config';\n\nexport default eslintConfig(defaultOptions => ({\n  ...defaultOptions,\n  tailwind: {\n    cssConfigPath: 'app\u002Fassets\u002Fcss\u002Fmain.css',\n  },\n}));\n","eslint.config.js","js",[65,100,101,106,113,119,125,131,137,143],{"__ignoreMap":63},[68,102,103],{"class":70,"line":71},[68,104,105],{},"import eslintConfig from '@angelblanco\u002Feslint-config';\n",[68,107,109],{"class":70,"line":108},2,[68,110,112],{"emptyLinePlaceholder":111},true,"\n",[68,114,116],{"class":70,"line":115},3,[68,117,118],{},"export default eslintConfig(defaultOptions => ({\n",[68,120,122],{"class":70,"line":121},4,[68,123,124],{},"  ...defaultOptions,\n",[68,126,128],{"class":70,"line":127},5,[68,129,130],{},"  tailwind: {\n",[68,132,134],{"class":70,"line":133},6,[68,135,136],{},"    cssConfigPath: 'app\u002Fassets\u002Fcss\u002Fmain.css',\n",[68,138,140],{"class":70,"line":139},7,[68,141,142],{},"  },\n",[68,144,146],{"class":70,"line":145},8,[68,147,148],{},"}));\n",[10,150,151,152,155,156,159,160,165],{},"Viene desactivado por defecto. Si tu CSS está en ",[65,153,154],{},"src\u002Fstyle.css",", basta con ",[65,157,158],{},"tailwind: true",". El resto de ",[13,161,164],{"href":162,"rel":163},"https:\u002F\u002Fgithub.com\u002Ffrancoismassart\u002Feslint-plugin-tailwindcss#settings",[17],"ajustes del plugin"," van en el mismo objeto.",[50,167,169],{"id":168},"actualiza-a-antfueslint-config-v10-y-eslint-10","Actualiza a @antfu\u002Feslint-config v10 y ESLint 10",[10,171,172,173,178],{},"La 3.0 también actualiza a ",[13,174,177],{"href":175,"rel":176},"https:\u002F\u002Fgithub.com\u002Fantfu\u002Feslint-config",[17],"@antfu\u002Feslint-config"," v10 y ESLint 10. Instala la última versión de ambos paquetes:",[58,180,182],{"className":60,"code":181,"language":62,"meta":63,"style":63},"pnpm add -D eslint@latest @angelblanco\u002Feslint-config@latest\n",[65,183,184],{"__ignoreMap":63},[68,185,186,188,190,192,195],{"class":70,"line":71},[68,187,75],{"class":74},[68,189,79],{"class":78},[68,191,82],{"class":78},[68,193,194],{"class":78}," eslint@latest",[68,196,197],{"class":78}," @angelblanco\u002Feslint-config@latest\n",[10,199,200,201,204],{},"La primera vez que ejecutes ",[65,202,203],{},"eslint --fix"," verás que reformatea algunos arrays, objetos y ternarios multilínea.",[206,207],"github-repo-preview",{"description":208,"repo":209},"Configuración de ESLint de Ángel Blanco, construida sobre @antfu\u002Feslint-config para proyectos Vue + TypeScript.","angelblanco\u002Feslint-config",[211,212,213],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}",{"title":63,"searchDepth":108,"depth":108,"links":215},[216,217],{"id":52,"depth":108,"text":53},{"id":168,"depth":108,"text":169},"2026-11-07","@angelblanco\u002Feslint-config 3.0 ya está en npm: lint opcional de Tailwind CSS v4, @antfu\u002Feslint-config v10 y ESLint 10.","md",null,{},"\u002Fes\u002Fblog\u002Flint-tailwind-css-v4-with-eslint","2",{"title":5,"description":219},"es\u002Fblog\u002F0006.lint-tailwind-css-v4-with-eslint",[228,229,230,231],"eslint","tailwindcss","tooling","npm",false,"40hwZlwShaqUR-Tmj-2YmvXDxrkE9iMpSV3hqkGvnWQ",{"id":235,"title":236,"body":237,"date":218,"description":456,"extension":220,"image":221,"meta":457,"navigation":111,"path":458,"readingTime":224,"schemaOrg":221,"seo":459,"stem":460,"tags":461,"toc":232,"updatedAt":221,"__hash__":462},"blog_en\u002Fblog\u002F0006.lint-tailwind-css-v4-with-eslint.md","@angelblanco\u002Feslint-config 3.0 is out, now with Tailwind CSS",{"type":7,"value":238,"toc":452},[239,249,265,268,272,275,289,295,399,413,417,424,440,446,449],[10,240,241,244,245,248],{},[13,242,18],{"href":15,"rel":243},[17]," is available on npm. You can now lint your ",[13,246,24],{"href":22,"rel":247},[17]," classes.",[10,250,251,252,256,257,260,261,264],{},"When I started this blog and ",[13,253,255],{"href":254},"\u002Fblog\u002Fcreate-your-eslint-config\u002F","created my own ESLint config"," in 2025, there was no ",[13,258,38],{"href":36,"rel":259},[17]," plugin for Tailwind CSS v4 yet. In November 2026 I'm updating my open source repositories, and ",[13,262,44],{"href":42,"rel":263},[17]," is finally ready.",[10,266,267],{},"It's impressive how much the stack you use can change in a year, but I'll write about that in upcoming posts.",[50,269,271],{"id":270},"enable-tailwind-css-linting","Enable Tailwind CSS linting",[10,273,274],{},"Install the plugin (it requires Tailwind CSS v4):",[58,276,277],{"className":60,"code":61,"language":62,"meta":63,"style":63},[65,278,279],{"__ignoreMap":63},[68,280,281,283,285,287],{"class":70,"line":71},[68,282,75],{"class":74},[68,284,79],{"class":78},[68,286,82],{"class":78},[68,288,85],{"class":78},[10,290,291,292,294],{},"Then enable the ",[65,293,91],{}," option and point it to your CSS entry file:",[58,296,297],{"className":95,"code":96,"filename":97,"language":98,"meta":63,"style":63},[65,298,299,319,323,350,362,373,385,389],{"__ignoreMap":63},[68,300,301,305,309,312,315],{"class":70,"line":71},[68,302,304],{"class":303},"sAS4m","import",[68,306,308],{"class":307},"s0aCy"," eslintConfig ",[68,310,311],{"class":303},"from",[68,313,314],{"class":78}," '@angelblanco\u002Feslint-config'",[68,316,318],{"class":317},"sxyLT",";\n",[68,320,321],{"class":70,"line":108},[68,322,112],{"emptyLinePlaceholder":111},[68,324,325,328,331,334,337,341,344,347],{"class":70,"line":115},[68,326,327],{"class":303},"export",[68,329,330],{"class":303}," default",[68,332,333],{"class":74}," eslintConfig",[68,335,336],{"class":307},"(",[68,338,340],{"class":339},"s2f33","defaultOptions",[68,342,343],{"class":303}," =>",[68,345,346],{"class":307}," (",[68,348,349],{"class":317},"{\n",[68,351,352,356,359],{"class":70,"line":121},[68,353,355],{"class":354},"sjJjI","  ...",[68,357,340],{"class":358},"seXix",[68,360,361],{"class":317},",\n",[68,363,364,367,370],{"class":70,"line":127},[68,365,366],{"class":307},"  tailwind",[68,368,369],{"class":354},":",[68,371,372],{"class":317}," {\n",[68,374,375,378,380,383],{"class":70,"line":133},[68,376,377],{"class":307},"    cssConfigPath",[68,379,369],{"class":354},[68,381,382],{"class":78}," 'app\u002Fassets\u002Fcss\u002Fmain.css'",[68,384,361],{"class":317},[68,386,387],{"class":70,"line":139},[68,388,142],{"class":317},[68,390,391,394,397],{"class":70,"line":145},[68,392,393],{"class":317},"}",[68,395,396],{"class":307},"))",[68,398,318],{"class":317},[10,400,401,402,404,405,407,408,412],{},"It's disabled by default. If your CSS lives at ",[65,403,154],{},", ",[65,406,158],{}," is enough. The other ",[13,409,411],{"href":162,"rel":410},[17],"plugin settings"," go in the same object.",[50,414,416],{"id":415},"upgrade-to-antfueslint-config-v10-and-eslint-10","Upgrade to @antfu\u002Feslint-config v10 and ESLint 10",[10,418,419,420,423],{},"3.0 also updates to ",[13,421,177],{"href":175,"rel":422},[17]," v10 and ESLint 10. Upgrade both packages:",[58,425,426],{"className":60,"code":181,"language":62,"meta":63,"style":63},[65,427,428],{"__ignoreMap":63},[68,429,430,432,434,436,438],{"class":70,"line":71},[68,431,75],{"class":74},[68,433,79],{"class":78},[68,435,82],{"class":78},[68,437,194],{"class":78},[68,439,197],{"class":78},[10,441,442,443,445],{},"Expect ",[65,444,203],{}," to reformat some multi-line arrays, objects and ternaries the first time you run it.",[206,447],{"description":448,"repo":209},"Ángel Blanco's ESLint configuration, built on @antfu\u002Feslint-config for Vue + TypeScript projects.",[211,450,451],{},"html pre.shiki code .sMmZK, html code.shiki .sMmZK{--shiki-default:#1E66F5;--shiki-default-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic}html pre.shiki code .sgueU, html code.shiki .sgueU{--shiki-default:#40A02B;--shiki-dark:#A6E3A1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sAS4m, html code.shiki .sAS4m{--shiki-default:#8839EF;--shiki-dark:#CBA6F7}html pre.shiki code .s0aCy, html code.shiki .s0aCy{--shiki-default:#4C4F69;--shiki-dark:#CDD6F4}html pre.shiki code .sxyLT, html code.shiki .sxyLT{--shiki-default:#7C7F93;--shiki-dark:#9399B2}html pre.shiki code .s2f33, html code.shiki .s2f33{--shiki-default:#E64553;--shiki-default-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic}html pre.shiki code .sjJjI, html code.shiki .sjJjI{--shiki-default:#179299;--shiki-dark:#94E2D5}html pre.shiki code .seXix, html code.shiki .seXix{--shiki-default:#E64553;--shiki-dark:#EBA0AC}",{"title":63,"searchDepth":108,"depth":108,"links":453},[454,455],{"id":270,"depth":108,"text":271},{"id":415,"depth":108,"text":416},"@angelblanco\u002Feslint-config 3.0 is available on npm: optional Tailwind CSS v4 linting, @antfu\u002Feslint-config v10 and ESLint 10.",{},"\u002Fblog\u002Flint-tailwind-css-v4-with-eslint",{"title":236,"description":456},"blog\u002F0006.lint-tailwind-css-v4-with-eslint",[228,229,230,231],"FSzUArCYkVVm935pw4kbUyZ23SOtOEjrUS_BePcHkBA",[464,466,477,487,497,505],{"id":4,"path":223,"title":5,"description":219,"date":218,"readingTime":224,"tags":465},[228,229,230,231],{"id":467,"path":468,"title":469,"description":470,"date":471,"readingTime":472,"tags":473},"blog_es\u002Fes\u002Fblog\u002F0005.apt-install-php-85-on-ubuntu-26.md","\u002Fes\u002Fblog\u002Fapt-install-php-85-on-ubuntu-26","Instalar PHP 8.5 con apt en Ubuntu 26.04","Instala PHP 8.5 y Composer en Ubuntu 26.04 LTS con apt desde el repositorio packages.sury.org de Ondřej Surý y mantenlos al día con apt upgrade.","2026-11-06","12",[474,475,476,62],"php","ubuntu","composer",{"id":478,"path":479,"title":480,"description":481,"date":482,"readingTime":483,"tags":484},"blog_es\u002Fes\u002Fblog\u002F0004.apt-install-node-26-on-ubuntu-26.md","\u002Fes\u002Fblog\u002Fapt-install-node-26-on-ubuntu-26","Instalar Node.js 26 con apt en Ubuntu 26.04","El 21 de octubre de 2026, Node.js publicó parches de seguridad para diez vulnerabilidades que afectan a sus versiones con soporte, cuatro de ellas graves, incluida una ejecución remota de código. Las versiones sin soporte, como Node.js 20 y 25, no recibirán actualizaciones.","2026-11-05","8",[485,475,486,62],"nodejs","javascript",{"id":488,"path":489,"title":490,"description":491,"date":492,"readingTime":493,"tags":494},"blog_es\u002Fes\u002Fblog\u002F0003.create-your-eslint-config.md","\u002Fes\u002Fblog\u002Fcreate-your-eslint-config","Crea tu propia configuración de ESLint y compártela entre proyectos","Si alguna vez has trabajado en varios proyectos, conoces el aburrimiento de copiar configuraciones de ESLint de un repositorio a otro. Cada vez que empiezas un proyecto nuevo, o partes de cero o copias el archivo eslint.config.js del anterior. Hay una forma mejor: publicar tu propio paquete de configuración de ESLint.","2025-11-02","3",[228,495,496,230,231],"typescript","vue",{"id":498,"path":499,"title":500,"description":501,"date":502,"readingTime":503,"tags":504},"blog_es\u002Fes\u002Fblog\u002F0002.install-node-24-on-ubuntu-24.md","\u002Fes\u002Fblog\u002Finstall-node-24-on-ubuntu-24","Instalar Node.js 24 en Ubuntu 24.04","Instalar Node.js 24 en Ubuntu 24 debería ser un proceso sencillo. Aunque Ubuntu incluye una versión de Node.js en sus repositorios por defecto, es posible que quieras utilizar una versión más reciente, como Node.js 24, que es LTS desde el 28 de octubre de 2025 y tiene soporte hasta abril de 2028. Si vas a instalarlo desde cero, mejor instala Node.js 26 en Ubuntu 26.04. En esta guía te enseño dos métodos para que lo tengas listo rápidamente.","2025-10-12","6",[485,475,486,62],{"id":506,"path":507,"title":508,"description":509,"date":510,"readingTime":511,"tags":512},"blog_es\u002Fes\u002Fblog\u002F0001.hello.md","\u002Fes\u002Fblog\u002Fhello","De Svelte a Nuxt: Reconstruyendo mi portfolio en 2025","Estamos en 2025 y acabo de publicar una versión completamente nueva de mi web personal. He migrado de un stack basado en Svelte y Sapper a Nuxt, Tailwind CSS y un monorepo con Turborepo. No ha sido un cambio estético, sino una reescritura completa, fruto de cinco años de evolución en el frontend y de las ganas de usar en casa las mismas herramientas que en el trabajo.","2025-09-27","4",[513,496,514,515,229],"nuxt","svelte","turborepo",1794096651369]