diagrammatron 0.4.3 → 0.5.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.
data/lib/subset.yaml ADDED
@@ -0,0 +1,55 @@
1
+ type: object
2
+ properties:
3
+ expressions:
4
+ type: array
5
+ minItems: 0
6
+ default: []
7
+ items:
8
+ type: object
9
+ required:
10
+ - name
11
+ properties:
12
+ name:
13
+ type: string
14
+ expression:
15
+ type: string
16
+ default: ''
17
+ sets:
18
+ type: array
19
+ items:
20
+ $ref: "#/$defs/SetRules"
21
+ minItems: 0
22
+ default: []
23
+ $defs:
24
+ SetRules:
25
+ type: object
26
+ required:
27
+ - name
28
+ properties:
29
+ name:
30
+ type: string
31
+ nodes:
32
+ $ref: "#/$defs/Rules"
33
+ edges:
34
+ $ref: "#/$defs/Rules"
35
+ any:
36
+ $ref: "#/$defs/Rules"
37
+ Rules:
38
+ type: array
39
+ items:
40
+ $ref: "#/$defs/FieldRules"
41
+ minItems: 0
42
+ default: []
43
+ FieldRules:
44
+ type: object
45
+ required:
46
+ - name
47
+ - rules
48
+ properties:
49
+ name:
50
+ type: string
51
+ rules:
52
+ type: array
53
+ items:
54
+ type: string
55
+ minItems: 0
data/lib/subsets.rb ADDED
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2023 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ require_relative '../lib/common'
7
+ require 'ostruct'
8
+ require 'set'
9
+
10
+ def split_expression_string(expression_string)
11
+ out = []
12
+ remaining = expression_string.lstrip
13
+ until remaining.empty?
14
+ item, sep, rest = remaining.partition(/[\s+-]/)
15
+ out << item unless item.empty?
16
+ sep.strip!
17
+ unless sep.empty?
18
+ out << :plus if sep == '+'
19
+ out << :minus if sep == '-'
20
+ end
21
+ remaining = rest.lstrip
22
+ end
23
+ out
24
+ end
25
+
26
+ def identifier?(item)
27
+ item.is_a?(String)
28
+ end
29
+
30
+ def expression_array_errors(expression_array)
31
+ errors = []
32
+ previous_item_type = :symbol
33
+ unless expression_array.empty?
34
+ errors << 'Expression must start with an identifier' unless identifier?(expression_array.first)
35
+ errors << 'Expression must end with an identifier' unless identifier?(expression_array.last)
36
+ end
37
+ expression_array.each_with_index do |item, index|
38
+ current_item_type = identifier?(item) ? :identifier : :symbol
39
+ if current_item_type == previous_item_type
40
+ errors << "Invalid item '#{item}' at index #{index}. Expected #{current_item_type == :identifier ? 'operator' : 'identifier'}."
41
+ end
42
+ previous_item_type = current_item_type
43
+ end
44
+ errors.empty? ? nil : errors
45
+ end
46
+
47
+ def check_rules(r, filename)
48
+ ok = true
49
+ c = {}
50
+ r.fetch('sets', []).each do |setrules|
51
+ name = setrules.delete('name')
52
+ if c.key?(name)
53
+ aargh("#{filename} duplicate set name: #{name}")
54
+ ok = false
55
+ next
56
+ end
57
+ cats = {}
58
+ %i[any nodes edges].each do |category|
59
+ fr = {}
60
+ setrules.fetch(category.to_s, []).each do |fieldrules|
61
+ frn = fieldrules['name']
62
+ res = fr.fetch(frn, [])
63
+ res.concat(fieldrules['rules'].map { |str| Regexp.new(str) })
64
+ fr[frn] = res
65
+ rescue StandardError => e
66
+ aargh("#{filename} #{name} #{category} #{frn} rule error:\n#{e}")
67
+ ok = false
68
+ end
69
+ cats[category] = fr
70
+ end
71
+ c[name] = cats
72
+ end
73
+ r['sets'] = c
74
+ c = {}
75
+ r.fetch('expressions', []).each do |ne|
76
+ name = ne.delete('name')
77
+ if c.key?(name)
78
+ aargh("#{filename} duplicate expression name: #{name}")
79
+ ok = false
80
+ next
81
+ end
82
+ ea = split_expression_string(ne['expression'])
83
+ errs = expression_array_errors(ea)
84
+ unless errs.nil?
85
+ aargh("#{filename} expressions #{name}:\n#{errs.join("\n")}")
86
+ ok = false
87
+ end
88
+ c[name] = ea
89
+ end
90
+ r['expressions'] = c
91
+ ok
92
+ end
93
+
94
+ # Values in any are used if there is no existing value.
95
+ def merge_any(r)
96
+ r.fetch('sets', {}).each_value do |rules|
97
+ any = rules.delete(:any)
98
+ next if any.nil?
99
+ %i[edges nodes].each do |category|
100
+ c = rules.fetch(category, {})
101
+ any.each do |field, patterns|
102
+ next if c.key?(field)
103
+ c[field] = patterns
104
+ end
105
+ rules[category] = c
106
+ end
107
+ end
108
+ end
109
+
110
+ # sets:
111
+ # name:
112
+ # nodes/edges: # Merge here.
113
+ # name: []
114
+ # expressions: # Merge here.
115
+ # name: string
116
+
117
+ def merge_rules(full, overwriting)
118
+ full['expressions'] = {} unless full.key? 'expressions'
119
+ full['expressions'].merge!(overwriting.fetch('expressions', {}))
120
+ sets = full.fetch('sets', {})
121
+ ow = overwriting.fetch('sets', {})
122
+ sets.each do |name, rules|
123
+ %i[nodes edges].each do |category|
124
+ m = ow.dig(name, category)
125
+ next if m.nil?
126
+ rules[category] = {} unless rules.key? category
127
+ rules[category].merge!(m)
128
+ end
129
+ end
130
+ sets.merge!(ow) { |_key, merged, _used| merged } # Adds new sets.
131
+ full['sets'] = sets
132
+ end
133
+
134
+ def match_item(item, rules)
135
+ rules.each do |field, patterns|
136
+ vals = item.fetch(field, nil)
137
+ next if vals.nil?
138
+ vals = [ vals ] unless vals.is_a?(Array)
139
+ patterns.each do |p|
140
+ vals.each do |v|
141
+ next unless v.is_a?(String)
142
+ return true if p.match?(v)
143
+ end
144
+ end
145
+ end
146
+ false
147
+ end
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diagrammatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismo Kärkkäinen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-02 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json_schemer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
13
33
  description: |2
14
34
 
15
35
  Generates diagrams in SVG format from input material. Split into multiple
@@ -22,6 +42,8 @@ executables:
22
42
  - diagrammatron-place
23
43
  - diagrammatron-prune
24
44
  - diagrammatron-render
45
+ - diagrammatron-schema
46
+ - diagrammatron-subset
25
47
  - diagrammatron-template
26
48
  - dot_json2diagrammatron
27
49
  extensions: []
@@ -34,16 +56,25 @@ files:
34
56
  - bin/diagrammatron-place
35
57
  - bin/diagrammatron-prune
36
58
  - bin/diagrammatron-render
59
+ - bin/diagrammatron-schema
60
+ - bin/diagrammatron-subset
37
61
  - bin/diagrammatron-template
38
62
  - bin/dot_json2diagrammatron
39
63
  - lib/common.rb
64
+ - lib/edges.yaml
65
+ - lib/nodes.yaml
66
+ - lib/place.yaml
67
+ - lib/render.yaml
68
+ - lib/subset.yaml
69
+ - lib/subsets.rb
40
70
  - template/internal.yaml
41
71
  - template/root.yaml
42
72
  - template/svg_1.1.erb
43
73
  homepage: https://xn--ismo-krkkinen-gfbd.fi/diagrammatron/index.html
44
74
  licenses:
45
75
  - UPL-1.0
46
- metadata: {}
76
+ metadata:
77
+ rubygems_mfa_required: 'true'
47
78
  post_install_message:
48
79
  rdoc_options: []
49
80
  require_paths:
@@ -52,14 +83,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
83
  requirements:
53
84
  - - ">="
54
85
  - !ruby/object:Gem::Version
55
- version: 2.7.0
86
+ version: 3.0.0
56
87
  required_rubygems_version: !ruby/object:Gem::Requirement
57
88
  requirements:
58
89
  - - ">="
59
90
  - !ruby/object:Gem::Version
60
91
  version: '0'
61
92
  requirements: []
62
- rubygems_version: 3.1.2
93
+ rubygems_version: 3.2.33
63
94
  signing_key:
64
95
  specification_version: 4
65
96
  summary: Generates diagrams from input graph.