sashite-sin 2.1.0 → 3.1.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/LICENSE +201 -0
- data/README.md +115 -274
- data/lib/sashite/sin/constants.rb +38 -0
- data/lib/sashite/sin/errors/argument/messages.rb +45 -0
- data/lib/sashite/sin/errors/argument.rb +21 -0
- data/lib/sashite/sin/errors.rb +19 -0
- data/lib/sashite/sin/identifier.rb +113 -330
- data/lib/sashite/sin/parser.rb +137 -0
- data/lib/sashite/sin.rb +48 -166
- data/lib/sashite-sin.rb +0 -11
- metadata +14 -12
- data/LICENSE.md +0 -22
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "constants"
|
|
4
|
+
require_relative "errors"
|
|
5
|
+
|
|
6
|
+
module Sashite
|
|
7
|
+
module Sin
|
|
8
|
+
# Parses SIN (Style Identifier Notation) strings.
|
|
9
|
+
#
|
|
10
|
+
# The parser uses byte-level validation to ensure security against
|
|
11
|
+
# malformed input, Unicode lookalikes, and injection attacks.
|
|
12
|
+
#
|
|
13
|
+
# @example Parsing a valid SIN string
|
|
14
|
+
# Parser.parse("C") # => { abbr: :C, side: :first }
|
|
15
|
+
# Parser.parse("c") # => { abbr: :C, side: :second }
|
|
16
|
+
#
|
|
17
|
+
# @example Validation
|
|
18
|
+
# Parser.valid?("C") # => true
|
|
19
|
+
# Parser.valid?("CC") # => false
|
|
20
|
+
#
|
|
21
|
+
# @see https://sashite.dev/specs/sin/1.0.0/
|
|
22
|
+
module Parser
|
|
23
|
+
# Parses a SIN string into its components.
|
|
24
|
+
#
|
|
25
|
+
# @param input [String] The SIN string to parse
|
|
26
|
+
# @return [Hash] Hash with :abbr and :side keys
|
|
27
|
+
# @raise [Errors::Argument] If the input is invalid
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# Parser.parse("C") # => { abbr: :C, side: :first }
|
|
31
|
+
# Parser.parse("s") # => { abbr: :S, side: :second }
|
|
32
|
+
def self.parse(input)
|
|
33
|
+
validate_input_type!(input)
|
|
34
|
+
validate_not_empty!(input)
|
|
35
|
+
validate_length!(input)
|
|
36
|
+
|
|
37
|
+
byte = input.getbyte(0)
|
|
38
|
+
validate_letter!(byte)
|
|
39
|
+
|
|
40
|
+
extract_components(byte)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Reports whether the input is a valid SIN string.
|
|
44
|
+
#
|
|
45
|
+
# @param input [String] The string to validate
|
|
46
|
+
# @return [Boolean] true if valid, false otherwise
|
|
47
|
+
#
|
|
48
|
+
# @example
|
|
49
|
+
# Parser.valid?("C") # => true
|
|
50
|
+
# Parser.valid?("c") # => true
|
|
51
|
+
# Parser.valid?("") # => false
|
|
52
|
+
# Parser.valid?("CC") # => false
|
|
53
|
+
def self.valid?(input)
|
|
54
|
+
parse(input)
|
|
55
|
+
true
|
|
56
|
+
rescue Errors::Argument
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @!group Private Class Methods
|
|
61
|
+
|
|
62
|
+
# Validates that input is a String.
|
|
63
|
+
#
|
|
64
|
+
# @param input [Object] The input to validate
|
|
65
|
+
# @raise [Errors::Argument] If input is not a String
|
|
66
|
+
# @return [void]
|
|
67
|
+
private_class_method def self.validate_input_type!(input)
|
|
68
|
+
return if ::String === input
|
|
69
|
+
|
|
70
|
+
raise Errors::Argument, Errors::Argument::Messages::MUST_BE_LETTER
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Validates that input is not empty.
|
|
74
|
+
#
|
|
75
|
+
# @param input [String] The input to validate
|
|
76
|
+
# @raise [Errors::Argument] If input is empty
|
|
77
|
+
# @return [void]
|
|
78
|
+
private_class_method def self.validate_not_empty!(input)
|
|
79
|
+
return unless input.empty?
|
|
80
|
+
|
|
81
|
+
raise Errors::Argument, Errors::Argument::Messages::EMPTY_INPUT
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Validates that input does not exceed maximum length.
|
|
85
|
+
#
|
|
86
|
+
# @param input [String] The input to validate
|
|
87
|
+
# @raise [Errors::Argument] If input exceeds maximum length
|
|
88
|
+
# @return [void]
|
|
89
|
+
private_class_method def self.validate_length!(input)
|
|
90
|
+
return if input.bytesize <= Constants::MAX_STRING_LENGTH
|
|
91
|
+
|
|
92
|
+
raise Errors::Argument, Errors::Argument::Messages::INPUT_TOO_LONG
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Validates that byte is an ASCII letter.
|
|
96
|
+
#
|
|
97
|
+
# @param byte [Integer] The byte to validate
|
|
98
|
+
# @raise [Errors::Argument] If byte is not a letter
|
|
99
|
+
# @return [void]
|
|
100
|
+
private_class_method def self.validate_letter!(byte)
|
|
101
|
+
return if uppercase_letter?(byte) || lowercase_letter?(byte)
|
|
102
|
+
|
|
103
|
+
raise Errors::Argument, Errors::Argument::Messages::MUST_BE_LETTER
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Extracts abbr and side from a validated byte.
|
|
107
|
+
#
|
|
108
|
+
# @param byte [Integer] A validated ASCII letter byte
|
|
109
|
+
# @return [Hash] Hash with :abbr and :side keys
|
|
110
|
+
private_class_method def self.extract_components(byte)
|
|
111
|
+
if uppercase_letter?(byte)
|
|
112
|
+
{ abbr: byte.chr.to_sym, side: :first }
|
|
113
|
+
else
|
|
114
|
+
{ abbr: byte.chr.upcase.to_sym, side: :second }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Reports whether byte is an uppercase ASCII letter (A-Z).
|
|
119
|
+
#
|
|
120
|
+
# @param byte [Integer] The byte to check
|
|
121
|
+
# @return [Boolean] true if A-Z
|
|
122
|
+
private_class_method def self.uppercase_letter?(byte)
|
|
123
|
+
byte >= 0x41 && byte <= 0x5A
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Reports whether byte is a lowercase ASCII letter (a-z).
|
|
127
|
+
#
|
|
128
|
+
# @param byte [Integer] The byte to check
|
|
129
|
+
# @return [Boolean] true if a-z
|
|
130
|
+
private_class_method def self.lowercase_letter?(byte)
|
|
131
|
+
byte >= 0x61 && byte <= 0x7A
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @!endgroup
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
data/lib/sashite/sin.rb
CHANGED
|
@@ -1,188 +1,70 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "sin/constants"
|
|
4
|
+
require_relative "sin/errors"
|
|
3
5
|
require_relative "sin/identifier"
|
|
6
|
+
require_relative "sin/parser"
|
|
4
7
|
|
|
5
8
|
module Sashite
|
|
6
|
-
# SIN (Style Identifier Notation) implementation for Ruby
|
|
9
|
+
# SIN (Style Identifier Notation) implementation for Ruby.
|
|
7
10
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# and player assignment simultaneously.
|
|
11
|
+
# SIN provides a compact, ASCII-based format for encoding Player Style
|
|
12
|
+
# with Player Side assignment in abstract strategy board games.
|
|
11
13
|
#
|
|
12
|
-
#
|
|
14
|
+
# A SIN token is exactly one ASCII letter:
|
|
15
|
+
# - Uppercase (A-Z) indicates first player
|
|
16
|
+
# - Lowercase (a-z) indicates second player
|
|
13
17
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
+
# @example Parsing SIN strings
|
|
19
|
+
# sin = Sashite::Sin.parse("C")
|
|
20
|
+
# sin.abbr # => :C
|
|
21
|
+
# sin.side # => :first
|
|
22
|
+
# sin.to_s # => "C"
|
|
18
23
|
#
|
|
19
|
-
#
|
|
24
|
+
# @example Creating identifiers directly
|
|
25
|
+
# sin = Sashite::Sin::Identifier.new(:C, :first)
|
|
26
|
+
# sin.to_s # => "C"
|
|
20
27
|
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
28
|
+
# @example Validation
|
|
29
|
+
# Sashite::Sin.valid?("C") # => true
|
|
30
|
+
# Sashite::Sin.valid?("CC") # => false
|
|
24
31
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# Structure: `<style-letter>`
|
|
28
|
-
#
|
|
29
|
-
# Grammar (BNF):
|
|
30
|
-
# <sin> ::= <uppercase-letter> | <lowercase-letter>
|
|
31
|
-
# <uppercase-letter> ::= "A" | "B" | "C" | ... | "Z"
|
|
32
|
-
# <lowercase-letter> ::= "a" | "b" | "c" | ... | "z"
|
|
33
|
-
#
|
|
34
|
-
# Regular Expression: `/\A[A-Za-z]\z/`
|
|
35
|
-
#
|
|
36
|
-
# ## Style Attribute Mapping
|
|
37
|
-
#
|
|
38
|
-
# SIN encodes style attributes using the following correspondence:
|
|
39
|
-
#
|
|
40
|
-
# | Style Attribute | SIN Encoding | Examples |
|
|
41
|
-
# |-----------------|--------------|----------|
|
|
42
|
-
# | **Letter** | Single ASCII character | `C`, `c`, `S`, `s` |
|
|
43
|
-
# | **Style Family** | ASCII letter choice (A-Z) | `C`/`c` = Chess, `S`/`s` = Shōgi |
|
|
44
|
-
# | **Player Assignment** | Letter case | `C` = First player, `c` = Second player |
|
|
45
|
-
#
|
|
46
|
-
# The **Letter** attribute combines two distinct semantic components:
|
|
47
|
-
# - **Style Family**: The underlying ASCII character (A-Z), representing the game tradition or rule system
|
|
48
|
-
# - **Player Assignment**: The case of the character (uppercase/lowercase), representing which player uses this style
|
|
49
|
-
#
|
|
50
|
-
# ## Character Selection Conventions
|
|
51
|
-
#
|
|
52
|
-
# ### Primary Convention: First Letter
|
|
53
|
-
# By convention, SIN identifiers should preferably use the **first letter** of the corresponding SNN style name:
|
|
54
|
-
# - `Chess` → `C`/`c`
|
|
55
|
-
# - `Shogi` → `S`/`s`
|
|
56
|
-
# - `Xiangqi` → `X`/`x`
|
|
57
|
-
# - `Makruk` → `M`/`m`
|
|
58
|
-
# - `Janggi` → `J`/`j`
|
|
59
|
-
#
|
|
60
|
-
# ### Collision Resolution
|
|
61
|
-
# When multiple styles would claim the same first letter, systematic collision resolution applies
|
|
62
|
-
# using sequential letter selection from the SNN name until a unique identifier is found.
|
|
63
|
-
#
|
|
64
|
-
# ### Compatibility Groups
|
|
65
|
-
# Styles requiring incompatible board structures can safely share SIN letters since they
|
|
66
|
-
# cannot coexist in the same match.
|
|
67
|
-
#
|
|
68
|
-
# ## System Constraints
|
|
69
|
-
#
|
|
70
|
-
# - **26 possible identifiers** per player using ASCII letters
|
|
71
|
-
# - **Exactly 2 players** through case distinction:
|
|
72
|
-
# - First player: Uppercase letters (`A-Z`)
|
|
73
|
-
# - Second player: Lowercase letters (`a-z`)
|
|
74
|
-
# - **Single character** per style-player combination
|
|
75
|
-
# - **Rule-agnostic** - independent of specific game mechanics
|
|
76
|
-
#
|
|
77
|
-
# ## Examples
|
|
78
|
-
#
|
|
79
|
-
# ### Traditional Game Styles
|
|
80
|
-
#
|
|
81
|
-
# # Chess (8×8)
|
|
82
|
-
# chess_white = Sashite::Sin.parse("C") # First player (White pieces)
|
|
83
|
-
# chess_black = Sashite::Sin.parse("c") # Second player (Black pieces)
|
|
84
|
-
#
|
|
85
|
-
# # Shōgi (9×9)
|
|
86
|
-
# shogi_sente = Sashite::Sin.parse("S") # First player (Sente 先手)
|
|
87
|
-
# shogi_gote = Sashite::Sin.parse("s") # Second player (Gote 後手)
|
|
88
|
-
#
|
|
89
|
-
# # Xiangqi (9×10)
|
|
90
|
-
# xiangqi_red = Sashite::Sin.parse("X") # First player (Red pieces)
|
|
91
|
-
# xiangqi_black = Sashite::Sin.parse("x") # Second player (Black pieces)
|
|
92
|
-
#
|
|
93
|
-
# ### Cross-Style Scenarios
|
|
94
|
-
#
|
|
95
|
-
# # Chess vs. Ōgi Match (both 8×8 compatible)
|
|
96
|
-
# chess_style = Sashite::Sin.parse("C") # Chess style, first player
|
|
97
|
-
# ogi_style = Sashite::Sin.parse("o") # Ōgi style, second player
|
|
98
|
-
#
|
|
99
|
-
# ### All 26 Letters
|
|
100
|
-
#
|
|
101
|
-
# # First player identifiers (A-Z)
|
|
102
|
-
# ("A".."Z").each { |letter| Sashite::Sin.parse(letter).first_player? } # => all true
|
|
103
|
-
#
|
|
104
|
-
# # Second player identifiers (a-z)
|
|
105
|
-
# ("a".."z").each { |letter| Sashite::Sin.parse(letter).second_player? } # => all true
|
|
106
|
-
#
|
|
107
|
-
# ## Design Properties
|
|
108
|
-
#
|
|
109
|
-
# - **ASCII compatibility**: Maximum portability across systems
|
|
110
|
-
# - **Rule-agnostic**: Independent of specific game mechanics
|
|
111
|
-
# - **Minimal overhead**: Single character per style-player combination
|
|
112
|
-
# - **Flexible collision resolution**: Systematic approaches for identifier conflicts
|
|
113
|
-
# - **Semantic clarity**: Distinct concepts for Letter (Style Family + Player Assignment)
|
|
114
|
-
# - **SNN coordination**: Works harmoniously with formal style naming
|
|
115
|
-
# - **Context-aware**: Adapts to avoid conflicts within specific game scenarios
|
|
116
|
-
#
|
|
117
|
-
# @see https://sashite.dev/specs/sin/1.0.0/ SIN Specification v1.0.0
|
|
118
|
-
# @see https://sashite.dev/specs/sin/1.0.0/examples/ SIN Examples
|
|
119
|
-
# @see https://sashite.dev/specs/snn/ Style Name Notation (SNN)
|
|
32
|
+
# @see https://sashite.dev/specs/sin/1.0.0/
|
|
120
33
|
module Sin
|
|
121
|
-
#
|
|
34
|
+
# Parses a SIN string into an Identifier.
|
|
122
35
|
#
|
|
123
|
-
# @param
|
|
124
|
-
# @return [
|
|
36
|
+
# @param input [String] The SIN string to parse
|
|
37
|
+
# @return [Identifier] The parsed identifier
|
|
38
|
+
# @raise [Errors::Argument] If the input is invalid
|
|
125
39
|
#
|
|
126
|
-
# @example
|
|
127
|
-
# Sashite::Sin.
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
# Sashite::Sin.valid?("s") # => true (Shōgi second player)
|
|
131
|
-
# Sashite::Sin.valid?("CHESS") # => false (multi-character)
|
|
132
|
-
# Sashite::Sin.valid?("1") # => false (not a letter)
|
|
133
|
-
# Sashite::Sin.valid?("") # => false (empty string)
|
|
134
|
-
def self.valid?(sin_string)
|
|
135
|
-
Identifier.valid?(sin_string)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Parse an SIN string into an Identifier object
|
|
139
|
-
#
|
|
140
|
-
# The identifier will have both letter and side attributes inferred from the case:
|
|
141
|
-
# - Uppercase letter → first player (:first)
|
|
142
|
-
# - Lowercase letter → second player (:second)
|
|
143
|
-
#
|
|
144
|
-
# @param sin_string [String] SIN notation string (single ASCII letter)
|
|
145
|
-
# @return [Sin::Identifier] parsed identifier object with letter and side attributes
|
|
146
|
-
# @raise [ArgumentError] if the SIN string is invalid
|
|
147
|
-
#
|
|
148
|
-
# @example Parse different SIN formats with dual-purpose encoding
|
|
149
|
-
# Sashite::Sin.parse("C") # => #<Sashite::Sin::Identifier @family=:C, @side=:first>
|
|
150
|
-
# Sashite::Sin.parse("c") # => #<Sashite::Sin::Identifier @family=:C, @side=:second>
|
|
151
|
-
# Sashite::Sin.parse("S") # => #<Sashite::Sin::Identifier @family=:S, @side=:first>
|
|
152
|
-
# Sashite::Sin.parse("s") # => #<Sashite::Sin::Identifier @family=:S, @side=:second>
|
|
40
|
+
# @example Parsing uppercase (first player)
|
|
41
|
+
# sin = Sashite::Sin.parse("C")
|
|
42
|
+
# sin.abbr # => :C
|
|
43
|
+
# sin.side # => :first
|
|
153
44
|
#
|
|
154
|
-
# @example
|
|
155
|
-
#
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
45
|
+
# @example Parsing lowercase (second player)
|
|
46
|
+
# sin = Sashite::Sin.parse("c")
|
|
47
|
+
# sin.abbr # => :C
|
|
48
|
+
# sin.side # => :second
|
|
49
|
+
def self.parse(input)
|
|
50
|
+
components = Parser.parse(input)
|
|
51
|
+
|
|
52
|
+
Identifier.new(components.fetch(:abbr), components.fetch(:side))
|
|
161
53
|
end
|
|
162
54
|
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
# Ensures the letter case matches the specified side:
|
|
166
|
-
# - :first side → uppercase letter
|
|
167
|
-
# - :second side → lowercase letter
|
|
168
|
-
#
|
|
169
|
-
# @param family [Symbol] style family (:A to :Z representing Style Family)
|
|
170
|
-
# @param side [Symbol] player side (:first or :second)
|
|
171
|
-
# @return [Sin::Identifier] new immutable identifier instance
|
|
172
|
-
# @raise [ArgumentError] if parameters are invalid
|
|
173
|
-
#
|
|
174
|
-
# @example Create identifiers with family and side separation
|
|
175
|
-
# Sashite::Sin.identifier(:C, :first) # => #<Sashite::Sin::Identifier @family=:C, @side=:first>
|
|
176
|
-
# Sashite::Sin.identifier(:C, :second) # => #<Sashite::Sin::Identifier @family=:C, @side=:second>
|
|
55
|
+
# Reports whether the input is a valid SIN string.
|
|
177
56
|
#
|
|
178
|
-
# @
|
|
179
|
-
#
|
|
180
|
-
# chess_second = Sashite::Sin.identifier(:C, :second) # Chess family, second player
|
|
57
|
+
# @param input [String] The string to validate
|
|
58
|
+
# @return [Boolean] true if valid, false otherwise
|
|
181
59
|
#
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
|
|
185
|
-
|
|
60
|
+
# @example
|
|
61
|
+
# Sashite::Sin.valid?("C") # => true
|
|
62
|
+
# Sashite::Sin.valid?("c") # => true
|
|
63
|
+
# Sashite::Sin.valid?("") # => false
|
|
64
|
+
# Sashite::Sin.valid?("CC") # => false
|
|
65
|
+
# Sashite::Sin.valid?("1") # => false
|
|
66
|
+
def self.valid?(input)
|
|
67
|
+
Parser.valid?(input)
|
|
186
68
|
end
|
|
187
69
|
end
|
|
188
70
|
end
|
data/lib/sashite-sin.rb
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "sashite/sin"
|
|
4
|
-
|
|
5
|
-
# Sashité namespace for board game notation libraries
|
|
6
|
-
#
|
|
7
|
-
# Sashité provides a collection of libraries for representing and manipulating
|
|
8
|
-
# board game concepts according to the Sashité Protocol specifications.
|
|
9
|
-
#
|
|
10
|
-
# @see https://sashite.dev/protocol/ Sashité Protocol
|
|
11
|
-
# @see https://sashite.dev/specs/ Sashité Specifications
|
|
12
|
-
# @author Sashité
|
|
13
|
-
module Sashite
|
|
14
|
-
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sashite-sin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cyril Kato
|
|
@@ -9,33 +9,35 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
|
-
description:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
a modern Ruby interface featuring immutable identifier objects and functional programming
|
|
16
|
-
principles. SIN uses single ASCII letters with case-based side encoding (A-Z for first player,
|
|
17
|
-
a-z for second player), enabling clear distinction between different style families in
|
|
18
|
-
multi-style gaming environments. Perfect for cross-style matches, game engines, and hybrid
|
|
19
|
-
gaming systems requiring compact style identification with enhanced collision resolution.
|
|
12
|
+
description: SIN (Style Identifier Notation) implementation for Ruby. Provides a rule-agnostic
|
|
13
|
+
format for identifying player styles in abstract strategy board games with immutable
|
|
14
|
+
identifier objects and functional programming principles.
|
|
20
15
|
email: contact@cyril.email
|
|
21
16
|
executables: []
|
|
22
17
|
extensions: []
|
|
23
18
|
extra_rdoc_files: []
|
|
24
19
|
files:
|
|
25
|
-
- LICENSE
|
|
20
|
+
- LICENSE
|
|
26
21
|
- README.md
|
|
27
22
|
- lib/sashite-sin.rb
|
|
28
23
|
- lib/sashite/sin.rb
|
|
24
|
+
- lib/sashite/sin/constants.rb
|
|
25
|
+
- lib/sashite/sin/errors.rb
|
|
26
|
+
- lib/sashite/sin/errors/argument.rb
|
|
27
|
+
- lib/sashite/sin/errors/argument/messages.rb
|
|
29
28
|
- lib/sashite/sin/identifier.rb
|
|
29
|
+
- lib/sashite/sin/parser.rb
|
|
30
30
|
homepage: https://github.com/sashite/sin.rb
|
|
31
31
|
licenses:
|
|
32
|
-
-
|
|
32
|
+
- Apache-2.0
|
|
33
33
|
metadata:
|
|
34
34
|
bug_tracker_uri: https://github.com/sashite/sin.rb/issues
|
|
35
35
|
documentation_uri: https://rubydoc.info/github/sashite/sin.rb/main
|
|
36
36
|
homepage_uri: https://github.com/sashite/sin.rb
|
|
37
37
|
source_code_uri: https://github.com/sashite/sin.rb
|
|
38
38
|
specification_uri: https://sashite.dev/specs/sin/1.0.0/
|
|
39
|
+
wiki_uri: https://sashite.dev/specs/sin/1.0.0/examples/
|
|
40
|
+
funding_uri: https://github.com/sponsors/sashite
|
|
39
41
|
rubygems_mfa_required: 'true'
|
|
40
42
|
rdoc_options: []
|
|
41
43
|
require_paths:
|
|
@@ -51,7 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
51
53
|
- !ruby/object:Gem::Version
|
|
52
54
|
version: '0'
|
|
53
55
|
requirements: []
|
|
54
|
-
rubygems_version:
|
|
56
|
+
rubygems_version: 4.0.3
|
|
55
57
|
specification_version: 4
|
|
56
58
|
summary: SIN (Style Identifier Notation) implementation for Ruby with immutable identifier
|
|
57
59
|
objects
|
data/LICENSE.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2025 Cyril Kato
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
a copy of this software and associated documentation files (the
|
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
-
the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
|
14
|
-
included in all copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|