Skip to content
This repository has been archived by the owner on Dec 2, 2018. It is now read-only.

Fix issue https://github.com/ben-eb/perfectionist/issues/53 and add feature https://github.com/ben-eb/perfectionist/issues/21 #54

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions src/applyVerticalAlign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';
import {block as commentRegex} from 'comment-regex';
import applyTransformFeatures from './applyTransformFeatures';
import blank from './blank';
import getIndent from './getIndent';
import isSassVariable from './isSassVariable';
import longest from './longest';
import {maxAtRuleLength, maxSelectorLength, maxValueLength} from './maxSelectorLength';
import prefixedDecls from './prefixedDecls';
import space from './space';
import sameLine from './sameLine';
import walk from './walk';

const {unprefixed} = postcss.vendor;

export default function applyVerticalAlign (css, opts) {
css.walk(rule => {
const {raws, type} = rule;
if (type === 'decl') {
if (raws.value) {
rule.value = raws.value.raw.trim();
}
// Format sass variable `$size: 30em;`
if (isSassVariable(rule)) {
if (rule !== css.first) {
rule.raws.before = '\n';
}
rule.raws.between = ': ';
}

const ast = valueParser(rule.value);

walk(ast, (node, index, parent) => {
const next = parent.nodes[index + 1];
if (node.type === 'function') {
node.before = node.after = '';
}
if (node.type === 'div' && node.value === ',') {
node.before = '';
node.after = ' ';
}
if (node.type === 'space') {
node.value = ' ';
}
if (
node.type === 'word' &&
node.value === '!' &&
parent.nodes[index + 2] &&
next.type === 'space' &&
parent.nodes[index + 2].type === 'word'
) {
next.type = 'word';
next.value = '';
}
if (node.type === 'word') {
applyTransformFeatures(node, opts);
}
});

rule.value = ast.toString();

// Format `!important`
if (rule.important) {
rule.raws.important = ' !important';
}

if (raws.value) {
rule.raws.value.raw = rule.value;
}
}
let indent = getIndent(rule, opts.indentSize);
if (type === 'comment') {
let prev = rule.prev();
if (prev && prev.type === 'decl') {
if (sameLine(prev, rule)) {
rule.raws.before = ' ' + blank(rule.raws.before);
} else {
rule.raws.before = '\n' + indent + blank(rule.raws.before);
}
}
if (!prev && rule !== css.first) {
rule.raws.before = '\n' + indent + blank(rule.raws.before);
}
if (rule.parent && rule.parent.type === 'root') {
let next = rule.next();
if (next) {
next.raws.before = '\n\n';
}
if (rule !== css.first) {
rule.raws.before = '\n\n';
}
}
return;
}
rule.raws.before = indent + blank(rule.raws.before);
if (type === 'rule' || type === 'atrule') {
if (!rule.nodes) {
rule.raws.between = '';
} else {
rule.raws.between = '\n' + indent;
}
rule.raws.semicolon = true;
if (rule.nodes) {
rule.raws.after = '\n';
}
}
// visual cascade of vendor prefixed properties
if (opts.cascade && type === 'rule' && rule.nodes.length > 1) {
let props = [];
let prefixed = prefixedDecls(rule).sort(longest).filter(({prop}) => {
let base = unprefixed(prop);
if (!~props.indexOf(base)) {
return props.push(base);
}
return false;
});
prefixed.forEach(prefix => {
let base = unprefixed(prefix.prop);
let vendor = prefix.prop.replace(base, '').length;
rule.nodes.filter(({prop}) => prop && ~prop.indexOf(base)).forEach(decl => {
let thisVendor = decl.prop.replace(base, '').length;
let extraSpace = vendor - thisVendor;
if (extraSpace > 0) {
decl.raws.before = space(extraSpace) + blank(decl.raws.before);
}
});
});
}
if (raws.selector && raws.selector.raw) {
rule.selector = rule.raws.selector.raw;
}
maxSelectorLength(rule, opts);
if (type === 'atrule') {
if (rule.params) {
rule.raws.afterName = ' ';
}
maxAtRuleLength(rule, opts);
}
if (type === 'decl') {
if (!commentRegex().test(rule.raws.between)) {
rule.raws.between = ': ';
}
maxValueLength(rule, opts);
}
if (rule.parent && rule.parent.type !== 'root') {
rule.raws.before = '\n' + blank(rule.raws.before);
rule.raws.after = '\n' + indent;
}
if (rule.parent && rule !== rule.parent.first && (type === 'rule' || type === 'atrule')) {
if (type === 'atrule' && !rule.nodes) {
rule.raws.before = '\n' + indent;
return;
}
rule.raws.before = '\n\n' + indent;
}
});
css.raws.after = '\n';
}
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import postcss from 'postcss';
import applyCompact from './applyCompact';
import applyCompressed from './applyCompressed';
import applyExpanded from './applyExpanded';
import applyVerticalAlign from './applyVerticalAlign';

const perfectionist = postcss.plugin('perfectionist', opts => {
opts = {
Expand Down Expand Up @@ -32,6 +33,9 @@ const perfectionist = postcss.plugin('perfectionist', opts => {
case 'compressed':
applyCompressed(css, opts);
break;
case 'vertical-align':
applyVerticalAlign(css, opts);
break;
case 'expanded':
default:
applyExpanded(css, opts);
Expand Down
6 changes: 3 additions & 3 deletions src/maxSelectorLength.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ export function maxSelectorLength (rule, opts) {
});
}

export function maxValueLength (rule, {maxValueLength: max}) {
export function maxValueLength (rule, opts) {
if (rule.raws.value && rule.raws.value.raw) {
rule.value = rule.raws.value.raw;
}
return splitProperty(rule, 'value', {
max,
max: opts.maxValueLength,
breakEvery: true,
reindent: function (r) {
return getIndent(r).length + r.prop.length + 2;
return getIndent(r, opts.indentSize).length + r.prop.length + 2;
},
});
}