1 | 'use strict';
|
2 |
|
3 | const _ = require('lodash');
|
4 | const postcss = require('postcss');
|
5 | const report = require('../../utils/report');
|
6 | const ruleMessages = require('../../utils/ruleMessages');
|
7 | const validateOptions = require('../../utils/validateOptions');
|
8 |
|
9 | const ruleName = 'linebreaks';
|
10 |
|
11 | const messages = ruleMessages(ruleName, {
|
12 | expected: (linebreak) => `Expected linebreak to be ${linebreak}`,
|
13 | });
|
14 |
|
15 | function rule(actual, secondary, context) {
|
16 | return (root, result) => {
|
17 | const validOptions = validateOptions(result, ruleName, {
|
18 | actual,
|
19 | possible: ['unix', 'windows'],
|
20 | });
|
21 |
|
22 | if (!validOptions) {
|
23 | return;
|
24 | }
|
25 |
|
26 | const shouldHaveCR = actual === 'windows';
|
27 |
|
28 | if (context.fix) {
|
29 | const propertiesToUpdate = ['selector', 'raws.before', 'raws.after', 'value', 'text'];
|
30 |
|
31 | root.walk((node) => {
|
32 | propertiesToUpdate.forEach((property) => {
|
33 | const fixedData = fixData(_.get(node, property), shouldHaveCR);
|
34 |
|
35 | _.set(node, property, fixedData);
|
36 | });
|
37 | });
|
38 |
|
39 | root.raws.after = fixData(root.raws.after, shouldHaveCR);
|
40 | } else {
|
41 | const lines = root.source.input.css.split('\n');
|
42 |
|
43 | for (let i = 0; i < lines.length; i++) {
|
44 | let line = lines[i];
|
45 |
|
46 | if (i < lines.length - 1 && !line.includes('\r')) {
|
47 | line += '\n';
|
48 | }
|
49 |
|
50 | if (hasError(line, shouldHaveCR)) {
|
51 | const lineNum = i + 1;
|
52 | const colNum = line.length;
|
53 |
|
54 | reportNewlineError(shouldHaveCR, lineNum, colNum, actual, result);
|
55 | }
|
56 | }
|
57 | }
|
58 |
|
59 | function hasError(dataToCheck, shouldHaveCR) {
|
60 | const hasNewlineToVerify = /[\r\n]/.test(dataToCheck);
|
61 | const hasCR = hasNewlineToVerify ? /\r/.test(dataToCheck) : false;
|
62 |
|
63 | return hasNewlineToVerify && hasCR !== shouldHaveCR;
|
64 | }
|
65 |
|
66 | function fixData(data, shouldHaveCR) {
|
67 | if (data) {
|
68 | let result = data.replace(/\r/g, '');
|
69 |
|
70 | if (shouldHaveCR) {
|
71 | result = result.replace(/\n/g, '\r\n');
|
72 | }
|
73 |
|
74 | return result;
|
75 | }
|
76 |
|
77 | return data;
|
78 | }
|
79 |
|
80 | function createReportNode(line, column) {
|
81 |
|
82 | return postcss.rule({
|
83 | source: {
|
84 | start: {
|
85 | line,
|
86 | column,
|
87 | },
|
88 | },
|
89 | });
|
90 | }
|
91 |
|
92 | function reportNewlineError(shouldHaveCR, lineNum, colNum, actual, result) {
|
93 | const reportNode = createReportNode(lineNum, colNum);
|
94 |
|
95 | report({
|
96 | message: messages.expected(actual),
|
97 | node: reportNode,
|
98 | result,
|
99 | ruleName,
|
100 | });
|
101 | }
|
102 | };
|
103 | }
|
104 |
|
105 | rule.ruleName = ruleName;
|
106 | rule.messages = messages;
|
107 | module.exports = rule;
|