Skip to content

Commit 9502955

Browse files
authored
Merge pull request #1347 from hydephp/refactor-internal-scripts
Refactor internal Markdown formatter script
2 parents e2cdb6b + c0a8a45 commit 9502955

File tree

1 file changed

+137
-86
lines changed

1 file changed

+137
-86
lines changed

monorepo/scripts/docs/MarkdownFormatter.php

Lines changed: 137 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,127 @@
1313
$timeStart = microtime(true);
1414

1515
$filesChanged = 0;
16-
1716
$linesCounted = 0;
18-
1917
$links = [];
20-
2118
$warnings = [];
2219

2320
// Buffer headings so we can check for style
2421
$headings = []; // [filename => [line => heading]]
2522
$checksHeadings = false;
2623

27-
function find_markdown_files($dir): array
24+
class MarkdownFormatter
2825
{
29-
$markdown_files = [];
26+
protected string $input;
27+
protected string $output;
28+
protected string $filename;
3029

31-
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
32-
foreach ($iterator as $file) {
33-
// Skip _data directory
34-
if (str_contains($file->getPathname(), '_data')) {
35-
continue;
30+
public function __construct(string $input, string $filename = 'Input')
31+
{
32+
$this->input = $input;
33+
$this->filename = $filename;
34+
35+
$this->run();
36+
}
37+
38+
protected function run(): void
39+
{
40+
$stream = $this->input;
41+
$filename = $this->filename;
42+
43+
$text = $stream;
44+
$text = str_replace("\r\n", "\n", $text);
45+
$text = str_replace("\t", ' ', $text);
46+
47+
if (empty(trim($text))) {
48+
// Warn
49+
global $warnings;
50+
$warnings[] = "File $filename is empty";
51+
52+
return;
3653
}
3754

38-
if ($file->isFile() && strtolower($file->getExtension()) == 'md') {
39-
$markdown_files[] = realpath($file->getPathname());
55+
$lines = explode("\n", $text);
56+
$new_lines = [];
57+
58+
$last_line = '';
59+
$was_last_line_heading = false;
60+
$is_inside_fenced_code_block = false;
61+
$is_inside_fenced_fenced_code_block = false;
62+
$firstHeadingLevel = null;
63+
foreach ($lines as $index => $line) {
64+
global $linesCounted;
65+
$linesCounted++;
66+
67+
/** Normalization */
68+
69+
// Remove multiple empty lines
70+
if (trim($line) == '' && trim($last_line) == '') {
71+
continue;
72+
}
73+
74+
// Make sure there is a space after headings
75+
if ($was_last_line_heading && trim($line) != '') {
76+
$new_lines[] = '';
77+
}
78+
79+
// Make sure there are two empty lines before level 2 headings (but not if it's the first l2 heading)
80+
if ($is_inside_fenced_code_block !== true && str_starts_with($line, '## ') && $index > $firstHeadingLevel + 3) {
81+
$new_lines[] = '';
82+
}
83+
84+
if ($firstHeadingLevel === null && str_starts_with($line, '# ')) {
85+
$firstHeadingLevel = $index;
86+
}
87+
88+
// Check if line is a heading
89+
if (str_starts_with($line, '##')) {
90+
$was_last_line_heading = true;
91+
global $headings;
92+
$headings[$filename][$index + 1] = $line;
93+
} else {
94+
$was_last_line_heading = false;
95+
}
96+
97+
// Make sure there is a space before opening a fenced code block (search for ```language)
98+
if (str_starts_with($line, '```') && $line !== '```' && trim($last_line) != '') {
99+
if (! $is_inside_fenced_fenced_code_block) {
100+
$new_lines[] = '';
101+
}
102+
}
103+
104+
// Check if line is a fenced code block
105+
if (str_starts_with($line, '``')) {
106+
$is_inside_fenced_code_block = ! $is_inside_fenced_code_block;
107+
}
108+
109+
// Check if line is an escaped fenced code block
110+
if (str_starts_with($line, '````')) {
111+
$is_inside_fenced_fenced_code_block = ! $is_inside_fenced_fenced_code_block;
112+
}
113+
114+
// Remove trailing spaces
115+
$line = rtrim($line);
116+
117+
$new_lines[] = $line;
118+
$last_line = $line;
40119
}
41-
}
42120

43-
return $markdown_files;
44-
}
121+
$new_content = implode("\n", $new_lines);
122+
$new_content = trim($new_content)."\n";
45123

46-
function handle_file(string $file): void
47-
{
48-
echo 'Handling '.$file."\n";
124+
$this->output = $new_content;
125+
}
49126

50-
normalize_lines($file);
127+
public function getOutput(): string
128+
{
129+
return $this->output;
130+
}
51131
}
52132

53-
function normalize_lines($filename): void
133+
function lint(string $filename): void
54134
{
55-
$stream = file_get_contents($filename);
56-
57-
$text = $stream;
58-
$text = str_replace("\r\n", "\n", $text);
59-
$text = str_replace("\t", ' ', $text);
135+
/** Linting */
136+
$text = file_get_contents($filename);
60137

61138
if (empty(trim($text))) {
62139
// Warn
@@ -67,72 +144,13 @@ function normalize_lines($filename): void
67144
}
68145

69146
$lines = explode("\n", $text);
70-
$new_lines = [];
71-
72-
$last_line = '';
73-
$was_last_line_heading = false;
74147
$is_inside_fenced_code_block = false;
75-
$is_inside_fenced_fenced_code_block = false;
76-
$firstHeadingLevel = null;
77148
foreach ($lines as $index => $line) {
78-
global $linesCounted;
79-
$linesCounted++;
80-
81-
/** Normalization */
82-
83-
// Remove multiple empty lines
84-
if (trim($line) == '' && trim($last_line) == '') {
85-
continue;
86-
}
87-
88-
// Make sure there is a space after headings
89-
if ($was_last_line_heading && trim($line) != '') {
90-
$new_lines[] = '';
91-
}
92-
93-
// Make sure there are two empty lines before level 2 headings (but not if it's the first l2 heading)
94-
if ($is_inside_fenced_code_block !== true && str_starts_with($line, '## ') && $index > $firstHeadingLevel + 3) {
95-
$new_lines[] = '';
96-
}
97-
98-
if ($firstHeadingLevel === null && str_starts_with($line, '# ')) {
99-
$firstHeadingLevel = $index;
100-
}
101-
102-
// Check if line is a heading
103-
if (str_starts_with($line, '##')) {
104-
$was_last_line_heading = true;
105-
global $headings;
106-
$headings[$filename][$index + 1] = $line;
107-
} else {
108-
$was_last_line_heading = false;
109-
}
110-
111-
// Make sure there is a space before opening a fenced code block (search for ```language)
112-
if (str_starts_with($line, '```') && $line !== '```' && trim($last_line) != '') {
113-
if (! $is_inside_fenced_fenced_code_block) {
114-
$new_lines[] = '';
115-
}
116-
}
117-
118149
// Check if line is a fenced code block
119150
if (str_starts_with($line, '``')) {
120151
$is_inside_fenced_code_block = ! $is_inside_fenced_code_block;
121152
}
122153

123-
// Check if line is an escaped fenced code block
124-
if (str_starts_with($line, '````')) {
125-
$is_inside_fenced_fenced_code_block = ! $is_inside_fenced_fenced_code_block;
126-
}
127-
128-
// Remove trailing spaces
129-
$line = rtrim($line);
130-
131-
$new_lines[] = $line;
132-
$last_line = $line;
133-
134-
/** Linting */
135-
136154
// if not inside fenced code block
137155
if (! $is_inside_fenced_code_block) {
138156
// Add any links to buffer, so we can check them later
@@ -267,9 +285,42 @@ function normalize_lines($filename): void
267285
}
268286
}
269287
}
288+
}
289+
290+
function find_markdown_files($dir): array
291+
{
292+
$markdown_files = [];
293+
294+
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
295+
foreach ($iterator as $file) {
296+
// Skip _data directory
297+
if (str_contains($file->getPathname(), '_data')) {
298+
continue;
299+
}
300+
301+
if ($file->isFile() && strtolower($file->getExtension()) == 'md') {
302+
$markdown_files[] = realpath($file->getPathname());
303+
}
304+
}
305+
306+
return $markdown_files;
307+
}
308+
309+
function handle_file(string $file): void
310+
{
311+
echo 'Handling '.$file."\n";
312+
313+
normalize_lines($file);
314+
lint($file);
315+
}
316+
317+
function normalize_lines($filename): void
318+
{
319+
$stream = file_get_contents($filename);
320+
321+
$formatter = new MarkdownFormatter($stream, $filename);
322+
$new_content = $formatter->getOutput();
270323

271-
$new_content = implode("\n", $new_lines);
272-
$new_content = trim($new_content)."\n";
273324
file_put_contents($filename, $new_content);
274325

275326
if ($new_content !== $stream) {

0 commit comments

Comments
 (0)