@kirigami/php-prepros 1.9.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +502 -21
- package/README.md +1988 -1817
- package/index.d.ts +62 -26
- package/index.js +1 -1
- package/package.json +59 -59
- package/src/imagebatch.php +68 -67
- package/src/libraries/aliases.inc.php +879 -879
- package/src/libraries/curl.class.php +7 -7
- package/src/libraries/ld.class.php +803 -804
- package/src/libraries/md-legacy.class.php +1257 -0
- package/src/libraries/md.class.php +51 -1249
- package/src/libraries/meta.class.php +496 -506
- package/src/libraries/{normalizer.class.php → normalizer-legacy.class.php} +11 -1
- package/src/libraries/prepros.class.php +85 -8
- package/src/libraries/schema-legacy.class.php +549 -0
- package/src/libraries/schema.class.php +99 -472
- package/src/libraries/yaml-legacy.class.php +598 -0
- package/src/libraries/yaml.class.php +41 -406
- package/src/prepros.js +152 -48
- package/src/prepros.php +4 -5
- package/src/runenv.php +2 -2
- package/src/utils.inc.php +12 -2
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* YAML —
|
|
4
|
+
* YAML — YAML parser backed by PHP's native `yaml` extension (PECL yaml /
|
|
5
|
+
* libyaml), statically built into @kirigami/php-wasm.
|
|
5
6
|
*
|
|
6
7
|
* Usage:
|
|
7
8
|
* $data = YAML::parse($yamlString); // mappings → stdClass (default)
|
|
8
9
|
* $data = YAML::parse($yamlString, true); // mappings → associative array
|
|
9
10
|
* $data = YAML::parseFile('/path/to/config.yaml');
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
12
|
+
* Follows YAML 1.1 (libyaml's resolver), including its implicit-boolean
|
|
13
|
+
* scalars: not just yes/no/true/false/on/off but also the bare single-letter
|
|
14
|
+
* y/Y/n/N — as a value *or* as a mapping key (the classic "Norway problem":
|
|
15
|
+
* an unquoted `no:` key or a `NO` value resolves to `false`). Quote such
|
|
16
|
+
* scalars (`"y": 2`) in project YAML to keep them as strings. See
|
|
17
|
+
* docs/BUGS.md for the differences found against the previous hand-written
|
|
18
|
+
* parser (now YAML_LEGACY::).
|
|
19
|
+
*
|
|
20
|
+
* `yaml.decode_php` must stay off (it is by default) so a `!php/object` tag
|
|
21
|
+
* in untrusted YAML can't trigger unserialize().
|
|
20
22
|
*/
|
|
21
23
|
class YAML
|
|
22
24
|
{
|
|
@@ -28,22 +30,25 @@ class YAML
|
|
|
28
30
|
|
|
29
31
|
public static function parse(string $yaml, bool $assoc = false): mixed
|
|
30
32
|
{
|
|
31
|
-
$
|
|
32
|
-
$
|
|
33
|
-
$pos = 0;
|
|
33
|
+
$ndocs = 0;
|
|
34
|
+
$error = null;
|
|
34
35
|
|
|
35
|
-
$
|
|
36
|
+
set_error_handler(function (int $errno, string $errstr) use (&$error) {
|
|
37
|
+
$error = $errstr;
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
$result = yaml_parse($yaml, -1, $ndocs);
|
|
41
|
+
restore_error_handler();
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
$
|
|
39
|
-
|
|
40
|
-
if (preg_match('/^\.\.\./', $line)) { $pos++; break; }
|
|
43
|
+
if ($result === false) {
|
|
44
|
+
throw new \RuntimeException($error ?? 'Failed to parse YAML.');
|
|
45
|
+
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
$
|
|
47
|
+
if ($ndocs <= 1) {
|
|
48
|
+
return self::convert($result[0] ?? null, $assoc);
|
|
44
49
|
}
|
|
45
50
|
|
|
46
|
-
return
|
|
51
|
+
return array_map(fn($doc) => self::convert($doc, $assoc), $result);
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
public static function parseFile(string $path, bool $assoc = false): mixed
|
|
@@ -186,399 +191,29 @@ class YAML
|
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
// -------------------------------------------------------------------------
|
|
189
|
-
//
|
|
190
|
-
// -------------------------------------------------------------------------
|
|
191
|
-
|
|
192
|
-
private static function parseBlock(array $lines, int &$pos, int $indent, bool $assoc = false): mixed
|
|
193
|
-
{
|
|
194
|
-
self::skipEmptyAndComments($lines, $pos);
|
|
195
|
-
|
|
196
|
-
if ($pos >= count($lines)) return null;
|
|
197
|
-
|
|
198
|
-
$line = $lines[$pos];
|
|
199
|
-
$lineIndent = self::getIndent($line);
|
|
200
|
-
$trimmed = ltrim($line);
|
|
201
|
-
|
|
202
|
-
if (str_starts_with($trimmed, '- ') || $trimmed === '-') {
|
|
203
|
-
return self::parseSequence($lines, $pos, $lineIndent, $assoc);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (self::isMapping($trimmed)) {
|
|
207
|
-
return self::parseMapping($lines, $pos, $lineIndent, $assoc);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
private static function parseMapping(array $lines, int &$pos, int $indent, bool $assoc = false): array|object
|
|
214
|
-
{
|
|
215
|
-
$result = [];
|
|
216
|
-
|
|
217
|
-
while ($pos < count($lines)) {
|
|
218
|
-
self::skipEmptyAndComments($lines, $pos);
|
|
219
|
-
if ($pos >= count($lines)) break;
|
|
220
|
-
|
|
221
|
-
$line = $lines[$pos];
|
|
222
|
-
$lineIndent = self::getIndent($line);
|
|
223
|
-
$trimmed = ltrim($line);
|
|
224
|
-
|
|
225
|
-
if ($lineIndent < $indent) break;
|
|
226
|
-
if ($lineIndent > $indent) break;
|
|
227
|
-
if (preg_match('/^(---|\.\.\.)\s*$/', $trimmed)) break;
|
|
228
|
-
if (!self::isMapping($trimmed)) break;
|
|
229
|
-
|
|
230
|
-
[$key, $rest] = self::splitKeyValue($trimmed);
|
|
231
|
-
$pos++;
|
|
232
|
-
|
|
233
|
-
if ($rest === null) {
|
|
234
|
-
// Value on the following lines: sub-block or multi-line plain scalar
|
|
235
|
-
self::skipEmptyAndComments($lines, $pos);
|
|
236
|
-
if ($pos < count($lines)) {
|
|
237
|
-
$nextIndent = self::getIndent($lines[$pos]);
|
|
238
|
-
if ($nextIndent > $indent) {
|
|
239
|
-
$nextTrimmed = ltrim($lines[$pos]);
|
|
240
|
-
// Plain scalar if it's neither a mapping nor a sequence
|
|
241
|
-
if (!self::isMapping($nextTrimmed) && !str_starts_with($nextTrimmed, '- ')) {
|
|
242
|
-
$result[$key] = self::parseScalar(
|
|
243
|
-
self::collectPlainScalar($lines, $pos, $indent, '')
|
|
244
|
-
);
|
|
245
|
-
} else {
|
|
246
|
-
$result[$key] = self::parseBlock($lines, $pos, $nextIndent, $assoc);
|
|
247
|
-
}
|
|
248
|
-
} else {
|
|
249
|
-
$result[$key] = null;
|
|
250
|
-
}
|
|
251
|
-
} else {
|
|
252
|
-
$result[$key] = null;
|
|
253
|
-
}
|
|
254
|
-
} elseif ($rest === '|' || $rest === '|-' || $rest === '|+') {
|
|
255
|
-
$result[$key] = self::parseLiteralBlock($lines, $pos, $indent, $rest);
|
|
256
|
-
} elseif ($rest === '>' || $rest === '>-' || $rest === '>+') {
|
|
257
|
-
$result[$key] = self::parseFoldedBlock($lines, $pos, $indent, $rest);
|
|
258
|
-
} elseif ($rest !== '' && ($rest[0] === '[' || $rest[0] === '{')) {
|
|
259
|
-
$result[$key] = self::parseInlineCollection($rest, $assoc);
|
|
260
|
-
} else {
|
|
261
|
-
// Inline scalar, may be followed by continuation lines
|
|
262
|
-
$result[$key] = self::parseScalar(
|
|
263
|
-
self::collectPlainScalar($lines, $pos, $indent, $rest)
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return $assoc ? $result : (object) $result;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
private static function parseSequence(array $lines, int &$pos, int $indent, bool $assoc = false): array
|
|
272
|
-
{
|
|
273
|
-
$result = [];
|
|
274
|
-
|
|
275
|
-
while ($pos < count($lines)) {
|
|
276
|
-
self::skipEmptyAndComments($lines, $pos);
|
|
277
|
-
if ($pos >= count($lines)) break;
|
|
278
|
-
|
|
279
|
-
$line = $lines[$pos];
|
|
280
|
-
$lineIndent = self::getIndent($line);
|
|
281
|
-
$trimmed = ltrim($line);
|
|
282
|
-
|
|
283
|
-
if ($lineIndent < $indent) break;
|
|
284
|
-
if ($lineIndent > $indent) break;
|
|
285
|
-
if (preg_match('/^(---|\.\.\.)\s*$/', $trimmed)) break;
|
|
286
|
-
if (!str_starts_with($trimmed, '- ') && $trimmed !== '-') break;
|
|
287
|
-
|
|
288
|
-
$itemContent = $trimmed === '-' ? '' : substr($trimmed, 2);
|
|
289
|
-
$pos++;
|
|
290
|
-
|
|
291
|
-
if ($itemContent === '') {
|
|
292
|
-
self::skipEmptyAndComments($lines, $pos);
|
|
293
|
-
if ($pos < count($lines)) {
|
|
294
|
-
$nextIndent = self::getIndent($lines[$pos]);
|
|
295
|
-
$result[] = $nextIndent > $indent
|
|
296
|
-
? self::parseBlock($lines, $pos, $nextIndent, $assoc)
|
|
297
|
-
: null;
|
|
298
|
-
} else {
|
|
299
|
-
$result[] = null;
|
|
300
|
-
}
|
|
301
|
-
} elseif (self::isMapping($itemContent)) {
|
|
302
|
-
// Inline mapping inside the sequence:
|
|
303
|
-
// Rebuild a virtual array of lines by prefixing the first key
|
|
304
|
-
// with fakeIndent, then delegate entirely to parseMapping to get
|
|
305
|
-
// all of its logic (|, >, plain scalars, sub-blocks…).
|
|
306
|
-
$fakeIndent = $lineIndent + 2;
|
|
307
|
-
$fakePrefix = str_repeat(' ', $fakeIndent);
|
|
308
|
-
$virtualLines = array_merge(
|
|
309
|
-
[$fakePrefix . $itemContent],
|
|
310
|
-
array_slice($lines, $pos)
|
|
311
|
-
);
|
|
312
|
-
$vPos = 0;
|
|
313
|
-
$itemMap = self::parseMapping($virtualLines, $vPos, $fakeIndent, $assoc);
|
|
314
|
-
$pos += max(0, $vPos - 1);
|
|
315
|
-
$result[] = $itemMap;
|
|
316
|
-
} elseif ($itemContent[0] === '[' || $itemContent[0] === '{') {
|
|
317
|
-
$result[] = self::parseInlineCollection($itemContent, $assoc);
|
|
318
|
-
} else {
|
|
319
|
-
$result[] = self::parseScalar($itemContent);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return $result;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// -------------------------------------------------------------------------
|
|
327
|
-
// Multi-line plain scalar
|
|
194
|
+
// yaml_parse() → stdClass/array shape
|
|
328
195
|
// -------------------------------------------------------------------------
|
|
329
196
|
|
|
330
197
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
198
|
+
* yaml_parse() always returns plain PHP arrays (associative for mappings,
|
|
199
|
+
* indexed for sequences). $assoc=false wants mappings as stdClass instead
|
|
200
|
+
* — this walks the tree and converts them, leaving sequences as arrays
|
|
201
|
+
* (recursing into their items).
|
|
333
202
|
*/
|
|
334
|
-
private static function
|
|
335
|
-
{
|
|
336
|
-
$parts = $first !== '' ? [trim($first)] : [];
|
|
337
|
-
|
|
338
|
-
while ($pos < count($lines)) {
|
|
339
|
-
$raw = $lines[$pos];
|
|
340
|
-
$trimmed = trim($raw);
|
|
341
|
-
|
|
342
|
-
// Blank line: end of the scalar
|
|
343
|
-
if ($trimmed === '') break;
|
|
344
|
-
|
|
345
|
-
$lineIndent = self::getIndent($raw);
|
|
346
|
-
|
|
347
|
-
// Back to the parent indentation or less: end
|
|
348
|
-
if ($lineIndent <= $parentIndent) break;
|
|
349
|
-
|
|
350
|
-
// Comment alone on the line: end
|
|
351
|
-
if (str_starts_with($trimmed, '#')) break;
|
|
352
|
-
|
|
353
|
-
// It's a mapping or a sequence: end
|
|
354
|
-
if (self::isMapping($trimmed) || str_starts_with($trimmed, '- ')) break;
|
|
355
|
-
|
|
356
|
-
$parts[] = $trimmed;
|
|
357
|
-
$pos++;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return implode(' ', $parts);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// -------------------------------------------------------------------------
|
|
364
|
-
// Multi-line blocks
|
|
365
|
-
// -------------------------------------------------------------------------
|
|
366
|
-
|
|
367
|
-
private static function parseLiteralBlock(array $lines, int &$pos, int $parentIndent, string $indicator): string
|
|
368
|
-
{
|
|
369
|
-
$blockLines = [];
|
|
370
|
-
$blockIndent = null;
|
|
371
|
-
$chomping = self::getChomping($indicator);
|
|
372
|
-
|
|
373
|
-
while ($pos < count($lines)) {
|
|
374
|
-
$raw = $lines[$pos];
|
|
375
|
-
|
|
376
|
-
if (trim($raw) === '') {
|
|
377
|
-
$blockLines[] = '';
|
|
378
|
-
$pos++;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
$lineIndent = self::getIndent($raw);
|
|
383
|
-
if ($blockIndent === null) {
|
|
384
|
-
if ($lineIndent <= $parentIndent) break;
|
|
385
|
-
$blockIndent = $lineIndent;
|
|
386
|
-
}
|
|
387
|
-
if ($lineIndent < $blockIndent) break;
|
|
388
|
-
|
|
389
|
-
$blockLines[] = substr($raw, $blockIndent);
|
|
390
|
-
$pos++;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return self::applyChomping(implode("\n", $blockLines), $chomping);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
private static function parseFoldedBlock(array $lines, int &$pos, int $parentIndent, string $indicator): string
|
|
397
|
-
{
|
|
398
|
-
$blockLines = [];
|
|
399
|
-
$blockIndent = null;
|
|
400
|
-
$chomping = self::getChomping($indicator);
|
|
401
|
-
|
|
402
|
-
while ($pos < count($lines)) {
|
|
403
|
-
$raw = $lines[$pos];
|
|
404
|
-
|
|
405
|
-
if (trim($raw) === '') {
|
|
406
|
-
$blockLines[] = '';
|
|
407
|
-
$pos++;
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
$lineIndent = self::getIndent($raw);
|
|
412
|
-
if ($blockIndent === null) {
|
|
413
|
-
if ($lineIndent <= $parentIndent) break;
|
|
414
|
-
$blockIndent = $lineIndent;
|
|
415
|
-
}
|
|
416
|
-
if ($lineIndent < $blockIndent) break;
|
|
417
|
-
|
|
418
|
-
$blockLines[] = rtrim(substr($raw, $blockIndent));
|
|
419
|
-
$pos++;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
$folded = '';
|
|
423
|
-
$count = count($blockLines);
|
|
424
|
-
for ($i = 0; $i < $count; $i++) {
|
|
425
|
-
if ($blockLines[$i] === '') {
|
|
426
|
-
$folded .= "\n";
|
|
427
|
-
} elseif ($i < $count - 1 && $blockLines[$i + 1] !== '') {
|
|
428
|
-
$folded .= $blockLines[$i] . ' ';
|
|
429
|
-
} else {
|
|
430
|
-
$folded .= $blockLines[$i];
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
return self::applyChomping(rtrim($folded, ' '), $chomping);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// -------------------------------------------------------------------------
|
|
438
|
-
// Inline collections [a, b] {k: v}
|
|
439
|
-
// -------------------------------------------------------------------------
|
|
440
|
-
|
|
441
|
-
private static function parseInlineCollection(string $raw, bool $assoc = false): mixed
|
|
442
|
-
{
|
|
443
|
-
$raw = trim($raw);
|
|
444
|
-
if ($raw[0] === '[') return self::parseInlineSequence($raw, $assoc);
|
|
445
|
-
if ($raw[0] === '{') return self::parseInlineMapping($raw, $assoc);
|
|
446
|
-
return self::parseScalar($raw);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
private static function parseInlineSequence(string $raw, bool $assoc = false): array
|
|
450
|
-
{
|
|
451
|
-
$inner = trim(substr($raw, 1, strrpos($raw, ']') - 1));
|
|
452
|
-
if ($inner === '') return [];
|
|
453
|
-
|
|
454
|
-
return array_map(
|
|
455
|
-
fn($item) => self::parseInlineCollection(trim($item), $assoc),
|
|
456
|
-
self::splitInline($inner)
|
|
457
|
-
);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
private static function parseInlineMapping(string $raw, bool $assoc = false): array|object
|
|
461
|
-
{
|
|
462
|
-
$inner = trim(substr($raw, 1, strrpos($raw, '}') - 1));
|
|
463
|
-
if ($inner === '') return $assoc ? [] : new \stdClass();
|
|
464
|
-
|
|
465
|
-
$result = [];
|
|
466
|
-
foreach (self::splitInline($inner) as $pair) {
|
|
467
|
-
$colonPos = strpos($pair, ':');
|
|
468
|
-
if ($colonPos === false) continue;
|
|
469
|
-
$k = trim(substr($pair, 0, $colonPos));
|
|
470
|
-
$v = trim(substr($pair, $colonPos + 1));
|
|
471
|
-
$result[$k] = self::parseInlineCollection($v, $assoc);
|
|
472
|
-
}
|
|
473
|
-
return $assoc ? $result : (object) $result;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
private static function splitInline(string $str): array
|
|
477
|
-
{
|
|
478
|
-
$parts = [];
|
|
479
|
-
$depth = 0;
|
|
480
|
-
$current = '';
|
|
481
|
-
$inSingle = false;
|
|
482
|
-
$inDouble = false;
|
|
483
|
-
|
|
484
|
-
for ($i = 0, $len = strlen($str); $i < $len; $i++) {
|
|
485
|
-
$c = $str[$i];
|
|
486
|
-
|
|
487
|
-
if ($c === "'" && !$inDouble) { $inSingle = !$inSingle; $current .= $c; continue; }
|
|
488
|
-
if ($c === '"' && !$inSingle) { $inDouble = !$inDouble; $current .= $c; continue; }
|
|
489
|
-
if ($inSingle || $inDouble) { $current .= $c; continue; }
|
|
490
|
-
|
|
491
|
-
if ($c === '[' || $c === '{') { $depth++; $current .= $c; continue; }
|
|
492
|
-
if ($c === ']' || $c === '}') { $depth--; $current .= $c; continue; }
|
|
493
|
-
|
|
494
|
-
if ($c === ',' && $depth === 0) { $parts[] = $current; $current = ''; continue; }
|
|
495
|
-
$current .= $c;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
if ($current !== '') $parts[] = $current;
|
|
499
|
-
return $parts;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// -------------------------------------------------------------------------
|
|
503
|
-
// Scalars
|
|
504
|
-
// -------------------------------------------------------------------------
|
|
505
|
-
|
|
506
|
-
private static function parseScalar(string $value): mixed
|
|
203
|
+
private static function convert(mixed $node, bool $assoc): mixed
|
|
507
204
|
{
|
|
508
|
-
$
|
|
509
|
-
|
|
510
|
-
if (!preg_match('/^[\'"]/', $value)) {
|
|
511
|
-
$value = rtrim(preg_replace('/(^|\s)#.*$/', '', $value));
|
|
205
|
+
if ($assoc || !is_array($node)) {
|
|
206
|
+
return $node;
|
|
512
207
|
}
|
|
513
208
|
|
|
514
|
-
if ($
|
|
515
|
-
|
|
516
|
-
if (str_starts_with($value, '"') && str_ends_with($value, '"') && strlen($value) >= 2) {
|
|
517
|
-
return stripcslashes(substr($value, 1, -1));
|
|
209
|
+
if (array_is_list($node)) {
|
|
210
|
+
return array_map(fn($v) => self::convert($v, $assoc), $node);
|
|
518
211
|
}
|
|
519
212
|
|
|
520
|
-
|
|
521
|
-
|
|
213
|
+
$obj = new \stdClass();
|
|
214
|
+
foreach ($node as $key => $value) {
|
|
215
|
+
$obj->$key = self::convert($value, $assoc);
|
|
522
216
|
}
|
|
523
|
-
|
|
524
|
-
if (in_array(strtolower($value), ['~', 'null'], true)) return null;
|
|
525
|
-
if (in_array(strtolower($value), ['true', 'yes', 'on'], true)) return true;
|
|
526
|
-
if (in_array(strtolower($value), ['false', 'no', 'off'], true)) return false;
|
|
527
|
-
if (preg_match('/^-?\d+$/', $value)) return (int) $value;
|
|
528
|
-
if (preg_match('/^-?\d+\.\d*([eE][+-]?\d+)?$/', $value)) return (float) $value;
|
|
529
|
-
if (in_array(strtolower($value), ['.inf', '+.inf'], true)) return INF;
|
|
530
|
-
if (strtolower($value) === '-.inf') return -INF;
|
|
531
|
-
if (strtolower($value) === '.nan') return NAN;
|
|
532
|
-
|
|
533
|
-
return $value;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// -------------------------------------------------------------------------
|
|
537
|
-
// Helpers
|
|
538
|
-
// -------------------------------------------------------------------------
|
|
539
|
-
|
|
540
|
-
private static function getIndent(string $line): int
|
|
541
|
-
{
|
|
542
|
-
return strlen($line) - strlen(ltrim($line));
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
private static function isMapping(string $trimmed): bool
|
|
546
|
-
{
|
|
547
|
-
return (bool) preg_match('/^(?:"[^"]*"|\'[^\']*\'|[^:\'"\[\{]+):\s?/', $trimmed);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
private static function splitKeyValue(string $line): array
|
|
551
|
-
{
|
|
552
|
-
if (preg_match('/^("(?:[^"\\\\]|\\\\.)*"|\'(?:[^\']|\'\')*\'|[^:]+?):\s*(.*)$/', $line, $m)) {
|
|
553
|
-
$key = self::parseScalar($m[1]);
|
|
554
|
-
$val = trim($m[2]) !== '' ? trim($m[2]) : null;
|
|
555
|
-
return [$key, $val];
|
|
556
|
-
}
|
|
557
|
-
return [$line, null];
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
private static function skipEmptyAndComments(array $lines, int &$pos): void
|
|
561
|
-
{
|
|
562
|
-
while ($pos < count($lines)) {
|
|
563
|
-
$t = trim($lines[$pos]);
|
|
564
|
-
if ($t === '' || str_starts_with($t, '#')) $pos++;
|
|
565
|
-
else break;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
private static function getChomping(string $indicator): string
|
|
570
|
-
{
|
|
571
|
-
if (str_ends_with($indicator, '-')) return 'strip';
|
|
572
|
-
if (str_ends_with($indicator, '+')) return 'keep';
|
|
573
|
-
return 'clip';
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
private static function applyChomping(string $text, string $chomping): string
|
|
577
|
-
{
|
|
578
|
-
return match ($chomping) {
|
|
579
|
-
'strip' => rtrim($text, "\n"),
|
|
580
|
-
'keep' => $text,
|
|
581
|
-
default => rtrim($text, "\n") . "\n",
|
|
582
|
-
};
|
|
217
|
+
return $obj;
|
|
583
218
|
}
|
|
584
|
-
}
|
|
219
|
+
}
|