-
Notifications
You must be signed in to change notification settings - Fork 0
parse source details #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HassanAkbar
wants to merge
4
commits into
main
Choose a base branch
from
source-details-parsing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Termium | ||
| # Parses the asterisk-delimited source details string | ||
| class SourceDetails | ||
| attr_accessor :raw, :standard, :author_name, :year, :organization, :department, :office, :division, :role | ||
|
|
||
| class << self | ||
| def cast(value) | ||
| return value if value.is_a?(SourceDetails) | ||
| return nil if value.nil? || value.to_s.strip.empty? | ||
|
|
||
| new( | ||
| value | ||
| ) | ||
| end | ||
|
|
||
| def serialize(value) | ||
| value&.raw | ||
| end | ||
|
|
||
| alias from_xml cast | ||
| end | ||
|
|
||
| def initialize(value) | ||
| return if value.nil? || value.to_s.strip.empty? | ||
|
|
||
| columns = value.to_s.split("*").map(&:strip) | ||
|
|
||
| @raw = value.to_s | ||
| @year = presence(columns[1]) | ||
| @organization = presence(columns[2]) | ||
| @department = presence(columns[3]) | ||
| @office = presence(columns[4]) | ||
| @division = presence(columns[5]) | ||
| @role = presence(columns[6]) | ||
|
|
||
| first_column = presence(columns[0]) | ||
| if standard_identifier?(first_column) | ||
| @standard = first_column | ||
| else | ||
| @author_name = first_column | ||
| end | ||
| end | ||
|
|
||
| def presence(value) | ||
| value unless value.nil? || value.empty? | ||
| end | ||
|
|
||
| # Matches ISO or ISO-IEC standard identifiers with a document number | ||
| # e.g., "ISO-9000", "ISO-IEC-2382-16", "ISO-IEC-27001" | ||
| def standard_identifier?(value) | ||
| return false if value.nil? | ||
|
|
||
| value.match?(/\AISO(-IEC)?-\d+/i) | ||
| end | ||
|
|
||
| alias to_xml raw | ||
| alias to_s raw | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe Termium::SourceDetails do | ||
| describe ".cast" do | ||
| context "with ISO-IEC standard identifier" do | ||
| let(:input) { "ISO-IEC-2382-16 * 1996 * * * " } | ||
| subject(:details) { described_class.cast(input) } | ||
|
|
||
| it "sets standard from first column" do | ||
| expect(details.standard).to eq("ISO-IEC-2382-16") | ||
| end | ||
|
|
||
| it "sets year" do | ||
| expect(details.year).to eq("1996") | ||
| end | ||
|
|
||
| it "does not set author_name" do | ||
| expect(details.author_name).to be_nil | ||
| end | ||
|
|
||
| it "does not set organization" do | ||
| expect(details.organization).to be_nil | ||
| end | ||
| end | ||
|
|
||
| context "with organization name (not a standard identifier)" do | ||
| let(:input) { "ISO/IEC JTC 1 * 2011" } | ||
| subject(:details) { described_class.cast(input) } | ||
|
|
||
| it "sets author_name from first column" do | ||
| expect(details.author_name).to eq("ISO/IEC JTC 1") | ||
| end | ||
|
|
||
| it "sets year" do | ||
| expect(details.year).to eq("2011") | ||
| end | ||
|
|
||
| it "does not set standard" do | ||
| expect(details.standard).to be_nil | ||
| end | ||
| end | ||
|
|
||
| context "with personal author (has organization)" do | ||
| let(:input) { "Ranger, Natalie * 2006 * Bureau de la traduction * Services linguistiques" } | ||
| subject(:details) { described_class.cast(input) } | ||
|
|
||
| it "sets author_name from first column" do | ||
| expect(details.author_name).to eq("Ranger, Natalie") | ||
| end | ||
|
|
||
| it "sets year" do | ||
| expect(details.year).to eq("2006") | ||
| end | ||
|
|
||
| it "sets organization" do | ||
| expect(details.organization).to eq("Bureau de la traduction") | ||
| end | ||
|
|
||
| it "sets department" do | ||
| expect(details.department).to eq("Services linguistiques") | ||
| end | ||
|
|
||
| it "does not set standard" do | ||
| expect(details.standard).to be_nil | ||
| end | ||
| end | ||
|
|
||
| context "when value is already SourceDetails" do | ||
| let(:original) { described_class.cast("ISO-IEC-2382-16 * 1996 * * * ") } | ||
|
|
||
| it "returns the same object" do | ||
| expect(described_class.cast(original)).to be(original) | ||
| end | ||
| end | ||
|
|
||
| context "with nil input" do | ||
| it "returns nil" do | ||
| expect(described_class.cast(nil)).to be_nil | ||
| end | ||
| end | ||
|
|
||
| context "with empty string" do | ||
| it "returns nil" do | ||
| expect(described_class.cast("")).to be_nil | ||
| end | ||
| end | ||
| end | ||
|
|
||
| describe ".serialize" do | ||
| let(:details) { described_class.cast("ISO-IEC-2382-16 * 1996 * * * ") } | ||
|
|
||
| it "returns the raw string" do | ||
| expect(described_class.serialize(details)).to eq("ISO-IEC-2382-16 * 1996 * * * ") | ||
| end | ||
|
|
||
| it "returns nil for nil input" do | ||
| expect(described_class.serialize(nil)).to be_nil | ||
| end | ||
| end | ||
|
|
||
| describe "#to_s" do | ||
| let(:details) { described_class.cast("Ranger, Natalie * 2006 * Bureau de la traduction") } | ||
|
|
||
| it "returns the raw string" do | ||
| expect(details.to_s).to eq("Ranger, Natalie * 2006 * Bureau de la traduction") | ||
| end | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe Termium::Source do | ||
| describe "XML round-trip" do | ||
| let(:xml_input) { '<source order="1" details="ISO-IEC-2382-16 * 1996 * * * "/>' } | ||
|
|
||
| it "preserves details attribute" do | ||
| source = described_class.from_xml(xml_input) | ||
| output = source.to_xml | ||
|
|
||
| expect(output).to include('details="ISO-IEC-2382-16 * 1996 * * * "') | ||
| end | ||
|
|
||
| it "parses details into SourceDetails object" do | ||
| source = described_class.from_xml(xml_input) | ||
|
|
||
| expect(source.details).to be_a(Termium::SourceDetails) | ||
| expect(source.details.standard).to eq("ISO-IEC-2382-16") | ||
| end | ||
| end | ||
|
|
||
| describe "#content" do | ||
| context "with ISO-IEC standard" do | ||
| let(:source) { described_class.from_xml('<source order="1" details="ISO-IEC-2382-16 * 1996 * * * "/>') } | ||
|
|
||
| it "formats as ISO/IEC reference" do | ||
| expect(source.content).to eq("ISO/IEC 2382-16:1996") | ||
| end | ||
| end | ||
|
|
||
| context "with ISO standard" do | ||
| let(:source) { described_class.from_xml('<source order="1" details="ISO-2382-12 * 1988 * * * "/>') } | ||
|
|
||
| it "formats as ISO reference" do | ||
| expect(source.content).to eq("ISO 2382-12:1988") | ||
| end | ||
| end | ||
|
|
||
| context "with non-standard source" do | ||
| let(:source) { described_class.from_xml('<source order="1" details="Ranger, Natalie * 2006 * Bureau de la traduction"/>') } | ||
|
|
||
| it "returns raw details" do | ||
| expect(source.content).to eq("Ranger, Natalie * 2006 * Bureau de la traduction") | ||
| end | ||
| end | ||
| end | ||
| end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SourceDetails.serializecurrently returnsvalue&.raw, which will returnnilifvalueis a plain String. That can drop data if callers setdetailsto a raw string (or if the serializer passes a string through). Consider handling String inputs explicitly (e.g., returning the string as-is) in addition toSourceDetailsinstances.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
valueparameter is expected to be aSourceDetailsinstance ornil, never a plainString. Strings are converted toSourceDetailsviacastbeforeserializeis called.