SMELUKOV_DEV Telegram 119
Мой ПР, из поста выше, пока не посмотрели, а проблему решать как-то надо.
Начал перебирать варианты:
- заменить минификатор
- поменять csso и cssnano местами
- отключить у csso все оптимизации кроме вырезания неиспользуемых классов

Первый вариант слишком рискованный
Второй выглядит как так себе, потому что cssnano вышит в конфиг сборки, а csso просто используется в плагине, на этапе optimizeChunkAssets
Третий вариант тоже не подходит, потому что дело, как оказалось, не в csso, а в css-tree. Это css-tree убирает пробел:

const {parse, generate} = require("css-tree");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast);

console.log(source); // .foo{font:1em"Arial"}


Делает это css-tree совершенно законно и генерит валидный CSS. У css-tree нет задачи восстановить CSS из AST в первозданном виде.
Но проблему, все такие надо как-то решать, например добавить пробелы перед строками везде, где их нет. Звучит как костыль, но пока мой ПР в cssnano не вмержили - ок.

Оказалось, что генератор в css-tree можно кастомизировать. Вот так можно вставить пробелы вообще перед всеми токенами:


const {parse, generate} = require("css-tree");
const {tokenTypes} = require("css-tree/tokenizer");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast, {
decorator(handlers) {
return {
...handlers,
tokenBefore() {
this.emit(' ');
return tokenTypes.WhiteSpace;
}
}
}
});
console.log(source); // . foo { font : 1em "Arial" }


Хендлер tokenBefore используется для расстановки пробелов между токенами во время генерации из AST, потому что само AST не содержит информации о пробелах (whitespaces). Например, если парсить border: 1px solid red в AST и потом обратно в CSS, то именно tokenBefore даст понять генератору, что 1px, solid и red должны быть разделены пробелами.

Предыдущий результат - это, конечно, не то, что нам нужно, поэтому немного перепишем:


const {parse, generate} = require("css-tree");
const {tokenTypes} = require("css-tree/tokenizer");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast, {
decorator(handlers) {
return {
...handlers,
tokenBefore(prev, current, value) {
if (prev !== tokenTypes.WhiteSpace && current === tokenTypes.String) {
this.emit(' ');
return tokenTypes.WhiteSpace;
}

return handlers.tokenBefore(prev, current, value);
}
}
}
});
console.log(source); // .foo{font:1em "Arial"}


Здесь мы добавляем пробелы только перед строковыми токенами и только в тех случаях, когда перед ними еще нет пробела.

Но мы же работаем не с css-tree напрямую, а с csso. Как здесь быть?
Очень просто. Если раньше мы делали так:


const CSSO = require('csso');

const compressedCSS = CSSO.minify(input.source, {
sourceMap: false,
restructure: false,
usage: {
classes: usedClasses
}
});


То теперь будет так:


const {parse, compress, generate} = require('csso/syntax');

const ast = parse(source);
const compressedAST = compress(ast, {
restructure: false,
usage: {
classes: usedClasses
}
}).ast;
const compressedCSS = generate(compressedAST, {
sourceMap: false,
decorator(handlers) {
// ...
}
});


Вот и всё, так я обхожу баг в cssnano
👍18



tgoop.com/smelukov_dev/119
Create:
Last Update:

Мой ПР, из поста выше, пока не посмотрели, а проблему решать как-то надо.
Начал перебирать варианты:
- заменить минификатор
- поменять csso и cssnano местами
- отключить у csso все оптимизации кроме вырезания неиспользуемых классов

Первый вариант слишком рискованный
Второй выглядит как так себе, потому что cssnano вышит в конфиг сборки, а csso просто используется в плагине, на этапе optimizeChunkAssets
Третий вариант тоже не подходит, потому что дело, как оказалось, не в csso, а в css-tree. Это css-tree убирает пробел:


const {parse, generate} = require("css-tree");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast);

console.log(source); // .foo{font:1em"Arial"}


Делает это css-tree совершенно законно и генерит валидный CSS. У css-tree нет задачи восстановить CSS из AST в первозданном виде.
Но проблему, все такие надо как-то решать, например добавить пробелы перед строками везде, где их нет. Звучит как костыль, но пока мой ПР в cssnano не вмержили - ок.

Оказалось, что генератор в css-tree можно кастомизировать. Вот так можно вставить пробелы вообще перед всеми токенами:


const {parse, generate} = require("css-tree");
const {tokenTypes} = require("css-tree/tokenizer");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast, {
decorator(handlers) {
return {
...handlers,
tokenBefore() {
this.emit(' ');
return tokenTypes.WhiteSpace;
}
}
}
});
console.log(source); // . foo { font : 1em "Arial" }


Хендлер tokenBefore используется для расстановки пробелов между токенами во время генерации из AST, потому что само AST не содержит информации о пробелах (whitespaces). Например, если парсить border: 1px solid red в AST и потом обратно в CSS, то именно tokenBefore даст понять генератору, что 1px, solid и red должны быть разделены пробелами.

Предыдущий результат - это, конечно, не то, что нам нужно, поэтому немного перепишем:


const {parse, generate} = require("css-tree");
const {tokenTypes} = require("css-tree/tokenizer");

const ast = parse('.foo {font: 1em "Arial"}');
const source = generate(ast, {
decorator(handlers) {
return {
...handlers,
tokenBefore(prev, current, value) {
if (prev !== tokenTypes.WhiteSpace && current === tokenTypes.String) {
this.emit(' ');
return tokenTypes.WhiteSpace;
}

return handlers.tokenBefore(prev, current, value);
}
}
}
});
console.log(source); // .foo{font:1em "Arial"}


Здесь мы добавляем пробелы только перед строковыми токенами и только в тех случаях, когда перед ними еще нет пробела.

Но мы же работаем не с css-tree напрямую, а с csso. Как здесь быть?
Очень просто. Если раньше мы делали так:


const CSSO = require('csso');

const compressedCSS = CSSO.minify(input.source, {
sourceMap: false,
restructure: false,
usage: {
classes: usedClasses
}
});


То теперь будет так:


const {parse, compress, generate} = require('csso/syntax');

const ast = parse(source);
const compressedAST = compress(ast, {
restructure: false,
usage: {
classes: usedClasses
}
}).ast;
const compressedCSS = generate(compressedAST, {
sourceMap: false,
decorator(handlers) {
// ...
}
});


Вот и всё, так я обхожу баг в cssnano

BY Сергей Мелюков


Share with your friend now:
tgoop.com/smelukov_dev/119

View MORE
Open in Telegram


Telegram News

Date: |

Telegram offers a powerful toolset that allows businesses to create and manage channels, groups, and bots to broadcast messages, engage in conversations, and offer reliable customer support via bots. There have been several contributions to the group with members posting voice notes of screaming, yelling, groaning, and wailing in different rhythms and pitches. Calling out the “degenerate” community or the crypto obsessives that engage in high-risk trading, Co-founder of NFT renting protocol Rentable World emiliano.eth shared this group on his Twitter. He wrote: “hey degen, are you stressed? Just let it out all out. Voice only tg channel for screaming”. Telegram channels fall into two types: Telegram Channels requirements & features Public channels are public to the internet, regardless of whether or not they are subscribed. A public channel is displayed in search results and has a short address (link).
from us


Telegram Сергей Мелюков
FROM American