pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.12
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/README.adoc +33 -11
- data/conformance/pending.yaml +4 -0
- data/lib/pubid/adobe/identifier.rb +1 -3
- data/lib/pubid/adobe/parser.rb +10 -2
- data/lib/pubid/adobe.rb +1 -0
- data/lib/pubid/amca/builder.rb +2 -2
- data/lib/pubid/amca/identifiers/base.rb +49 -27
- data/lib/pubid/amca/identifiers/interpretation.rb +17 -9
- data/lib/pubid/amca/identifiers/publication.rb +13 -9
- data/lib/pubid/amca/identifiers/standard.rb +2 -0
- data/lib/pubid/amca/parser.rb +1 -1
- data/lib/pubid/amca/renderer.rb +4 -4
- data/lib/pubid/amca/urn_generator.rb +2 -2
- data/lib/pubid/amca.rb +2 -1
- data/lib/pubid/ansi/builder.rb +2 -2
- data/lib/pubid/ansi/identifier.rb +18 -0
- data/lib/pubid/ansi/parser.rb +1 -1
- data/lib/pubid/ansi/renderer.rb +2 -2
- data/lib/pubid/ansi.rb +5 -5
- data/lib/pubid/api/builder.rb +16 -2
- data/lib/pubid/api/identifier.rb +25 -4
- data/lib/pubid/api/identifiers/mpms.rb +10 -8
- data/lib/pubid/api/parser.rb +1 -1
- data/lib/pubid/api/renderer.rb +16 -7
- data/lib/pubid/api/single_identifier.rb +5 -12
- data/lib/pubid/api.rb +1 -0
- data/lib/pubid/ashrae/builder.rb +31 -10
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +6 -0
- data/lib/pubid/ashrae/identifiers/addendum.rb +8 -0
- data/lib/pubid/ashrae/identifiers/base.rb +81 -5
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +7 -0
- data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
- data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
- data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
- data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
- data/lib/pubid/ashrae/parser.rb +23 -8
- data/lib/pubid/ashrae/renderer.rb +6 -6
- data/lib/pubid/ashrae/supplement_identifier.rb +17 -2
- data/lib/pubid/ashrae/urn_generator.rb +8 -2
- data/lib/pubid/ashrae.rb +7 -1
- data/lib/pubid/asme/builder.rb +11 -2
- data/lib/pubid/asme/identifier.rb +9 -0
- data/lib/pubid/asme/identifiers/standard.rb +86 -2
- data/lib/pubid/asme/parser.rb +1 -1
- data/lib/pubid/asme/renderer.rb +3 -3
- data/lib/pubid/asme/single_identifier.rb +8 -1
- data/lib/pubid/asme/urn_generator.rb +2 -2
- data/lib/pubid/asme.rb +1 -0
- data/lib/pubid/astm/builder.rb +10 -3
- data/lib/pubid/astm/identifier.rb +9 -0
- data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
- data/lib/pubid/astm/identifiers/code_number.rb +81 -0
- data/lib/pubid/astm/identifiers/data_series.rb +2 -0
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
- data/lib/pubid/astm/identifiers/manual.rb +10 -0
- data/lib/pubid/astm/identifiers/monograph.rb +2 -0
- data/lib/pubid/astm/identifiers/research_report.rb +10 -0
- data/lib/pubid/astm/identifiers/standard.rb +10 -0
- data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
- data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
- data/lib/pubid/astm/identifiers.rb +1 -0
- data/lib/pubid/astm/parser.rb +1 -1
- data/lib/pubid/astm/renderer.rb +1 -1
- data/lib/pubid/astm/single_identifier.rb +31 -1
- data/lib/pubid/astm/urn_generator.rb +7 -5
- data/lib/pubid/astm.rb +1 -0
- data/lib/pubid/bipm/builder.rb +66 -10
- data/lib/pubid/bipm/identifier.rb +134 -9
- data/lib/pubid/bipm/identifiers/committee_document.rb +12 -0
- data/lib/pubid/bipm/identifiers/guide.rb +11 -0
- data/lib/pubid/bipm/identifiers/meeting.rb +12 -0
- data/lib/pubid/bipm/identifiers/mep.rb +12 -0
- data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
- data/lib/pubid/bipm/identifiers/si_brochure.rb +13 -0
- data/lib/pubid/bipm/parser.rb +65 -12
- data/lib/pubid/bipm/renderer.rb +8 -0
- data/lib/pubid/bipm/urn_parser.rb +11 -3
- data/lib/pubid/bipm.rb +7 -1
- data/lib/pubid/bsi/builder.rb +48 -38
- data/lib/pubid/bsi/components/date.rb +10 -4
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -2
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
- data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
- data/lib/pubid/bsi/identifiers/handbook.rb +1 -3
- data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -2
- data/lib/pubid/bsi/identifiers/set.rb +11 -0
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
- data/lib/pubid/bsi/parser.rb +1 -1
- data/lib/pubid/bsi/renderer.rb +63 -51
- data/lib/pubid/bsi/single_identifier.rb +27 -9
- data/lib/pubid/bsi/urn_generator.rb +11 -2
- data/lib/pubid/bsi.rb +7 -1
- data/lib/pubid/builder/base.rb +18 -8
- data/lib/pubid/bundled_identifier.rb +16 -6
- data/lib/pubid/calconnect/identifier.rb +9 -5
- data/lib/pubid/calconnect/parser.rb +1 -1
- data/lib/pubid/calconnect.rb +7 -1
- data/lib/pubid/ccsds/identifier.rb +13 -2
- data/lib/pubid/ccsds/identifiers/base.rb +4 -2
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/ccsds/parser.rb +1 -1
- data/lib/pubid/ccsds/single_identifier.rb +16 -12
- data/lib/pubid/ccsds.rb +1 -0
- data/lib/pubid/cen_cenelec/builder.rb +101 -76
- data/lib/pubid/cen_cenelec/identifier.rb +115 -3
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
- data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
- data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/parser.rb +1 -1
- data/lib/pubid/cen_cenelec/renderer.rb +55 -60
- data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
- data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
- data/lib/pubid/cen_cenelec.rb +28 -10
- data/lib/pubid/cie/builder.rb +10 -0
- data/lib/pubid/cie/identifier.rb +6 -1
- data/lib/pubid/cie/identifiers/bundle.rb +4 -2
- data/lib/pubid/cie/identifiers/conference.rb +2 -2
- data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
- data/lib/pubid/cie/identifiers/identical.rb +2 -2
- data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
- data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
- data/lib/pubid/cie/identifiers/standard.rb +22 -13
- data/lib/pubid/cie/identifiers/supplement.rb +2 -2
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
- data/lib/pubid/cie/parser.rb +1 -1
- data/lib/pubid/cie.rb +7 -1
- data/lib/pubid/conformance/checks.rb +72 -0
- data/lib/pubid/conformance/corpus/case.rb +55 -0
- data/lib/pubid/conformance/corpus.rb +36 -0
- data/lib/pubid/conformance/generator.rb +212 -0
- data/lib/pubid/conformance/pending.rb +63 -0
- data/lib/pubid/conformance/runner.rb +153 -0
- data/lib/pubid/conformance.rb +55 -0
- data/lib/pubid/core.rb +2 -0
- data/lib/pubid/csa/builder.rb +47 -47
- data/lib/pubid/csa/composite_identifier.rb +14 -19
- data/lib/pubid/csa/identifier.rb +143 -81
- data/lib/pubid/csa/identifiers/bundled.rb +23 -13
- data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
- data/lib/pubid/csa/identifiers/cec.rb +44 -4
- data/lib/pubid/csa/identifiers/combined.rb +95 -73
- data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
- data/lib/pubid/csa/identifiers/package.rb +2 -2
- data/lib/pubid/csa/parser.rb +6 -2
- data/lib/pubid/csa/renderer.rb +13 -5
- data/lib/pubid/csa/single_identifier.rb +93 -4
- data/lib/pubid/csa/urn_generator.rb +9 -2
- data/lib/pubid/csa/wrapper_identifier.rb +39 -23
- data/lib/pubid/csa.rb +7 -1
- data/lib/pubid/doi/identifier.rb +6 -3
- data/lib/pubid/doi/parser.rb +1 -1
- data/lib/pubid/doi.rb +1 -0
- data/lib/pubid/easc/identifier.rb +0 -2
- data/lib/pubid/easc/parser.rb +10 -2
- data/lib/pubid/easc.rb +1 -0
- data/lib/pubid/ecma/builder.rb +23 -9
- data/lib/pubid/ecma/identifier.rb +81 -10
- data/lib/pubid/ecma/parser.rb +39 -4
- data/lib/pubid/ecma/renderer.rb +29 -8
- data/lib/pubid/ecma/urn_generator.rb +34 -13
- data/lib/pubid/ecma/urn_parser.rb +30 -14
- data/lib/pubid/ecma.rb +1 -0
- data/lib/pubid/errors.rb +80 -0
- data/lib/pubid/etsi/builder.rb +6 -1
- data/lib/pubid/etsi/identifiers/base.rb +34 -20
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
- data/lib/pubid/etsi/parser.rb +1 -1
- data/lib/pubid/etsi.rb +1 -0
- data/lib/pubid/evs/builder.rb +26 -0
- data/lib/pubid/evs/identifier.rb +37 -0
- data/lib/pubid/evs/identifiers/national_adoption.rb +22 -0
- data/lib/pubid/evs/identifiers.rb +9 -0
- data/lib/pubid/evs/parser.rb +27 -0
- data/lib/pubid/evs/renderer.rb +30 -0
- data/lib/pubid/evs/urn_generator.rb +30 -0
- data/lib/pubid/evs/urn_parser.rb +80 -0
- data/lib/pubid/evs.rb +90 -0
- data/lib/pubid/export.rb +1 -0
- data/lib/pubid/format_detector.rb +1 -0
- data/lib/pubid/gb/builder.rb +14 -9
- data/lib/pubid/gb/identifier.rb +29 -7
- data/lib/pubid/gb/parser.rb +5 -1
- data/lib/pubid/gb/renderer.rb +4 -3
- data/lib/pubid/gb.rb +2 -0
- data/lib/pubid/gost/builder.rb +46 -9
- data/lib/pubid/gost/identifier.rb +0 -2
- data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
- data/lib/pubid/gost/parser.rb +10 -2
- data/lib/pubid/gost.rb +1 -0
- data/lib/pubid/iala/identifier.rb +9 -6
- data/lib/pubid/iala/parser.rb +10 -2
- data/lib/pubid/iala/urn_parser.rb +6 -2
- data/lib/pubid/iala.rb +1 -0
- data/lib/pubid/iana/builder.rb +3 -1
- data/lib/pubid/iana/identifier.rb +74 -6
- data/lib/pubid/iana/identifiers/registry.rb +36 -0
- data/lib/pubid/iana/parser.rb +1 -1
- data/lib/pubid/iana/renderer.rb +3 -0
- data/lib/pubid/iana/urn_generator.rb +5 -1
- data/lib/pubid/iana.rb +1 -0
- data/lib/pubid/identifier.rb +605 -13
- data/lib/pubid/identifier_metadata.rb +1 -0
- data/lib/pubid/idf/builder.rb +3 -3
- data/lib/pubid/idf/identifier.rb +25 -9
- data/lib/pubid/idf/identifiers/amendment.rb +1 -1
- data/lib/pubid/idf/identifiers/corrigendum.rb +1 -1
- data/lib/pubid/idf/identifiers/international_standard.rb +1 -1
- data/lib/pubid/idf/identifiers/reviewed_method.rb +1 -1
- data/lib/pubid/idf/parser.rb +1 -1
- data/lib/pubid/idf/renderer.rb +4 -4
- data/lib/pubid/idf/single_identifier.rb +1 -1
- data/lib/pubid/idf/urn_generator.rb +1 -1
- data/lib/pubid/idf.rb +7 -1
- data/lib/pubid/iec/builder.rb +14 -7
- data/lib/pubid/iec/components.rb +0 -1
- data/lib/pubid/iec/identifier.rb +73 -83
- data/lib/pubid/iec/identifiers/amendment.rb +6 -2
- data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
- data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
- data/lib/pubid/iec/identifiers/guide.rb +0 -16
- data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
- data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
- data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
- data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
- data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
- data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
- data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
- data/lib/pubid/iec/identifiers/working_document.rb +24 -10
- data/lib/pubid/iec/parser.rb +2 -18
- data/lib/pubid/iec/renderer.rb +13 -10
- data/lib/pubid/iec/single_identifier.rb +33 -10
- data/lib/pubid/iec/urn_generator.rb +227 -61
- data/lib/pubid/iec/urn_parser.rb +42 -4
- data/lib/pubid/iec.rb +1 -0
- data/lib/pubid/ieee/aiee/identifier.rb +2 -2
- data/lib/pubid/ieee/aiee/parser.rb +1 -1
- data/lib/pubid/ieee/builder.rb +87 -3
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
- data/lib/pubid/ieee/identifiers/base.rb +42 -5
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
- data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
- data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
- data/lib/pubid/ieee/identifiers/si_standard.rb +5 -2
- data/lib/pubid/ieee/ire/identifier.rb +2 -2
- data/lib/pubid/ieee/ire/parser.rb +20 -2
- data/lib/pubid/ieee/nesc/parser.rb +1 -1
- data/lib/pubid/ieee/parser.rb +208 -33
- data/lib/pubid/ieee/project_renderer.rb +46 -0
- data/lib/pubid/ieee/renderer.rb +11 -8
- data/lib/pubid/ieee/urn_generator.rb +32 -3
- data/lib/pubid/ieee.rb +9 -1
- data/lib/pubid/ieee_debug.rb +1 -0
- data/lib/pubid/ietf/builder.rb +24 -8
- data/lib/pubid/ietf/identifiers/base.rb +25 -28
- data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
- data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
- data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
- data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
- data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
- data/lib/pubid/ietf/identifiers/std.rb +11 -0
- data/lib/pubid/ietf/identifiers.rb +1 -0
- data/lib/pubid/ietf/parser.rb +27 -9
- data/lib/pubid/ietf/renderer.rb +44 -6
- data/lib/pubid/ietf/urn_generator.rb +20 -6
- data/lib/pubid/ietf/urn_parser.rb +10 -2
- data/lib/pubid/ietf.rb +12 -2
- data/lib/pubid/iho/identifiers/base.rb +10 -3
- data/lib/pubid/iho/parser.rb +1 -1
- data/lib/pubid/iho.rb +1 -0
- data/lib/pubid/isbn/identifier.rb +25 -7
- data/lib/pubid/isbn/parser.rb +1 -1
- data/lib/pubid/isbn.rb +1 -0
- data/lib/pubid/iso/builder.rb +10 -11
- data/lib/pubid/iso/bundled_identifier.rb +5 -3
- data/lib/pubid/iso/combined_identifier.rb +5 -3
- data/lib/pubid/iso/components.rb +0 -1
- data/lib/pubid/iso/identifier.rb +23 -11
- data/lib/pubid/iso/identifiers/directives.rb +7 -4
- data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
- data/lib/pubid/iso/identifiers/tc_document.rb +31 -46
- data/lib/pubid/iso/normalizer.rb +1 -1
- data/lib/pubid/iso/parser.rb +1 -1
- data/lib/pubid/iso/urn_generator.rb +10 -10
- data/lib/pubid/iso.rb +12 -5
- data/lib/pubid/itu/builder.rb +10 -0
- data/lib/pubid/itu/identifiers/addendum.rb +2 -2
- data/lib/pubid/itu/identifiers/amendment.rb +2 -2
- data/lib/pubid/itu/identifiers/base.rb +29 -5
- data/lib/pubid/itu/identifiers/contribution.rb +31 -0
- data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/itu/identifiers/errata.rb +2 -2
- data/lib/pubid/itu/identifiers/supplement.rb +2 -2
- data/lib/pubid/itu/identifiers.rb +1 -0
- data/lib/pubid/itu/parser.rb +20 -3
- data/lib/pubid/itu.rb +1 -0
- data/lib/pubid/jcgm/builder.rb +1 -1
- data/lib/pubid/jcgm/identifier.rb +10 -0
- data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
- data/lib/pubid/jcgm/parser.rb +10 -3
- data/lib/pubid/jcgm/renderer.rb +10 -3
- data/lib/pubid/jcgm/single_identifier.rb +24 -15
- data/lib/pubid/jcgm/urn_generator.rb +1 -1
- data/lib/pubid/jcgm/urn_parser.rb +156 -14
- data/lib/pubid/jcgm.rb +10 -0
- data/lib/pubid/jis/identifier.rb +10 -3
- data/lib/pubid/jis/parser.rb +1 -1
- data/lib/pubid/jis.rb +1 -0
- data/lib/pubid/nist/builder.rb +12 -12
- data/lib/pubid/nist/components/stage.rb +2 -2
- data/lib/pubid/nist/configuration.rb +6 -8
- data/lib/pubid/nist/identifiers/base.rb +22 -5
- data/lib/pubid/nist/identifiers/circular.rb +9 -2
- data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
- data/lib/pubid/nist/identifiers/crpl_report.rb +12 -7
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +2 -2
- data/lib/pubid/nist/identifiers/handbook.rb +9 -2
- data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +16 -8
- data/lib/pubid/nist/identifiers/monograph.rb +14 -7
- data/lib/pubid/nist/identifiers/report.rb +14 -6
- data/lib/pubid/nist/parser.rb +1 -1
- data/lib/pubid/nist/series/ir.rb +3 -7
- data/lib/pubid/nist/supplement_identifier.rb +16 -1
- data/lib/pubid/nist.rb +7 -1
- data/lib/pubid/oasis/builder.rb +12 -10
- data/lib/pubid/oasis/identifier.rb +89 -11
- data/lib/pubid/oasis/parser.rb +1 -1
- data/lib/pubid/oasis.rb +7 -1
- data/lib/pubid/ogc/identifier.rb +9 -5
- data/lib/pubid/ogc/parser.rb +1 -1
- data/lib/pubid/ogc.rb +1 -0
- data/lib/pubid/oiml/builder.rb +7 -3
- data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
- data/lib/pubid/oiml/identifiers/bulletin.rb +40 -10
- data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
- data/lib/pubid/oiml/identifiers/document.rb +2 -0
- data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/guide.rb +2 -0
- data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
- data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
- data/lib/pubid/oiml/identifiers.rb +1 -0
- data/lib/pubid/oiml/parser.rb +8 -3
- data/lib/pubid/oiml/renderer.rb +3 -3
- data/lib/pubid/oiml/single_identifier.rb +26 -42
- data/lib/pubid/oiml/supplement_identifier.rb +27 -0
- data/lib/pubid/oiml/urn_generator.rb +4 -4
- data/lib/pubid/oiml.rb +7 -1
- data/lib/pubid/omg/builder.rb +1 -0
- data/lib/pubid/omg/identifier.rb +20 -3
- data/lib/pubid/omg/parser.rb +64 -11
- data/lib/pubid/omg/renderer.rb +13 -1
- data/lib/pubid/omg.rb +2 -1
- data/lib/pubid/parser/grammar.rb +74 -0
- data/lib/pubid/parser.rb +2 -0
- data/lib/pubid/parsers/mr_string.rb +19 -0
- data/lib/pubid/plateau/parser.rb +1 -1
- data/lib/pubid/plateau.rb +10 -0
- data/lib/pubid/prefixes_support.rb +1 -0
- data/lib/pubid/renderers/annotator.rb +233 -0
- data/lib/pubid/renderers/base.rb +13 -0
- data/lib/pubid/renderers/directives_renderer.rb +6 -4
- data/lib/pubid/renderers/human_readable.rb +3 -3
- data/lib/pubid/renderers/mr_string.rb +15 -9
- data/lib/pubid/renderers.rb +1 -0
- data/lib/pubid/rendering/numbering.rb +25 -7
- data/lib/pubid/rendering.rb +1 -0
- data/lib/pubid/sae/builder.rb +1 -1
- data/lib/pubid/sae/identifiers/base.rb +13 -3
- data/lib/pubid/sae/parser.rb +1 -1
- data/lib/pubid/sae/urn_generator.rb +1 -1
- data/lib/pubid/sae.rb +1 -0
- data/lib/pubid/schema/declaration.rb +33 -0
- data/lib/pubid/schema/error.rb +14 -0
- data/lib/pubid/schema/identifier_type.rb +23 -0
- data/lib/pubid/schema/loader.rb +117 -0
- data/lib/pubid/schema/typed_stage.rb +24 -0
- data/lib/pubid/schema.rb +25 -0
- data/lib/pubid/tgpp/builder.rb +1 -1
- data/lib/pubid/tgpp/identifier.rb +21 -5
- data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
- data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
- data/lib/pubid/tgpp/parser.rb +22 -6
- data/lib/pubid/tgpp/renderer.rb +21 -5
- data/lib/pubid/tgpp/urn_generator.rb +27 -8
- data/lib/pubid/tgpp/urn_parser.rb +8 -6
- data/lib/pubid/tgpp.rb +7 -1
- data/lib/pubid/type_resolver.rb +16 -1
- data/lib/pubid/un/identifier.rb +6 -3
- data/lib/pubid/un/parser.rb +1 -1
- data/lib/pubid/un.rb +1 -0
- data/lib/pubid/urn_parser/errors.rb +8 -1
- data/lib/pubid/urn_parser.rb +1 -0
- data/lib/pubid/utils.rb +1 -0
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid/w3c/builder.rb +5 -5
- data/lib/pubid/w3c/identifier.rb +38 -9
- data/lib/pubid/w3c/parser.rb +1 -1
- data/lib/pubid/w3c/renderer.rb +1 -1
- data/lib/pubid/w3c/urn_generator.rb +2 -2
- data/lib/pubid/w3c.rb +1 -0
- data/lib/pubid/xsf/identifier.rb +9 -5
- data/lib/pubid/xsf/parser.rb +17 -4
- data/lib/pubid/xsf.rb +7 -1
- data/lib/pubid.rb +399 -21
- data/lib/tasks/conformance.rake +34 -0
- data/lib/tasks/docs.rake +16 -14
- data/lib/tasks/schema.rake +88 -0
- data/schema/core/joint_prefixes.yaml +24 -0
- data/schema/iec.yaml +1017 -0
- data/schema/iso.yaml +1586 -0
- data/schema/schema.schema.yaml +96 -0
- metadata +40 -19
- data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
- data/archived-gems/pubid-iec/stages.yaml +0 -129
- data/archived-gems/pubid-iec/update_codes.yaml +0 -67
- data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
- data/archived-gems/pubid-iso/stages.yaml +0 -106
- data/archived-gems/pubid-iso/update_codes.yaml +0 -4
- data/archived-gems/pubid-itu/i18n.yaml +0 -13
- data/archived-gems/pubid-itu/series.yaml +0 -42
- data/archived-gems/pubid-nist/publishers.yaml +0 -6
- data/archived-gems/pubid-nist/series.yaml +0 -121
- data/archived-gems/pubid-nist/update_codes.yaml +0 -93
- data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
- data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +0 -70
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
- data/lib/pubid/iec/components/code.rb +0 -36
- data/lib/pubid/iso/components/code.rb +0 -24
- /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
data/lib/pubid/iec/urn_parser.rb
CHANGED
|
@@ -31,16 +31,24 @@ module Pubid
|
|
|
31
31
|
# @return [Identifier] parsed identifier
|
|
32
32
|
def parse_urn(urn)
|
|
33
33
|
unless urn.start_with?("urn:iec:std:")
|
|
34
|
-
raise Errors::ParseError, "Invalid IEC URN: #{urn}"
|
|
34
|
+
raise Pubid::UrnParser::Errors::ParseError, "Invalid IEC URN: #{urn}"
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
code, lang, all_parts = urn_to_code(urn)
|
|
38
|
-
|
|
38
|
+
unless code
|
|
39
|
+
raise Pubid::UrnParser::Errors::ParseError,
|
|
40
|
+
"Invalid IEC URN: #{urn}"
|
|
41
|
+
end
|
|
39
42
|
|
|
40
43
|
id = Pubid::Iec::Identifier.parse(code)
|
|
41
44
|
id.all_parts = true if all_parts && id.class.attributes.key?(:all_parts)
|
|
45
|
+
# The language slot joins codes with a hyphen ("en-fr"). Building one
|
|
46
|
+
# Language from the whole field gave a single bogus language that
|
|
47
|
+
# rendered as "(en-fr)".
|
|
42
48
|
if lang && !lang.empty? && id.class.attributes.key?(:languages)
|
|
43
|
-
id.languages =
|
|
49
|
+
id.languages = lang.split("-").map do |code|
|
|
50
|
+
::Pubid::Components::Language.new(code: code)
|
|
51
|
+
end
|
|
44
52
|
end
|
|
45
53
|
id
|
|
46
54
|
end
|
|
@@ -57,7 +65,8 @@ module Pubid
|
|
|
57
65
|
all_parts = false
|
|
58
66
|
|
|
59
67
|
code = head.gsub("-", "/")
|
|
60
|
-
|
|
68
|
+
type_code = type_slot_to_code(type)
|
|
69
|
+
code += " #{type_code}" unless type_code.empty?
|
|
61
70
|
code += " #{num}"
|
|
62
71
|
code += ":#{date}" unless date.nil? || date.empty?
|
|
63
72
|
code += adjunct_to_code(fields[9..])
|
|
@@ -67,6 +76,8 @@ module Pubid
|
|
|
67
76
|
# part or date, so to_s renders "IEC NNNN (all parts)").
|
|
68
77
|
if deliv&.casecmp("SER")&.zero?
|
|
69
78
|
all_parts = true
|
|
79
|
+
elsif (edition = edition_slot_to_code(deliv))
|
|
80
|
+
code += " #{edition}"
|
|
70
81
|
elsif deliv && !deliv.empty?
|
|
71
82
|
code += " #{deliv}"
|
|
72
83
|
end
|
|
@@ -74,6 +85,33 @@ module Pubid
|
|
|
74
85
|
[code, lang&.downcase, all_parts]
|
|
75
86
|
end
|
|
76
87
|
|
|
88
|
+
# The type slot holds either the legacy type token ("TS"), a stage
|
|
89
|
+
# ("STAGE-10.20"), or both ("TS-STAGE-50.00"). A stage is written back as
|
|
90
|
+
# the abbreviation the grammar accepts, resolved from the registry by
|
|
91
|
+
# type code and harmonized code — so the round trip is exact in both
|
|
92
|
+
# directions. See issue #360 item 4.
|
|
93
|
+
def type_slot_to_code(type)
|
|
94
|
+
return "" if type.nil? || type.empty?
|
|
95
|
+
|
|
96
|
+
match = /\A(?:([A-Z]+)-)?STAGE-([\d.]+)\z/.match(type)
|
|
97
|
+
return type unless match
|
|
98
|
+
|
|
99
|
+
type_code = (match[1] || "IS").downcase
|
|
100
|
+
stage = Pubid::Iec.all_typed_stages.find do |s|
|
|
101
|
+
s.type_code.to_s == type_code &&
|
|
102
|
+
s.harmonized_stages&.first.to_s == match[2]
|
|
103
|
+
end
|
|
104
|
+
return "" unless stage
|
|
105
|
+
|
|
106
|
+
stage.abbr.first.to_s
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# "ED-7" in the deliverable slot is an edition, not a deliverable code.
|
|
110
|
+
def edition_slot_to_code(deliv)
|
|
111
|
+
match = /\AED-(.+)\z/.match(deliv.to_s)
|
|
112
|
+
match && "ED#{match[1]}"
|
|
113
|
+
end
|
|
114
|
+
|
|
77
115
|
# Port of Relaton::Iec.ajanct_to_code — recursively rebuilds amd/cor/ish
|
|
78
116
|
# adjuncts from (relation, type, number, date) quartets. A "PLUS"
|
|
79
117
|
# relation token (the consolidated "+" marker) yields "+"; otherwise "/".
|
data/lib/pubid/iec.rb
CHANGED
|
@@ -39,7 +39,7 @@ module Pubid
|
|
|
39
39
|
Builder.new.build(parsed)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def to_s(date_format: nil, trademark: false)
|
|
42
|
+
def to_s(date_format: nil, trademark: false, **opts)
|
|
43
43
|
result = [publisher]
|
|
44
44
|
result << type if type
|
|
45
45
|
result << code.to_s if code
|
|
@@ -81,7 +81,7 @@ module Pubid
|
|
|
81
81
|
# document number/filename downstream). It stays reachable on
|
|
82
82
|
# `relationships`.
|
|
83
83
|
|
|
84
|
-
base
|
|
84
|
+
annotate_plain_render(base, **opts)
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
|
@@ -7,7 +7,7 @@ module Pubid
|
|
|
7
7
|
module Aiee
|
|
8
8
|
# Parser for AIEE (American Institute of Electrical Engineers) identifiers
|
|
9
9
|
# Historical period: 1884-1963 (merged into IEEE in 1963)
|
|
10
|
-
class Parser <
|
|
10
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
11
11
|
# Basic building blocks
|
|
12
12
|
rule(:space) { str(" ") }
|
|
13
13
|
rule(:space?) { space.maybe }
|
data/lib/pubid/ieee/builder.rb
CHANGED
|
@@ -290,6 +290,16 @@ module Pubid
|
|
|
290
290
|
return build_interpretation_supplement(parsed_hash)
|
|
291
291
|
end
|
|
292
292
|
|
|
293
|
+
# The same document with a TRAILING DATE parses FLAT — no :base subtree,
|
|
294
|
+
# just an :interpretation marker beside the number — so the branch above
|
|
295
|
+
# skipped it and determine_identifier_class built a base-less
|
|
296
|
+
# InterpretationIdentifier that dropped the number, the part and the
|
|
297
|
+
# publisher: "IEEE Std 1003.2-1992/INT, Dec. 1994 Ed." rendered as
|
|
298
|
+
# " 1003.2-1992/INT". Mirrors build_flat_corrigendum / build_flat_amendment.
|
|
299
|
+
if parsed_hash[:interpretation] && !parsed_hash[:base]
|
|
300
|
+
return build_flat_interpretation(parsed_hash)
|
|
301
|
+
end
|
|
302
|
+
|
|
293
303
|
# Handle conformance supplements (check for base + conf_number)
|
|
294
304
|
if parsed_hash[:base] && parsed_hash[:conf_number]
|
|
295
305
|
return build_conformance_supplement(parsed_hash)
|
|
@@ -432,6 +442,35 @@ module Pubid
|
|
|
432
442
|
)
|
|
433
443
|
end
|
|
434
444
|
|
|
445
|
+
# Build an interpretation from a FLAT parse tree — the trailing-date form,
|
|
446
|
+
# where the :interpretation marker sits beside the base's own keys instead
|
|
447
|
+
# of over a :base subtree.
|
|
448
|
+
#
|
|
449
|
+
# The trailing date is the INTERPRETATION's date (an interpretation of the
|
|
450
|
+
# 1992 edition of 1003.2, issued in Dec 1994), so it goes on the wrapper;
|
|
451
|
+
# the base keeps its own `year`. That matches the nested form, whose
|
|
452
|
+
# `int_year` also lands on the wrapper.
|
|
453
|
+
# @param parsed_hash [Hash] flat parsed data carrying :interpretation
|
|
454
|
+
# @return [Identifiers::InterpretationIdentifier]
|
|
455
|
+
def build_flat_interpretation(parsed_hash)
|
|
456
|
+
int_year = extract_value(parsed_hash[:trailing_year]) if parsed_hash[:trailing_year]
|
|
457
|
+
|
|
458
|
+
base_hash = parsed_hash.reject do |key, _|
|
|
459
|
+
%i[interpretation trailing_month trailing_year].include?(key)
|
|
460
|
+
end
|
|
461
|
+
base = build_single_identifier(base_hash)
|
|
462
|
+
|
|
463
|
+
# The trailing MONTH is deliberately dropped, matching the nested form
|
|
464
|
+
# (whose `int_year` carries no month either). It was not preserved
|
|
465
|
+
# before this change, so nothing is lost; and setting it fed the URN's
|
|
466
|
+
# month_day_component, which put "Dec." — a word with a dot — into a
|
|
467
|
+
# URN segment.
|
|
468
|
+
Identifiers::InterpretationIdentifier.new(
|
|
469
|
+
base: base,
|
|
470
|
+
year: int_year,
|
|
471
|
+
)
|
|
472
|
+
end
|
|
473
|
+
|
|
435
474
|
# Build amendment supplement with recursive base parsing. Mirrors
|
|
436
475
|
# {#build_corrigendum_supplement} — reconstructs the base identifier
|
|
437
476
|
# string, recursively parses it, and wraps it in an Amendment.
|
|
@@ -630,7 +669,14 @@ module Pubid
|
|
|
630
669
|
# Extract publishers from joint_publishers
|
|
631
670
|
if parsed[:joint_publishers]
|
|
632
671
|
joint_pub_str = extract_value(parsed[:joint_publishers])
|
|
633
|
-
|
|
672
|
+
pubs = joint_pub_str.split("/")
|
|
673
|
+
attributes[:publishers] = pubs
|
|
674
|
+
# lutaml materializes attribute defaults during from_hash, so the
|
|
675
|
+
# deserialized joint carries publisher/copublisher alongside
|
|
676
|
+
# publishers; set the same shape on the parse path or the
|
|
677
|
+
# amendment-wrapped round-trip diverges on exactly those keys.
|
|
678
|
+
attributes[:publisher] = pubs.first
|
|
679
|
+
attributes[:copublisher] = pubs.drop(1)
|
|
634
680
|
end
|
|
635
681
|
|
|
636
682
|
# Build code with parts if present
|
|
@@ -654,6 +700,15 @@ module Pubid
|
|
|
654
700
|
end
|
|
655
701
|
attributes[:month] = extract_value(parsed[:month]) if parsed[:month]
|
|
656
702
|
|
|
703
|
+
# A text date trailing the DRAFT (pubid#216: "CD P26515/D1, March
|
|
704
|
+
# 2017") reaches the builder under :draft_month/:draft_year — the
|
|
705
|
+
# grammar captures them separately to avoid the :month/:year
|
|
706
|
+
# duplicate-subtree collision with the date clause.
|
|
707
|
+
if parsed[:draft_year]
|
|
708
|
+
attributes[:year] ||= extract_value(parsed[:draft_year])
|
|
709
|
+
attributes[:month] ||= extract_value(parsed[:draft_month])
|
|
710
|
+
end
|
|
711
|
+
|
|
657
712
|
# Extract edition, from relaton's "/E-<n>" suffix (normalized to
|
|
658
713
|
# "Edition <n>.0"). nil-residue hand-off item 1.
|
|
659
714
|
attributes[:edition] = extract_value(parsed[:edition]) if parsed[:edition]
|
|
@@ -683,6 +738,10 @@ module Pubid
|
|
|
683
738
|
attributes[:typed_stage] =
|
|
684
739
|
Pubid::Ieee.locate_stage(stage_abbr)
|
|
685
740
|
end
|
|
741
|
+
elsif parsed[:iso_published]
|
|
742
|
+
# Stage-less PUBLISHED joint form (pubid#317): ISO-led spelling,
|
|
743
|
+
# no project marker, no typed stage - renders as printed.
|
|
744
|
+
attributes[:lead_party] = "ISO"
|
|
686
745
|
else
|
|
687
746
|
# IEEE format - lead party is IEEE
|
|
688
747
|
attributes[:lead_party] = "IEEE"
|
|
@@ -695,7 +754,19 @@ module Pubid
|
|
|
695
754
|
Pubid::Ieee.locate_stage("P")
|
|
696
755
|
end
|
|
697
756
|
|
|
698
|
-
Identifiers::JointDevelopment.new(**attributes)
|
|
757
|
+
joint = Identifiers::JointDevelopment.new(**attributes)
|
|
758
|
+
|
|
759
|
+
# Amendment tail on the joint ISO-format form (pubid#317:
|
|
760
|
+
# "8802-11:2012/Amd.1:2014(E)"): wrap the joint id, mirroring
|
|
761
|
+
# build_flat_amendment.
|
|
762
|
+
return joint unless parsed[:amd_number]
|
|
763
|
+
|
|
764
|
+
amd_year = extract_value(parsed[:amd_year]) if parsed[:amd_year]
|
|
765
|
+
Identifiers::Amendment.new(
|
|
766
|
+
base: joint,
|
|
767
|
+
number: extract_value(parsed[:amd_number]),
|
|
768
|
+
year: amd_year,
|
|
769
|
+
)
|
|
699
770
|
end
|
|
700
771
|
|
|
701
772
|
# Build SI/PSI identifier from parsed data
|
|
@@ -770,9 +841,14 @@ module Pubid
|
|
|
770
841
|
# Pattern: slash >> "C" >> digits >> dot >> digits >> dot >> digits >> dash >> year_digits
|
|
771
842
|
# The parsed crossref is a string - extract the number part
|
|
772
843
|
# Format: C62.22.1-1996 where C is part of the crossref notation
|
|
844
|
+
# The captured slice keeps the leading slash, which is a SEPARATOR in
|
|
845
|
+
# the printed reference, not part of the number. Storing it made the
|
|
846
|
+
# secondary's code "/C62.22.1-1996", which then failed the renderer's
|
|
847
|
+
# own cross-reference test (`/^C\d+\./`) and fell through to the
|
|
848
|
+
# " and " join. Strip it.
|
|
773
849
|
secondary_id = Identifiers::Standard.new(
|
|
774
850
|
publisher: "IEEE",
|
|
775
|
-
number: extract_value(crossref),
|
|
851
|
+
number: extract_value(crossref).to_s.sub(%r{\A/}, ""),
|
|
776
852
|
)
|
|
777
853
|
elsif parsed[:secondary_joint]
|
|
778
854
|
# Joint standard format: ", Std 1177-1989"
|
|
@@ -1145,6 +1221,14 @@ module Pubid
|
|
|
1145
1221
|
return "P"
|
|
1146
1222
|
elsif type_value == "Std"
|
|
1147
1223
|
return "Std"
|
|
1224
|
+
elsif type_value == "Draft Std" && parsed[:draft].nil? && parsed[:digit_draft].nil?
|
|
1225
|
+
# A version-less "Draft Std" fabricates /D1 (issue #205);
|
|
1226
|
+
# deriving the stage from that fabricated version renders the
|
|
1227
|
+
# same P-prefixed form as an explicit "/D1" spelling, so the
|
|
1228
|
+
# render reaches its fixed point in one round (pubid#318).
|
|
1229
|
+
# Gated on no-draft: a dotted version ("D2.0") fails the registry
|
|
1230
|
+
# lookup above and must fall through, keeping "Draft Std".
|
|
1231
|
+
return "D1"
|
|
1148
1232
|
elsif type_value.match?(/^No\.?$/)
|
|
1149
1233
|
return type_value
|
|
1150
1234
|
end
|
|
@@ -30,6 +30,38 @@ module Pubid
|
|
|
30
30
|
ieee_identifier&.publisher || "IEEE"
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
# An adoption names one document by two designations and carries no
|
|
34
|
+
# number of its own, so `root.number` — the key relaton-index sorts and
|
|
35
|
+
# bsearches on — was "". Walk to the IEEE designation, which is the one
|
|
36
|
+
# IEEE files the document under, and which is also the source of truth
|
|
37
|
+
# for `publisher` above.
|
|
38
|
+
def root
|
|
39
|
+
ieee_identifier ? ieee_identifier.root : self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The document number must reach the URN and the MR slug too, not only
|
|
43
|
+
# `#root` — the project rule that an identity-bearing marker reaches
|
|
44
|
+
# every identity surface. `UrnGenerator#code_component` and the base
|
|
45
|
+
# `mr_number_with_part` both read `code_obj`, which a wrapper does not
|
|
46
|
+
# have, so all 66 adoptions collapsed onto 5 URNs and 5 slugs — and
|
|
47
|
+
# `to_slug` is an output FILENAME, so that is 66 documents overwriting
|
|
48
|
+
# each other. Delegate to the IEEE designation, as `#root` does.
|
|
49
|
+
#
|
|
50
|
+
# `code_obj` is a plain attr_accessor on the base, not a lutaml
|
|
51
|
+
# attribute, so overriding it as a method is safe here.
|
|
52
|
+
def code_obj
|
|
53
|
+
ieee_identifier&.code_obj
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Likewise the year: without it "AIEE No 15-1944" and "AIEE No 15-1959"
|
|
57
|
+
# — two different documents — produced the same slug "aiee.std.15".
|
|
58
|
+
# This is the `mr_year` HOOK, not a `#year` method: `year` is a lutaml
|
|
59
|
+
# attribute on the base, and a method of that name would shadow the
|
|
60
|
+
# generated accessor (the CLAUDE.md landmine).
|
|
61
|
+
def mr_year
|
|
62
|
+
(year || ieee_identifier&.year)&.to_s
|
|
63
|
+
end
|
|
64
|
+
|
|
33
65
|
# `publisher` is *derived* from `ieee_identifier` (the serialized source
|
|
34
66
|
# of truth), so it must not be serialized. Emitting it breaks the
|
|
35
67
|
# canonical round-trip: the derived value is default-omitted on the parse
|
|
@@ -15,7 +15,9 @@ module Pubid
|
|
|
15
15
|
# @return [String] URN representation
|
|
16
16
|
|
|
17
17
|
attribute :publisher, :string, default: -> { "IEEE" }
|
|
18
|
-
|
|
18
|
+
# IEC, ISO, ANSI, etc. `initialize_empty` makes from_hash give `[]`, the
|
|
19
|
+
# value a parsed identifier holds, so the two paths stay `==`.
|
|
20
|
+
attribute :copublisher, :string, collection: true, initialize_empty: true
|
|
19
21
|
# NB: there is deliberately NO `attribute :code`. IEEE's document code is
|
|
20
22
|
# serialized as the split index columns (number/prefix/parts/separator) on
|
|
21
23
|
# concrete leaf types via the CodeNumber mixin; `code`/`code_obj` remain a
|
|
@@ -72,8 +74,19 @@ module Pubid
|
|
|
72
74
|
# what the base `Pubid::Identifier#exclude`/matching machinery uses when it
|
|
73
75
|
# rebuilds via `self.class.new(attrs)`; without it, `exclude`/`matches?`
|
|
74
76
|
# raised ArgumentError for every IEEE identifier.
|
|
77
|
+
# Constructor parameters that are not lutaml attributes: `code` is
|
|
78
|
+
# runtime-only (kept as `code_obj`), and the draft forms are turned into
|
|
79
|
+
# component objects below.
|
|
80
|
+
def self.extra_init_keys
|
|
81
|
+
%i[code draft draft_obj]
|
|
82
|
+
end
|
|
83
|
+
|
|
75
84
|
def initialize(args = {}, **kwargs)
|
|
76
85
|
args = args.merge(kwargs) unless kwargs.empty?
|
|
86
|
+
# This override calls `super()` with no attributes and assigns through
|
|
87
|
+
# setters instead, so it bypasses the base constructor's coercion and
|
|
88
|
+
# unknown-key check. Apply them here to keep the cross-flavor contract.
|
|
89
|
+
args = self.class.normalize_init_attributes(args)
|
|
77
90
|
super()
|
|
78
91
|
|
|
79
92
|
# Handle typed_stage if provided
|
|
@@ -104,13 +117,26 @@ module Pubid
|
|
|
104
117
|
self.draft = args[:draft].to_s
|
|
105
118
|
end
|
|
106
119
|
|
|
107
|
-
# Set other attributes
|
|
120
|
+
# Set other attributes.
|
|
121
|
+
#
|
|
122
|
+
# A key the class accepts but does not declare as a lutaml attribute
|
|
123
|
+
# (see `extra_init_keys`) is assigned through its plain accessor.
|
|
124
|
+
# Without that, `CsaDualPublished#csa_identifier` — an `attr_accessor`
|
|
125
|
+
# by design, "stored as-is (not a Lutaml model type)" — was never
|
|
126
|
+
# assigned at all, and `renderer.rb` read nil from it:
|
|
127
|
+
# `IEEE Std 844.1-2017/CSA C22.2 No. 293.1-17` rendered back as
|
|
128
|
+
# `IEEE Std 844.1-2017/CSA`, losing the CSA designation entirely.
|
|
108
129
|
attrs = self.class.attributes
|
|
130
|
+
extra = self.class.extra_init_keys
|
|
109
131
|
args.each do |key, value|
|
|
110
132
|
next if %i[code draft draft_obj typed_stage].include?(key)
|
|
111
133
|
|
|
112
134
|
setter = :"#{key}="
|
|
113
|
-
|
|
135
|
+
if attrs.key?(key)
|
|
136
|
+
public_send(setter, value)
|
|
137
|
+
elsif extra.include?(key) && respond_to?(setter)
|
|
138
|
+
public_send(setter, value)
|
|
139
|
+
end
|
|
114
140
|
end
|
|
115
141
|
end
|
|
116
142
|
|
|
@@ -208,8 +234,13 @@ module Pubid
|
|
|
208
234
|
# orchestrator that consumes a PreParser::Result and routes to the
|
|
209
235
|
# correct builder.
|
|
210
236
|
def self.parse(input)
|
|
237
|
+
unless input.is_a?(String)
|
|
238
|
+
raise Pubid::Errors::InvalidInputError,
|
|
239
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
240
|
+
end
|
|
241
|
+
|
|
211
242
|
if input.length > Pubid::MAX_INPUT_LENGTH
|
|
212
|
-
raise
|
|
243
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
213
244
|
end
|
|
214
245
|
|
|
215
246
|
result = PreParser.preprocess(input)
|
|
@@ -275,9 +306,15 @@ module Pubid
|
|
|
275
306
|
def self.build_aiee_asa_adoption(parts)
|
|
276
307
|
aiee_id = parse_single(parts[0])
|
|
277
308
|
asa_id = parse_single(parts[1])
|
|
309
|
+
# `adopted_identifierS` — AdoptedStandard declares a collection. The
|
|
310
|
+
# singular spelling was not an attribute, so lutaml dropped it without
|
|
311
|
+
# a word and the ASA half of these 13 identifiers was never stored:
|
|
312
|
+
# `AIEE No 18-1934 (ASA C55 1934)` rendered back as `AIEE No 18-1934`.
|
|
313
|
+
# The unknown-key contract turned that silent loss into a raise, which
|
|
314
|
+
# is how it was found.
|
|
278
315
|
Identifiers::AdoptedStandard.new(
|
|
279
316
|
ieee_identifier: aiee_id,
|
|
280
|
-
|
|
317
|
+
adopted_identifiers: [asa_id],
|
|
281
318
|
)
|
|
282
319
|
end
|
|
283
320
|
private_class_method :build_aiee_asa_adoption
|
|
@@ -11,6 +11,27 @@ module Pubid
|
|
|
11
11
|
# CSA identifier is stored as-is (not a Lutaml model type)
|
|
12
12
|
attr_accessor :csa_identifier
|
|
13
13
|
|
|
14
|
+
# `csa_identifier` is a real constructor parameter even though it is
|
|
15
|
+
# not a lutaml attribute, so the unknown-key contract must let it
|
|
16
|
+
# through — and the constructor must actually assign it.
|
|
17
|
+
def self.extra_init_keys
|
|
18
|
+
super + %i[csa_identifier]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Walk to the IEEE designation for the relaton-index key: this wrapper
|
|
22
|
+
# names one document by an IEEE and a CSA number and holds neither
|
|
23
|
+
# itself, so `root.number` was "".
|
|
24
|
+
def root
|
|
25
|
+
ieee_identifier ? ieee_identifier.root : self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Carry the number onto the URN and the MR slug as well as #root — see
|
|
29
|
+
# AdoptedStandard#code_obj. `#code` below delegates already, but the
|
|
30
|
+
# URN generator and the MR renderer both read `code_obj`.
|
|
31
|
+
def code_obj
|
|
32
|
+
ieee_identifier&.code_obj
|
|
33
|
+
end
|
|
34
|
+
|
|
14
35
|
# Delegate common attributes to ieee_identifier
|
|
15
36
|
def publisher
|
|
16
37
|
ieee_identifier.publisher
|
|
@@ -18,6 +18,61 @@ module Pubid
|
|
|
18
18
|
# Return array of both publishers
|
|
19
19
|
[first_identifier&.publisher, second_identifier&.publisher].compact
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
# `publisher` above is DERIVED from the two member identifiers (the
|
|
23
|
+
# serialized source of truth), so it must not be serialized itself.
|
|
24
|
+
# Emitting it breaks the canonical round-trip exactly as it did on
|
|
25
|
+
# Identifiers::AdoptedStandard and Identifiers::JointDevelopment: the
|
|
26
|
+
# derived value is default-omitted on the parse path (the attribute is
|
|
27
|
+
# unset), but re-emitted once from_hash materializes the attribute
|
|
28
|
+
# default, because the override then returns the members' publishers
|
|
29
|
+
# rather than the "IEEE" default. Worse here, it is an ARRAY, so the
|
|
30
|
+
# re-emitted value was the literal string `["IEEE", "IEEE"]`.
|
|
31
|
+
#
|
|
32
|
+
# This made all 25 DualPublished ids in the fixture corpus fail
|
|
33
|
+
# `from_hash(to_hash) == to_hash` — the gate relaton's index build
|
|
34
|
+
# uses, which SKIPS a document that fails it. Dropping the key is
|
|
35
|
+
# lossless: first_identifier and second_identifier rebuild it.
|
|
36
|
+
#
|
|
37
|
+
# A top-level to_hash delete is sufficient because DualPublished is
|
|
38
|
+
# only ever a top-level wrapper, never a nested `base` (where lutaml's
|
|
39
|
+
# own transform would bypass this override).
|
|
40
|
+
def to_hash(*args)
|
|
41
|
+
hash = super
|
|
42
|
+
hash.delete("publisher") if hash.is_a?(::Hash)
|
|
43
|
+
hash
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# A dual-published document is one document under two designations, and
|
|
47
|
+
# this wrapper carries neither number itself — so `root.number`, the key
|
|
48
|
+
# relaton-index sorts and bsearches on, was "". Walk to the first
|
|
49
|
+
# designation, which is the one the printed reference leads with.
|
|
50
|
+
def root
|
|
51
|
+
first_identifier ? first_identifier.root : self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Carry the number onto the URN and the MR slug as well as #root — see
|
|
55
|
+
# AdoptedStandard#code_obj for why all three surfaces need it.
|
|
56
|
+
def code_obj
|
|
57
|
+
first_identifier&.code_obj
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# See AdoptedStandard#mr_year — without it the 1989 and the 1993
|
|
61
|
+
# printings of "IEEE Std 960 and IEEE Std 1177" shared one slug.
|
|
62
|
+
def mr_year
|
|
63
|
+
(year || first_identifier&.year)&.to_s
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# `#publisher` above returns an ARRAY, and the inherited `mr_publisher`
|
|
67
|
+
# is `publisher&.to_s&.downcase` — so the MR slug contained a literal
|
|
68
|
+
# Ruby array (`["ieee", "asme"]`, brackets, quotes, comma and space
|
|
69
|
+
# included) and `to_slug` is an output FILENAME. Join the two instead,
|
|
70
|
+
# keeping both publishers in the slug: they are equally part of this
|
|
71
|
+
# document's identity, so by the project rule both must reach it.
|
|
72
|
+
def mr_publisher
|
|
73
|
+
names = Array(publisher).map { |p| p.to_s.downcase }.reject(&:empty?)
|
|
74
|
+
names.empty? ? nil : names.join("-")
|
|
75
|
+
end
|
|
21
76
|
end
|
|
22
77
|
end
|
|
23
78
|
end
|
|
@@ -10,6 +10,29 @@ module Pubid
|
|
|
10
10
|
# Uniform `year` (the interpretation year), not `int_year` — inherited
|
|
11
11
|
# from the base, so no attribute is declared here.
|
|
12
12
|
|
|
13
|
+
# The interpreted standard's code must reach the URN. Before this
|
|
14
|
+
# change the flat-parsed form kept its number in the wrapper's own
|
|
15
|
+
# `code_obj` (the builder never built a base), so the URN carried it by
|
|
16
|
+
# accident; now that the number lives on `base` where it belongs, the
|
|
17
|
+
# URN generator has to be pointed at it or the URN silently loses the
|
|
18
|
+
# document number. `code_obj` is a plain attr_accessor, not a lutaml
|
|
19
|
+
# attribute, so overriding it as a method is safe.
|
|
20
|
+
def code_obj
|
|
21
|
+
super || base&.code_obj
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# MR supplement suffix: `int.{year}` — mirrors Corrigendum/Amendment.
|
|
25
|
+
# Without it the MrString renderer slugs an interpretation FLAT off
|
|
26
|
+
# attributes a supplement does not have, instead of recursing into
|
|
27
|
+
# `base`, so every interpretation of every standard collapsed onto
|
|
28
|
+
# "ieee.std.{year}" with no document number at all — and `to_slug` is
|
|
29
|
+
# an output FILENAME.
|
|
30
|
+
def mr_supplement_suffix
|
|
31
|
+
segments = ["int"]
|
|
32
|
+
segments << year.to_s if year
|
|
33
|
+
segments.join(".")
|
|
34
|
+
end
|
|
35
|
+
|
|
13
36
|
# TYPED_STAGES for interpretation
|
|
14
37
|
# Interpretation uses "INT" abbreviation
|
|
15
38
|
TYPED_STAGES = [
|
|
@@ -93,7 +93,9 @@ module Pubid
|
|
|
93
93
|
# @param format [Symbol] :ieee or :iso (defaults to canonical_format)
|
|
94
94
|
# @param trademark [Boolean] append the IEEE trademark symbol (™/®)
|
|
95
95
|
# @return [String] formatted identifier
|
|
96
|
-
|
|
96
|
+
# `**_opts` absorbs render flags this list does not name (`annotated:`),
|
|
97
|
+
# which the closed keyword list used to reject outright.
|
|
98
|
+
def to_s(format: canonical_format, trademark: false, **opts)
|
|
97
99
|
# The mark goes after the code number, before the draft and the year
|
|
98
100
|
# ("ISO/IEC/IEEE P26511™/D8-2018"), so it is threaded into the
|
|
99
101
|
# format builders rather than appended to the finished string.
|
|
@@ -105,12 +107,14 @@ module Pubid
|
|
|
105
107
|
""
|
|
106
108
|
end
|
|
107
109
|
|
|
108
|
-
case format
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
result = case format
|
|
111
|
+
when :iso
|
|
112
|
+
to_iso_format(mark)
|
|
113
|
+
else
|
|
114
|
+
to_ieee_format(mark)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
annotate_plain_render(result, **opts)
|
|
114
118
|
end
|
|
115
119
|
|
|
116
120
|
private
|
|
@@ -9,12 +9,41 @@ module Pubid
|
|
|
9
9
|
# - "IEEE Std 1299/C62.22.1-1996" (same document, two numbers)
|
|
10
10
|
# - "IEEE Std 960-1989, Std 1177-1989" (same document, two numbers)
|
|
11
11
|
class MultiNumberedIdentifier < Identifier
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
attr_accessor
|
|
12
|
+
# Both designations are real lutaml attributes.
|
|
13
|
+
#
|
|
14
|
+
# They used to be `attr_accessor`s, which lutaml cannot see — so
|
|
15
|
+
# `to_hash` emitted {"_type" => "pubid:ieee:multi-numbered-identifier"}
|
|
16
|
+
# and NOTHING else, `from_hash` could not rebuild either member, and
|
|
17
|
+
# `#exclude` (which iterates self.class.attributes) skipped them. The
|
|
18
|
+
# whole identity was dropped. That is the CSA container defect recorded
|
|
19
|
+
# in CLAUDE.md, and the fix is the same: make the members attributes.
|
|
20
|
+
#
|
|
21
|
+
# The type is the CROSS-FLAVOR ::Pubid::Identifier, not IEEE's own:
|
|
22
|
+
# `polymorphic: true` widens only to subclasses, and the second
|
|
23
|
+
# designation may belong to another body — the same reason
|
|
24
|
+
# AdoptedStandard's members carry that type.
|
|
25
|
+
attribute :primary_identifier, ::Pubid::Identifier, polymorphic: true
|
|
26
|
+
attribute :secondary_identifier, ::Pubid::Identifier, polymorphic: true
|
|
15
27
|
|
|
16
|
-
#
|
|
17
|
-
|
|
28
|
+
# One document under two numbers, neither of them held here, so
|
|
29
|
+
# `root.number` was "". Walk to the primary designation.
|
|
30
|
+
def root
|
|
31
|
+
primary_identifier ? primary_identifier.root : self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Carry the number onto the URN and the MR slug as well as #root — see
|
|
35
|
+
# AdoptedStandard#code_obj.
|
|
36
|
+
def code_obj
|
|
37
|
+
primary_identifier&.code_obj
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# See AdoptedStandard#mr_year. `year` below already delegates, so this
|
|
41
|
+
# only stringifies — it is kept explicit so the hook survives if that
|
|
42
|
+
# delegation is ever removed in favour of the URN generator's
|
|
43
|
+
# `year_component` root fallback.
|
|
44
|
+
def mr_year
|
|
45
|
+
year&.to_s
|
|
46
|
+
end
|
|
18
47
|
|
|
19
48
|
def publisher
|
|
20
49
|
primary_identifier&.publisher
|
|
@@ -27,6 +56,29 @@ module Pubid
|
|
|
27
56
|
def year
|
|
28
57
|
primary_identifier&.year
|
|
29
58
|
end
|
|
59
|
+
|
|
60
|
+
# `publisher` and `year` are DERIVED from primary_identifier — and,
|
|
61
|
+
# since that member became a serialized attribute above, the derived
|
|
62
|
+
# values are now re-emitted after from_hash materializes the attribute
|
|
63
|
+
# defaults, while the parse path omits them as unset. That asymmetry
|
|
64
|
+
# breaks `from_hash(to_hash) == to_hash`, the gate relaton's index
|
|
65
|
+
# build uses to decide whether to keep a document.
|
|
66
|
+
#
|
|
67
|
+
# It is latent rather than live for the one corpus id (its primary is
|
|
68
|
+
# IEEE-published with no year, so both derived values match their
|
|
69
|
+
# defaults and are dropped anyway), but the class documents that its
|
|
70
|
+
# members may belong to another body — and a synthetic AIEE primary
|
|
71
|
+
# reproduces it immediately. Dropping the keys is lossless:
|
|
72
|
+
# primary_identifier rebuilds both. Same treatment as
|
|
73
|
+
# AdoptedStandard#to_hash and DualPublished#to_hash.
|
|
74
|
+
def to_hash(*args)
|
|
75
|
+
hash = super
|
|
76
|
+
return hash unless hash.is_a?(::Hash)
|
|
77
|
+
|
|
78
|
+
hash.delete("publisher")
|
|
79
|
+
hash.delete("year")
|
|
80
|
+
hash
|
|
81
|
+
end
|
|
30
82
|
end
|
|
31
83
|
end
|
|
32
84
|
end
|
|
@@ -88,10 +88,10 @@ module Pubid
|
|
|
88
88
|
#
|
|
89
89
|
# @param trademark [Boolean] append the IEEE trademark symbol (™/®)
|
|
90
90
|
# @return [String] String representation
|
|
91
|
-
def to_s(trademark: false)
|
|
91
|
+
def to_s(trademark: false, **opts)
|
|
92
92
|
result = ["IEEE Std", year, name_portion].compact.join(" ")
|
|
93
93
|
result += trademark_symbol if trademark
|
|
94
|
-
result
|
|
94
|
+
annotate_plain_render(result, **opts)
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# Trademark symbol for this document's own code. A NESC string starts
|
|
@@ -29,12 +29,12 @@ module Pubid
|
|
|
29
29
|
#
|
|
30
30
|
# @param trademark [Boolean] append the IEEE trademark symbol (™/®)
|
|
31
31
|
# @return [String] Draft format with optional month and year
|
|
32
|
-
def to_s(trademark: false)
|
|
32
|
+
def to_s(trademark: false, **opts)
|
|
33
33
|
parts = ["Draft National Electrical Safety Code"]
|
|
34
34
|
parts << ", #{month} #{year}" if month && year
|
|
35
35
|
result = parts.join
|
|
36
36
|
result += trademark_symbol if trademark
|
|
37
|
-
result
|
|
37
|
+
annotate_plain_render(result, **opts)
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|