andromeda_cms 0.6.3 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/lib/andromeda/frontmatter.rb +60 -20
- data/lib/andromeda/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df0dda6ff30ba8c1244c31c1af9951993028e7056ae943b4cca5513c14c499d2
|
|
4
|
+
data.tar.gz: 76f8e9c8de6a02d0ca9c8d22e40946c5e3bfb5961fa6888781add1d0a7e3195a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eac17b62179d28bb3ce45a772d0a9a2a630098c841d8468436d4a9b3239c9fb83d8f841252ffe42500a420cc11679e75d0bb3b0333a72ef535147bdd0021df60
|
|
7
|
+
data.tar.gz: 3dfae8e7efde1146d5b8881c8654acc4b527d1dc65b661259a658fa82ef3aef5cffc59be30e483f53fc7e3e892e37071e68cf46a95905e530aa1e6af85cb3a47
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.0] - 2026-10-16
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- YAML frontmatter is now read the way Astro 7.3.6 and later read it. Astro
|
|
13
|
+
replaced js-yaml with the `yaml` package (core schema, timestamps, merge
|
|
14
|
+
keys), and Andromeda follows. Plain scalars that only YAML 1.1 or Psych
|
|
15
|
+
treat as numbers are now strings, as they are in Astro: values with
|
|
16
|
+
underscores (`1_000`, `0x1_F`), the `0b` prefix, and signed hexadecimal
|
|
17
|
+
or octal (`-0x1F`). Numbers in the core schema are unchanged, including
|
|
18
|
+
`010` (10), `0o17`, `0x1F` and `1e3`.
|
|
19
|
+
- A mapping that repeats a key now raises `Andromeda::SyntaxError` at the
|
|
20
|
+
second key, with its line and column, as Astro does. It used to keep the
|
|
21
|
+
last value silently. Keys are compared after resolution, so `1` and `01`
|
|
22
|
+
collide while `1` and `"1"` do not; repeated `<<` merge keys are allowed.
|
|
23
|
+
Content that repeats a key will fail to build until the duplicate is
|
|
24
|
+
removed.
|
|
25
|
+
|
|
8
26
|
## [0.6.3] - 2026-10-16
|
|
9
27
|
|
|
10
28
|
### Fixed
|
|
@@ -208,6 +226,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
208
226
|
- Generators: `andromeda:install`, `andromeda:collection`,
|
|
209
227
|
`andromeda:component` and `andromeda:import_astro`.
|
|
210
228
|
|
|
229
|
+
[0.7.0]: https://github.com/AndromedaCMS/andromeda_cms/releases/tag/v0.7.0
|
|
211
230
|
[0.6.3]: https://github.com/AndromedaCMS/andromeda_cms/releases/tag/v0.6.3
|
|
212
231
|
[0.6.2]: https://github.com/AndromedaCMS/andromeda_cms/releases/tag/v0.6.2
|
|
213
232
|
[0.6.1]: https://github.com/AndromedaCMS/andromeda_cms/releases/tag/v0.6.1
|
|
@@ -25,45 +25,53 @@ module Andromeda
|
|
|
25
25
|
# a non-blank line is seen, no `---`/`+++` after it is a fence.
|
|
26
26
|
LEADING_RE = /\A\uFEFF?(?:[ \t]*\r?\n)*/
|
|
27
27
|
|
|
28
|
-
# Psych resolves plain scalars by YAML 1.1 rules;
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
28
|
+
# Psych resolves plain scalars by YAML 1.1 rules; Astro 7.3.6 and later
|
|
29
|
+
# read frontmatter with the `yaml` package (core schema, `timestamp` tag,
|
|
30
|
+
# merge keys), which follows YAML 1.2's core schema. The two disagree on
|
|
31
|
+
# values that really do appear in hand-written frontmatter, and a silent
|
|
32
|
+
# disagreement is worse than an error: `time: 12:30` becoming the integer
|
|
33
|
+
# 45000 passes every schema check and then displays nonsense. Each rule
|
|
34
|
+
# below mirrors what that parser does with the same plain scalar.
|
|
34
35
|
class ScalarScanner < Psych::ScalarScanner
|
|
35
36
|
# 1.1-only booleans; 1.2 keeps them as strings.
|
|
36
37
|
YAML_1_1_ONLY_BOOL = /\A(?:[Yy]es|YES|[Nn]o|NO|[Oo]n|ON|[Oo]ff|OFF|[Yy]|[Nn])\z/
|
|
37
38
|
# 1.1 base-60 (`1:30`) and comma-grouped (`1,000`) numbers; 1.2 has
|
|
38
39
|
# neither, so these stay strings.
|
|
39
40
|
YAML_1_1_ONLY_NUMBER = /\A[-+]?[0-9][0-9_]*(?:(?::[0-5]?[0-9])+|(?:,[0-9_]+)+)(?:\.[0-9_]*)?\z/
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
OCTAL = /\
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
# The core schema's integers. A leading zero is plain decimal (`010` is
|
|
42
|
+
# 10, where 1.1 reads octal); `0o` octal and `0x` hex take no sign.
|
|
43
|
+
INTEGER = /\A[-+]?[0-9]+\z/
|
|
44
|
+
OCTAL = /\A0o[0-7]+\z/
|
|
45
|
+
HEX = /\A0x[0-9a-fA-F]+\z/
|
|
46
|
+
# The core schema's floats, including an exponent without a decimal
|
|
47
|
+
# point (`1e3`), which Psych rejects. `.inf`/`.nan` are left to Psych.
|
|
48
|
+
FLOAT = /\A[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)(?:[eE][-+]?[0-9]+)?\z/
|
|
49
|
+
# Number-like spellings Psych accepts but the core schema does not
|
|
50
|
+
# (`1_000`, `0b1010`, `-0x1F`, `0o1_7`); they stay strings.
|
|
51
|
+
NON_CORE_NUMBER = /\A[-+]?(?:0[xXbBoO][0-9a-fA-F_]+|(?:[0-9][0-9_]*(?:\.[0-9_]*)?|\.[0-9_]+)(?:[eE][-+]?[0-9_]+)?)\z/
|
|
46
52
|
|
|
47
53
|
def tokenize(string)
|
|
48
54
|
case string
|
|
49
55
|
when YAML_1_1_ONLY_BOOL, YAML_1_1_ONLY_NUMBER then string
|
|
50
|
-
when
|
|
51
|
-
when OCTAL then Integer(string
|
|
52
|
-
when
|
|
56
|
+
when INTEGER then Integer(string, 10)
|
|
57
|
+
when OCTAL then Integer(string[2..], 8)
|
|
58
|
+
when HEX then Integer(string, 16)
|
|
59
|
+
when FLOAT then Float(normalize_float(string))
|
|
60
|
+
when NON_CORE_NUMBER then string
|
|
53
61
|
else super
|
|
54
62
|
end
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
private
|
|
58
66
|
|
|
59
|
-
# Ruby's Float() rejects the `1.e3` and `.5e3` spellings YAML allows.
|
|
67
|
+
# Ruby's Float() rejects the `1.`, `1.e3` and `.5e3` spellings YAML allows.
|
|
60
68
|
def normalize_float(string)
|
|
61
|
-
string.sub(/\.(?=[eE])/, ".0").sub(/\A([-+]?)\./, "\\10.")
|
|
69
|
+
string.sub(/\.(?=[eE]|\z)/, ".0").sub(/\A([-+]?)\./, "\\10.")
|
|
62
70
|
end
|
|
63
71
|
end
|
|
64
72
|
|
|
65
|
-
# Restricts `!!` tags to Date/Time (matching
|
|
66
|
-
# which also has no notion of arbitrary Ruby classes) while still
|
|
73
|
+
# Restricts `!!` tags to Date/Time (matching the `yaml` package's core
|
|
74
|
+
# schema, which also has no notion of arbitrary Ruby classes) while still
|
|
67
75
|
# permitting the two classes plain `YYYY-MM-DD`/timestamp scalars resolve
|
|
68
76
|
# to, so unquoted dates round-trip instead of raising
|
|
69
77
|
# Psych::DisallowedClass.
|
|
@@ -76,7 +84,7 @@ module Andromeda
|
|
|
76
84
|
end
|
|
77
85
|
|
|
78
86
|
# Plain (non-"safe") visitor so anchors/aliases resolve instead of
|
|
79
|
-
# raising --
|
|
87
|
+
# raising -- the `yaml` package resolves them by default, and copied Astro content may
|
|
80
88
|
# rely on them.
|
|
81
89
|
class ToRuby < Psych::Visitors::ToRuby
|
|
82
90
|
def initialize
|
|
@@ -199,6 +207,8 @@ module Andromeda
|
|
|
199
207
|
return {} if node.nil?
|
|
200
208
|
|
|
201
209
|
reject_alias_explosion!(node, path: path, content_start_line: content_start_line)
|
|
210
|
+
reject_duplicate_keys!(node, ScalarScanner.new(ClassLoader.new), path: path,
|
|
211
|
+
content_start_line: content_start_line)
|
|
202
212
|
ToRuby.new.accept(node) || {}
|
|
203
213
|
rescue Psych::SyntaxError => e
|
|
204
214
|
# Psych's own #line/#column are 0-based and relative to `text` (the
|
|
@@ -305,6 +315,36 @@ module Andromeda
|
|
|
305
315
|
end
|
|
306
316
|
private_class_method :expanded_size
|
|
307
317
|
|
|
318
|
+
# Astro's `yaml` parser reports a repeated mapping key as an error, where
|
|
319
|
+
# Psych silently keeps the last value. Keys are compared after resolution,
|
|
320
|
+
# so `1` and `01` collide while `1` and `"1"` do not. Plain `<<` merge
|
|
321
|
+
# keys, alias keys and collection keys are left out.
|
|
322
|
+
def reject_duplicate_keys!(node, scanner, path:, content_start_line:)
|
|
323
|
+
if node.is_a?(Psych::Nodes::Mapping)
|
|
324
|
+
seen = {}
|
|
325
|
+
node.children.each_slice(2) do |key, _value|
|
|
326
|
+
next unless key.is_a?(Psych::Nodes::Scalar)
|
|
327
|
+
next if key.plain && key.value == "<<"
|
|
328
|
+
|
|
329
|
+
resolved = key.plain ? scanner.tokenize(key.value) : key.value
|
|
330
|
+
resolved = resolved.to_f if resolved.is_a?(Numeric)
|
|
331
|
+
if seen.key?(resolved)
|
|
332
|
+
raise syntax_error("duplicate key #{key.value.inspect}", path: path,
|
|
333
|
+
content_start_line: content_start_line,
|
|
334
|
+
relative_line: key.start_line,
|
|
335
|
+
relative_column: key.start_column)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
seen[resolved] = true
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
node.children.to_a.each do |child|
|
|
343
|
+
reject_duplicate_keys!(child, scanner, path: path, content_start_line: content_start_line)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
private_class_method :reject_duplicate_keys!
|
|
347
|
+
|
|
308
348
|
def syntax_error(message, path:, content_start_line:, relative_line:, relative_column:)
|
|
309
349
|
Andromeda::SyntaxError.new(
|
|
310
350
|
message,
|
data/lib/andromeda/version.rb
CHANGED