asciichem 0.30.0 → 0.30.1
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 +13 -0
- data/lib/asciichem/cml/group_extensions.rb +35 -6
- data/lib/asciichem/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: 2f8a0ef9952b9507c35ded04295298a3a62e86a7efce1f92d258a1aaf6d6125c
|
|
4
|
+
data.tar.gz: 0d11ccfb16383194e8a1fd3bf0816ce8b8465b548bc6dac43535d2633a0cf2ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 270015bf0f88f0bc2f06452a472759970b39ab75ae9aef233ea3c9f94f7b3abc2d20752098151aedd7ab51251aaad9414cfdb349167c059ac036e8bbdaff04d5
|
|
7
|
+
data.tar.gz: a4211637fc504c7db50994d14b151bb5e45357b48d870b4f4aff7eb49c79c269ba7014a755fd00c6e8dd22678e1f044011b9b4123ecc24530b9d693464a11357
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
All notable changes to AsciiChem are documented here.
|
|
4
4
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.30.1] - 2026-09-23
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- Groups attached by an explicit bond no longer re-spell through
|
|
10
|
+
CML round-trip: `CC(=O)O` came back as `CC=(O)O`. The CML
|
|
11
|
+
rebuilder left the attachment bond outside the reconstructed
|
|
12
|
+
group; the grammar keeps it inside (the inner molecule starts
|
|
13
|
+
with the bond), so the rebuilder now pulls an adjacent preceding
|
|
14
|
+
Bond into the group. Affects text syntax and SMILES ingestion
|
|
15
|
+
alike; regression specs cover single/sibling bonded groups,
|
|
16
|
+
multi-atom groups, and aspirin stability across double
|
|
17
|
+
round-trips.
|
|
18
|
+
|
|
6
19
|
## [0.30.0] - 2026-09-22
|
|
7
20
|
|
|
8
21
|
### Changed
|
|
@@ -213,18 +213,23 @@ module AsciiChem
|
|
|
213
213
|
def self.splice_group_into(nodes, target_nodes, record)
|
|
214
214
|
return if target_nodes.empty?
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
inner_nodes = group_nodes(nodes, target_nodes)
|
|
217
|
+
|
|
218
|
+
positions = target_nodes
|
|
219
|
+
.map { |target| position_of(nodes, target) }
|
|
220
|
+
.compact
|
|
220
221
|
return if positions.empty?
|
|
221
222
|
|
|
222
223
|
group = AsciiChem::Model::Group.new(
|
|
223
|
-
nodes:
|
|
224
|
+
nodes: inner_nodes,
|
|
224
225
|
multiplicity: record[:multiplicity],
|
|
225
226
|
bracket: record[:bracket]
|
|
226
227
|
)
|
|
228
|
+
replace_positions_with_group(nodes, group, positions)
|
|
229
|
+
end
|
|
230
|
+
private_class_method :splice_group_into
|
|
227
231
|
|
|
232
|
+
def self.replace_positions_with_group(nodes, group, positions)
|
|
228
233
|
first_pos = positions.min
|
|
229
234
|
nodes[first_pos] = group
|
|
230
235
|
# Remove remaining positions in descending order so earlier
|
|
@@ -233,7 +238,31 @@ module AsciiChem
|
|
|
233
238
|
nodes.delete_at(pos)
|
|
234
239
|
end
|
|
235
240
|
end
|
|
236
|
-
private_class_method :
|
|
241
|
+
private_class_method :replace_positions_with_group
|
|
242
|
+
|
|
243
|
+
# A Bond sitting immediately before the group's first target node
|
|
244
|
+
# is the group's attachment bond — the `=` of `C(=O)`. The
|
|
245
|
+
# grammar keeps that bond INSIDE the group (its inner molecule
|
|
246
|
+
# starts with the bond), so the rebuilder moves it in instead of
|
|
247
|
+
# leaving a stray prefix bond outside, which would re-spell as
|
|
248
|
+
# `C=(O)`. By construction of the bond insertion (each bond sits
|
|
249
|
+
# just before its later endpoint), a bond adjacent to the group's
|
|
250
|
+
# first atom always has that atom as its later endpoint.
|
|
251
|
+
def self.group_nodes(nodes, target_nodes)
|
|
252
|
+
idx = position_of(nodes, target_nodes.first)
|
|
253
|
+
bond = idx&.positive? ? nodes[idx - 1] : nil
|
|
254
|
+
return target_nodes unless bond.is_a?(AsciiChem::Model::Bond)
|
|
255
|
+
|
|
256
|
+
[nodes.delete_at(idx - 1), *target_nodes]
|
|
257
|
+
end
|
|
258
|
+
private_class_method :group_nodes
|
|
259
|
+
|
|
260
|
+
# Identity-based position lookup so duplicate Bonds (same kind
|
|
261
|
+
# → `==` equal) aren't confused.
|
|
262
|
+
def self.position_of(nodes, node)
|
|
263
|
+
nodes.each_with_index.find { |candidate, _| candidate.equal?(node) }&.last
|
|
264
|
+
end
|
|
265
|
+
private_class_method :position_of
|
|
237
266
|
|
|
238
267
|
# Flatten the canonical document's molecules (top-level +
|
|
239
268
|
# reaction reactants/products + cascade reactions) into a list,
|
data/lib/asciichem/version.rb
CHANGED