Skip to content

Commit 4852197

Browse files
authored
fix: OS-agnostic handling of end-of-line characters (#524)
* fix: OS-agnostic handling of end-of-line characters * try stubbing EOL in test
1 parent 01c3179 commit 4852197

File tree

10 files changed

+39
-18
lines changed

10 files changed

+39
-18
lines changed

jest.config.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const jestConfig = {
66
preset: 'ts-jest/presets/default-esm',
77
testEnvironment: 'node',
88
testMatch: ['<rootDir>/test/**/*-test.ts'],
9+
setupFiles: ['<rootDir>/test/jest.setup.cjs'],
910
transform: {
1011
'^.+\\.tsx?$': ['ts-jest', { useESM: true }],
1112
},

lib/config-list.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import {
23
BEGIN_CONFIG_LIST_MARKER,
34
END_CONFIG_LIST_MARKER,
@@ -111,5 +112,5 @@ export function updateConfigsList(
111112
ignoreConfig
112113
);
113114

114-
return `${preList}${BEGIN_CONFIG_LIST_MARKER}\n\n${list}\n\n${END_CONFIG_LIST_MARKER}${postList}`;
115+
return `${preList}${BEGIN_CONFIG_LIST_MARKER}${EOL}${EOL}${list}${EOL}${EOL}${END_CONFIG_LIST_MARKER}${postList}`;
115116
}

lib/generator.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
23
import { dirname, join, relative, resolve } from 'node:path';
34
import { getAllNamedOptions, hasOptions } from './rule-options.js';
@@ -168,16 +169,18 @@ export async function generate(path: string, options?: GenerateOptions) {
168169
// The rule doc header will be added later.
169170
let newRuleDocContents = [
170171
ruleDocSectionInclude.length > 0
171-
? ruleDocSectionInclude.map((title) => `## ${title}`).join('\n\n')
172+
? ruleDocSectionInclude
173+
.map((title) => `## ${title}`)
174+
.join(`${EOL}${EOL}`)
172175
: undefined,
173176
ruleHasOptions
174-
? `## Options\n\n${BEGIN_RULE_OPTIONS_LIST_MARKER}\n${END_RULE_OPTIONS_LIST_MARKER}`
177+
? `## Options${EOL}${EOL}${BEGIN_RULE_OPTIONS_LIST_MARKER}${EOL}${END_RULE_OPTIONS_LIST_MARKER}`
175178
: undefined,
176179
]
177180
.filter((section) => section !== undefined)
178-
.join('\n\n');
181+
.join(`${EOL}${EOL}`);
179182
if (newRuleDocContents !== '') {
180-
newRuleDocContents = `\n${newRuleDocContents}\n`;
183+
newRuleDocContents = `${EOL}${newRuleDocContents}${EOL}`;
181184
}
182185

183186
mkdirSync(dirname(pathToDoc), { recursive: true });

lib/markdown.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { EOL } from 'node:os';
2+
13
// General helpers for dealing with markdown files / content.
24

35
/**
@@ -12,7 +14,7 @@ export function replaceOrCreateHeader(
1214
newHeader: string,
1315
marker: string
1416
) {
15-
const lines = markdown.split('\n');
17+
const lines = markdown.split(EOL);
1618

1719
const titleLineIndex = lines.findIndex((line) => line.startsWith('# '));
1820
const markerLineIndex = lines.indexOf(marker);
@@ -22,16 +24,18 @@ export function replaceOrCreateHeader(
2224
// Any YAML front matter or anything else above the title should be kept as-is ahead of the new header.
2325
const preHeader = lines
2426
.slice(0, Math.max(titleLineIndex, dashesLineIndex2 + 1))
25-
.join('\n');
27+
.join(EOL);
2628

2729
// Anything after the marker comment, title, or YAML front matter should be kept as-is after the new header.
2830
const postHeader = lines
2931
.slice(
3032
Math.max(markerLineIndex + 1, titleLineIndex + 1, dashesLineIndex2 + 1)
3133
)
32-
.join('\n');
34+
.join(EOL);
3335

34-
return `${preHeader ? `${preHeader}\n` : ''}${newHeader}\n${postHeader}`;
36+
return `${
37+
preHeader ? `${preHeader}${EOL}` : ''
38+
}${newHeader}${EOL}${postHeader}`;
3539
}
3640

3741
/**
@@ -42,7 +46,7 @@ export function findSectionHeader(
4246
str: string
4347
): string | undefined {
4448
// Get all the matching strings.
45-
const regexp = new RegExp(`## .*${str}.*\n`, 'giu');
49+
const regexp = new RegExp(`## .*${str}.*${EOL}`, 'giu');
4650
const sectionPotentialMatches = [...markdown.matchAll(regexp)].map(
4751
(match) => match[0]
4852
);
@@ -64,7 +68,7 @@ export function findSectionHeader(
6468
}
6569

6670
export function findFinalHeaderLevel(str: string) {
67-
const lines = str.split('\n');
71+
const lines = str.split(EOL);
6872
const finalHeader = lines.reverse().find((line) => line.match('^(#+) .+$'));
6973
return finalHeader ? finalHeader.indexOf(' ') : undefined;
7074
}

lib/rule-doc-notices.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import { END_RULE_HEADER_MARKER } from './comment-markers.js';
23
import {
34
EMOJI_DEPRECATED,
@@ -523,5 +524,5 @@ export function generateRuleHeaderLines(
523524
),
524525
'',
525526
END_RULE_HEADER_MARKER,
526-
].join('\n');
527+
].join(EOL);
527528
}

lib/rule-list-legend.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import {
23
EMOJI_DEPRECATED,
34
EMOJI_FIXABLE,
@@ -287,5 +288,5 @@ export function generateLegend(
287288
);
288289
}
289290

290-
return legends.join('\\\n'); // Back slash ensures these end up displayed on separate lines.
291+
return legends.join(`\\${EOL}`); // Back slash ensures these end up displayed on separate lines.
291292
}

lib/rule-list.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import {
23
BEGIN_RULE_LIST_MARKER,
34
END_RULE_LIST_MARKER,
@@ -288,7 +289,7 @@ function generateRuleListMarkdownForRulesAndHeaders(
288289
);
289290
}
290291

291-
return parts.join('\n\n');
292+
return parts.join(`${EOL}${EOL}`);
292293
}
293294

294295
/**
@@ -546,7 +547,7 @@ export function updateRulesList(
546547
urlRuleDoc
547548
);
548549

549-
const newContent = `${legend ? `${legend}\n\n` : ''}${list}`;
550+
const newContent = `${legend ? `${legend}${EOL}${EOL}` : ''}${list}`;
550551

551-
return `${preList}${BEGIN_RULE_LIST_MARKER}\n\n${newContent}\n\n${END_RULE_LIST_MARKER}${postList}`;
552+
return `${preList}${BEGIN_RULE_LIST_MARKER}${EOL}${EOL}${newContent}${EOL}${EOL}${END_RULE_LIST_MARKER}${postList}`;
552553
}

lib/rule-options-list.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EOL } from 'node:os';
12
import {
23
BEGIN_RULE_OPTIONS_LIST_MARKER,
34
END_RULE_OPTIONS_LIST_MARKER,
@@ -159,5 +160,5 @@ export function updateRuleOptionsList(
159160
// New rule options list.
160161
const list = generateRuleOptionsListMarkdown(rule);
161162

162-
return `${preList}${BEGIN_RULE_OPTIONS_LIST_MARKER}\n\n${list}\n\n${END_RULE_OPTIONS_LIST_MARKER}${postList}`;
163+
return `${preList}${BEGIN_RULE_OPTIONS_LIST_MARKER}${EOL}${EOL}${list}${EOL}${EOL}${END_RULE_OPTIONS_LIST_MARKER}${postList}`;
163164
}

lib/string.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { EOL } from 'node:os';
2+
13
export function toSentenceCase(str: string) {
24
return str.replace(/^\w/u, function (txt) {
35
return txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase();
@@ -20,7 +22,7 @@ export function capitalizeOnlyFirstLetter(str: string) {
2022
}
2123

2224
function sanitizeMarkdownTableCell(text: string): string {
23-
return text.replace(/\|/gu, '\\|').replace(/\n/gu, '<br/>');
25+
return text.replace(/\|/gu, '\\|').replace(new RegExp(EOL, 'gu'), '<br/>');
2426
}
2527

2628
export function sanitizeMarkdownTable(

test/jest.setup.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const os = require('node:os');
2+
const sinon = require('sinon');
3+
4+
module.exports = function () {
5+
sinon.stub(os, 'EOL').value('\n'); // Stub os.EOL to always be '\n' for testing/snapshot purposes.
6+
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy