in my Angular project, I recently moved a menu from a typescript variable to a dynamically loaded json from backend.
Some Tailwind classes were used only in this menu so now at build time Tailwind doesn't know that it has to include styles for those classes.
Is it possible to force Tailwind to always include some classes? For example by working on the tailwind.config.js file.
As workaround, actually I've included this row in my index.html (but i don't like the errors from eslint):
<!--<span class="hidden bg-green-400 bg-pink-400"></span>-->
As suggested by Ihar Aliakseyenka, the "safelist" section is exactly what I was looking for. Thanks Ihar!
module.exports = {
content: [
'./pages/**/*.{html,js}'
'./components/**/*.{html,js}',
],
safelist: [
'bg-red-500',
'text-3xl',
'lg:text-4xl',
]
// ...
}
Tailwind uses tree-shaking i.e any class that wasn't declared in your source files, won't be generated in the output file.
Hence use safelist classes .
In tailwind.config.js
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
{
pattern: /bg-(red|green|blue|orange)-(100|500|700)/, // You can display all the colors that you need
variants: ['lg', 'hover', 'focus', 'lg:hover'], // Optional
},
],
// ...
}
How to make it more generic to include all possible tailwind colors?
const tailwindColors = require("./node_modules/tailwindcss/colors")
const colorSafeList = []
// Skip these to avoid a load of deprecated warnings when tailwind starts up
const deprecated = ["lightBlue", "warmGray", "trueGray", "coolGray", "blueGray"]
for (const colorName in tailwindColors) {
if (deprecated.includes(colorName)) {
continue
}
// Define all of your desired shades
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]
const pallette = tailwindColors[colorName]
if (typeof pallette === "object") {
shades.forEach((shade) => {
if (shade in pallette) {
// colorSafeList.push(`text-${colorName}-${shade}`) <-- You can add different colored text as well
colorSafeList.push(`bg-${colorName}-${shade}`)
}
})
}
}
// tailwind.config.js
module.exports = {
safelist: colorSafeList, // <-- add the safelist here
content: ["{pages,app}/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: tailwindColors,
},
},
plugins: [],
}
Related
I'm working in vue/quasar application.
I've my mixin like this in my view.cshtml
var mixin1 = {
data: function () {
return { data1:0,data2:'' }
}
,
beforeCreate: async function () {
...}
},
methods: {
addformulaire(url) {
},
Kilometrique() { }
}
}
And I want merge with my content in js file (it's to centralize same action an severals cshtml)
const nomeMixins = {
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
computed: {
libmntpiece(v) { return "toto"; }
},
methods: {
findinfcomplemtX3(cdecltx3, cdedocx3) {
},
preremplissagex3: async function (cdecltx3, cdedocx3) {
}
}
}
};
I want merge this 2 miwin in one. But when I try assign or var mixin = { ...mixin1, ...nomeMixins };
I've only mixin1 nothing about methods,data from my js file nomeMixins but merging failed cause I've same key in my json object. I'm trying to make a foreach but failed too
Someone try to merge to mixin / json object with same key in the case you've no double child property ?
You cant merge mixins in that way. the spread syntax will overwrite keys e.g data, computed, methods etc and final result will not be suitable for your purpose.
refer documentation for adding mixins in your component. Also note that You can easily add multiple mixins in any component, so I don't think combination of two mixins will be any useful.
UPDATE
reply to YannickIngenierie answer and pointing out mistakes in this article
Global Mixins are not declared like this
// not global mixin; on contrary MyMixin is local
// and only available in one component.
new Vue({
el: '#demo',
mixins: [MyMixin]
});
Local Mixins are not declared like this
// NOT local mixin; on contrary its global Mixin
// and available to all components
const DataLoader = Vue.mixin({....}}
Vue.component("article-card", {
mixins: [DataLoader], // no need of this
template: "#article-card-template",
created() {
this.load("https://jsonplaceholder.typicode.com/posts/1")
}
});
Point is refer documentation first before reading any article written by some random guy, including me. Do slight comparison what he is saying whats in documentation.
After working and searching... I find this one And understand that I can add directly mixin in my compoment (don't laught I'm begging with vue few months ago)
my custommiwin.js
const DataLoader = Vue.mixin({
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
methods: {
filterClt: async function (val, update, abort) {
if (val.length < 3) { abort(); return; }
else {//recherche
this.loadingcdt = true;
let res = await axios...
this.loadingcdt = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterclient = this.lstclt.filter(v => v.libelle.toLowerCase().indexOf(needle) > -1 || v.id.toLowerCase().indexOf(needle) > -1);
})
},
filterDocument: async function (val, update, abort, cdecltx3) {
if (!cdecltx3 || val.length < 3) { abort(); return; }
else {//recherche
this.loadingdoc = true;
let res = await axios({ ...) }
this.loadingdoc = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterdoc = this.lstdoc.filter(v => v.id.toLowerCase().indexOf(needle) > -1);
})
},
}
});
and in my compoment.js I add this
mixins: [DataLoader],
I include all my js file in my cshtml file
I want to interact with multiple elements like multiple checkboxes radio buttons, buttons etc. I want to store the label/name of the elements into the json file. How can I interact with multiple elements using the name from Json file in testcafe
Take a look at the data-driven test example. It shows how to load data from a JSON file. You can use the loaded data in Selector expressions like Selector('button').withText(data.buttons[0]) to reference elements.
I don't know your particular use case, but speaking purely technically, you can easily do what you're asking:
Resources/names.json:
{
"buttons": [
"First Click",
"Second Click"
],
"checkboxes": [
"Choice1",
"Choice2"
]
}
then I can lod the file in a test file and work with the values:
import { getBaseUrl } from '../Helpers/baseUrl';
import { getEnv } from '../Helpers/env';
import Webelements from '../Objects/webelements'
const baseUrl = getBaseUrl();
const env = getEnv();
const webelements = require('../Resources/names.json');
fixture `Webelements`
.page(baseUrl);
test
('Access Webelements From Json', async t => {
webelements.buttons.forEach((button) => {
console.log(button);
});
webelements.checkboxes.forEach((checkbox) => {
console.log(checkbox)
});
});
this will print the following into the console:
First Click
Second Click
Choice1
Choice2
Another solution could be using classes:
Objects/webelements.js:
class Checkboxes {
constructor () {
this.choices = {
1: "Choice1",
2: "Choice2"
}
}
}
class Buttons {
constructor () {
this.names = ["First Click", "Second Click"]
}
}
class Webelements {
constructor () {
this.checkboxes = new Checkboxes();
this.buttons = new Buttons();
}
}
export default new Webelements();
and use it like this:
test
('Access Webelements From Classes', async t => {
Object.entries(Webelements.checkboxes.choices).forEach(([key, val]) => {
console.log(key + " - " + val);
})
Webelements.buttons.names.forEach((name) => {
console.log(name)
});
});
this will output:
1 - Choice1
2 - Choice2
First Click
Second Click
So, there're options, but the point is that some solutions are better for some situations. I have very little idea about your situation, so you have to make this decision for yourself.
Using Electron and electron-store to add files' simplified executable names and their full paths from showOpenDialog to config.json. Selecting the same file causes repeating entries in config.json. For some reason (or rather missing code), app thinks they're different paths.
function addTool() {
dialog.showOpenDialog({
title: 'Select tool executable.',
filters: [{
name: 'Tool start file',
extensions: ['exe', 'jar']
}],
properties: ['openFile']
},
(exeFromDialog) => {
var var_exeToolPath = exeFromDialog.join(); //removes square brackets
var var_toolName = path.basename(var_exeToolPath).split(/[/._-]/g)[0];
//path.basename removes path until file, split+regex takes only first part until first character (one of ._/)
const tools = appConfig.get('tools');
const newTool = [...(tools || []), {
"toolName": var_toolName,
"toolPath": var_exeToolPath
}];
appConfig.set('tools', newTool);
})
}
This is how config.json looks when you open the same file few times:
{
"winPosition": {
"x": 1497,
"y": 410,
"width": 203,
"height": 603
},
"exePOEPath": [
"C:\\Program Files (x86)\\Grinding Gear Games\\Path of Exile\\PathOfExile_x64.exe"
],
"tools": [
{
"toolName": "tool1",
"toolPath": "D:\\tool1.exe"
},
{
"toolName": "tool1",
"toolPath": "D:\\tool1.exe"
},
{
"toolName": "tool1",
"toolPath": "D:\\tool1.exe"
}
]
}
Ultimately it comes to the question How to remove duplicates from your array
This part of your code will always add the new value, it doesn't check for duplicates
const newTool = [...(tools || []), {
toolName: var_toolName,
toolPath: var_exeToolPath
}]
So it should be improved to something like the following:
newTool = newTool.filter((item, pos, self) =>
self.find(other => other.toolName === item.toolName) === item
)
I would prefer using [...new Set([newTool])] but you store Objects which are compared by reference thus duplicates cannot be eliminated by Set
The data object for Vue render functions takes HTML attributes and their arguments:
{
// Same API as `v-bind:class`
'class': {
foo: true,
bar: false
},
// Same API as `v-bind:style`
style: {
color: 'red',
fontSize: '14px'
},
...
How do you render an element that takes attributes that don't take arguments (there's probably a proper expression for this but I don't know it). An example would be:
<f7-list accordion>
<f7-list-item>
...
My attempt isn't working:
render: function (createElement){
return createElement('f7-list', {{'attrs': { 'accordion': true }},
this.tree.map(function(item){return createElement('f7-list-item', item.name)}))
How does one include these attributes?
Can you pass it as a prop and then use it? You can try like this I think. (Untested)
render(createElement) {
return createElement('f7-list', {
props: {
'attrs': {'accordion':true}
}
})
}
Or perhaps simply
render(createElement) {
return createElement('f7-list', {
attrs: {
'accordion': true
}
})
}
<div class="aAA J-KU-Jg J-KU-Jg-K9" ></div>
What is the name of this compression method being used by Gmail, and is there a grunt module for it?
This method scans each js, css, and html file, and shortens the class names and ids.
You can give grunt-class-id-minifier a go:
grunt.initConfig({
class-id-minifier: {
simple: {
options: {
jsMapFile: 'tmp/simple/map.js',
jsMapDevFile: 'tmp/simple/map.dev.js',
minifyFilter: function (k, type) {
// type.id type.className
// J_ ignored in minified html
return /^J_/.test(k) ? false : true;
},
jsMapFilter: function (k, type) {
// className ignored in js map
return !!type.id;
}
},
files: [
{
expand: true,
cwd: 'test/fixtures/simple/',
src: '*.{html,css}',
dest: 'tmp/simple/'
}
]
}
}
});
https://www.npmjs.com/package/grunt-class-id-minifier