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
|
@@ -16,15 +16,27 @@ module Pubid
|
|
|
16
16
|
# The exact slug printed after "OASIS " — always set. Drives `to_s`, so
|
|
17
17
|
# the printed form round-trips verbatim regardless of decomposition.
|
|
18
18
|
attribute :original, :string
|
|
19
|
-
# Best-effort decomposition (any may be nil). `
|
|
19
|
+
# Best-effort decomposition (any may be nil). `number`/`label` are plain
|
|
20
20
|
# slug fragments; `version`/`stage`/`part` carry the recognized fragment
|
|
21
21
|
# verbatim (e.g. "3.0", "v1.2.1", "PS01", "Errata01", "Pt8", "Part1").
|
|
22
|
-
|
|
22
|
+
#
|
|
23
|
+
# `number` holds the specification name ("OSLC-CM", "STIX", "amqp-core").
|
|
24
|
+
# It is the key relaton-index sorts and binary-searches on
|
|
25
|
+
# (`id.root.number.to_s`), and it deliberately CLUSTERS: every version,
|
|
26
|
+
# stage and part of one specification shares it, the same shape as an
|
|
27
|
+
# IETF draft slug or an IANA registry slug.
|
|
28
|
+
#
|
|
29
|
+
# `number`/`stage`/`part` intentionally override the inherited
|
|
30
|
+
# Components::Code / Components::Stage attributes with plain strings (the
|
|
31
|
+
# mechanism JIS uses for `number` and W3C for `date`): OASIS names,
|
|
32
|
+
# stages and parts are opaque tokens that must round-trip exactly and are
|
|
33
|
+
# never re-parsed as structured parts. Redefining an inherited attribute
|
|
34
|
+
# is only deterministic under multi-flavor load because this class body
|
|
35
|
+
# lives in ONE file and is never reopened, so lutaml has finished
|
|
36
|
+
# building the table before `Identifiers::Standard` snapshots it — DO NOT
|
|
37
|
+
# split this class across two files.
|
|
38
|
+
attribute :number, :string
|
|
23
39
|
attribute :version, :string
|
|
24
|
-
# `stage`/`part` intentionally override the inherited Components::Stage /
|
|
25
|
-
# Components::Code attributes with plain strings (same mechanism JIS uses
|
|
26
|
-
# for `number`, W3C for `date`): OASIS stages/parts are opaque tokens that
|
|
27
|
-
# must round-trip exactly and are never re-parsed as structured parts.
|
|
28
40
|
attribute :stage, :string
|
|
29
41
|
attribute :part, :string
|
|
30
42
|
attribute :label, :string
|
|
@@ -39,7 +51,7 @@ module Pubid
|
|
|
39
51
|
key_value do
|
|
40
52
|
map "_type", to: :_type, polymorphic_map: OASIS_TYPE_MAP
|
|
41
53
|
map "original", to: :original
|
|
42
|
-
map "
|
|
54
|
+
map "number", to: :number
|
|
43
55
|
map "version", to: :version
|
|
44
56
|
map "stage", to: :stage
|
|
45
57
|
map "part", to: :part
|
|
@@ -58,24 +70,90 @@ module Pubid
|
|
|
58
70
|
render(format: :human, **opts)
|
|
59
71
|
end
|
|
60
72
|
|
|
73
|
+
# The decomposition fields. Excluding any of them must also clear
|
|
74
|
+
# `original`, which still spells the excluded value out verbatim.
|
|
75
|
+
DECOMPOSITION_KEYS = %i[number version stage part label].freeze
|
|
76
|
+
|
|
77
|
+
# Widen a partial reference. `#matches?` is
|
|
78
|
+
# `exclude(*ignore) == other.exclude(*ignore)`, and `original` carries
|
|
79
|
+
# every component verbatim, so without this a bare "OASIS WSDM" could
|
|
80
|
+
# never match "OASIS WSDM-v1.1" however much the caller ignored.
|
|
81
|
+
#
|
|
82
|
+
# `original` is cleared ONLY when the exclusion touches the
|
|
83
|
+
# decomposition — the "reset the whole cluster" rule CSA applies to its
|
|
84
|
+
# year-format siblings. A plain `==` still compares `original`, so two
|
|
85
|
+
# slugs that decompose alike but print differently stay distinct: the
|
|
86
|
+
# decomposition loses fragment order and drops repeated fragments, so it
|
|
87
|
+
# is not by itself an identity.
|
|
88
|
+
def exclude(*args)
|
|
89
|
+
result = super
|
|
90
|
+
result.original = nil if args.intersect?(DECOMPOSITION_KEYS)
|
|
91
|
+
result
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# MR string hooks. `to_slug` delegates to `to_mr_string` and consumers
|
|
95
|
+
# use it as an output FILENAME, so the slug must be unique per document.
|
|
96
|
+
#
|
|
97
|
+
# The publisher lives in the PUBLISHER constant rather than the inherited
|
|
98
|
+
# lutaml attribute, so the base `mr_publisher` returns nil (the BIPM and
|
|
99
|
+
# IANA case) and is supplied here.
|
|
100
|
+
def mr_publisher
|
|
101
|
+
PUBLISHER.downcase
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The whole verbatim slug, not the decomposed fields: decomposition loses
|
|
105
|
+
# fragment order and drops repeated fragments, so "x-1.0-os-Pt1" and
|
|
106
|
+
# "x-1.0-Pt1-os" would assemble to one slug. `original` cannot collide.
|
|
107
|
+
def mr_number_with_part
|
|
108
|
+
mr_sanitize(original)
|
|
109
|
+
end
|
|
110
|
+
|
|
61
111
|
# from_hash is the shared polymorphic dispatch on Pubid::Identifier;
|
|
62
112
|
# OASIS_TYPE_MAP remains as the key_value polymorphic_map.
|
|
63
113
|
|
|
64
114
|
# Parse an OASIS identifier string into an identifier object
|
|
65
115
|
# @param identifier [String] The OASIS identifier string to parse
|
|
66
116
|
# @return [Identifier] The Standard identifier object
|
|
67
|
-
# @raise [
|
|
117
|
+
# @raise [Pubid::Errors::ParseError] If parsing fails
|
|
68
118
|
def self.parse(identifier)
|
|
69
119
|
# Reject pathological inputs before they reach the parser
|
|
70
120
|
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
121
|
+
unless identifier.is_a?(String)
|
|
122
|
+
raise Pubid::Errors::InvalidInputError,
|
|
123
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
124
|
+
end
|
|
125
|
+
|
|
71
126
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
72
|
-
raise
|
|
127
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
73
128
|
end
|
|
74
129
|
|
|
75
130
|
parsed = Parser.parse(identifier)
|
|
76
131
|
Builder.build(parsed)
|
|
77
|
-
|
|
78
|
-
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
# Filter by CHARSET, not by an enumerated escape list, so a field added
|
|
137
|
+
# later cannot leak an unsafe character (the BIPM `mr_slug` precedent).
|
|
138
|
+
# Three characters need it today: the "." in every version —
|
|
139
|
+
# Renderers::MrString joins SEGMENTS with ".", so a dot inside one breaks
|
|
140
|
+
# the documented segment structure — plus the space and "]" of a few
|
|
141
|
+
# malformed records.
|
|
142
|
+
#
|
|
143
|
+
# A RUN of non-alphanumerics collapses to one "-", which is why "-" is
|
|
144
|
+
# outside the kept set (BIPM's form, not ETSI's): "v3.0]-PS01" would
|
|
145
|
+
# otherwise print a bare "--".
|
|
146
|
+
#
|
|
147
|
+
# Caveat, the same one BIPM records: "-" is both the intra-slug join and
|
|
148
|
+
# the substitute, so two slugs differing ONLY in which non-slug character
|
|
149
|
+
# they use collapse onto one MR string. The corpus has exactly one such
|
|
150
|
+
# pair, the malformed "OpenC2-MQTT-v1.0] -CS01" spelled once with a
|
|
151
|
+
# normal space and once with a non-breaking one — two spellings of one
|
|
152
|
+
# document. Every genuinely distinct identifier keeps its own slug.
|
|
153
|
+
def mr_sanitize(value)
|
|
154
|
+
slug = value.to_s.downcase.gsub(/[^a-z0-9]+/, "-")
|
|
155
|
+
.gsub(/\A-+|-+\z/, "")
|
|
156
|
+
slug.empty? ? nil : slug
|
|
79
157
|
end
|
|
80
158
|
end
|
|
81
159
|
end
|
data/lib/pubid/oasis/parser.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Pubid
|
|
|
16
16
|
# Builder with order-independent fragment classification. Keeping
|
|
17
17
|
# decomposition out of the PEG avoids brittle backtracking and guarantees a
|
|
18
18
|
# lossless round-trip.
|
|
19
|
-
class Parser <
|
|
19
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
20
20
|
rule(:prefix) { str("OASIS") >> str(" ") }
|
|
21
21
|
|
|
22
22
|
# The whole slug, captured verbatim (any character, incl. spaces / "]").
|
data/lib/pubid/oasis.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pubid"
|
|
3
4
|
module Pubid
|
|
4
5
|
module Oasis
|
|
5
6
|
extend Pubid::PrefixesSupport
|
|
@@ -21,8 +22,13 @@ module Pubid
|
|
|
21
22
|
def self.parse(identifier)
|
|
22
23
|
# Reject pathological inputs before they reach the parser
|
|
23
24
|
# (CodeQL rb/polynomial-redos barrier — inline .length by design).
|
|
25
|
+
unless identifier.is_a?(String)
|
|
26
|
+
raise Pubid::Errors::InvalidInputError,
|
|
27
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
25
|
-
raise
|
|
31
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
26
32
|
end
|
|
27
33
|
|
|
28
34
|
Identifier.parse(identifier)
|
data/lib/pubid/ogc/identifier.rb
CHANGED
|
@@ -61,16 +61,20 @@ module Pubid
|
|
|
61
61
|
# Parse an OGC identifier string into an identifier object.
|
|
62
62
|
# @param identifier [String] The OGC identifier string to parse
|
|
63
63
|
# @return [Identifier] The document identifier object
|
|
64
|
-
# @raise [
|
|
65
|
-
#
|
|
64
|
+
# @raise [Pubid::Errors::InvalidInputError]
|
|
65
|
+
# If the input exceeds the maximum length
|
|
66
|
+
# @raise [Pubid::Errors::ParseError] If parsing fails
|
|
66
67
|
def self.parse(identifier)
|
|
68
|
+
unless identifier.is_a?(String)
|
|
69
|
+
raise Pubid::Errors::InvalidInputError,
|
|
70
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
71
|
+
end
|
|
72
|
+
|
|
67
73
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
68
|
-
raise
|
|
74
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
Builder.build(Parser.parse(identifier))
|
|
72
|
-
rescue Parslet::ParseFailed => e
|
|
73
|
-
raise "Failed to parse OGC identifier '#{identifier}': #{e.message}"
|
|
74
78
|
end
|
|
75
79
|
end
|
|
76
80
|
end
|
data/lib/pubid/ogc/parser.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Pubid
|
|
|
12
12
|
# leniency, though the canonical printed form omits it.
|
|
13
13
|
#
|
|
14
14
|
# Examples: "25-023", "24-032r1", "01-009a", "04-095c1", "OGC 24-032r1".
|
|
15
|
-
class Parser <
|
|
15
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
16
16
|
rule(:space) { match["\\s"].repeat(1) }
|
|
17
17
|
rule(:digits) { match["0-9"].repeat(1) }
|
|
18
18
|
|
data/lib/pubid/ogc.rb
CHANGED
data/lib/pubid/oiml/builder.rb
CHANGED
|
@@ -152,7 +152,11 @@ module Pubid
|
|
|
152
152
|
code_attrs[:suffix] = parsed_hash[:code_suffix].to_s
|
|
153
153
|
code_attrs[:space_suffix] = true if parsed_hash.key?(:space_suffix)
|
|
154
154
|
end
|
|
155
|
-
|
|
155
|
+
# The code fields are flat index columns on the leaf (see
|
|
156
|
+
# Identifiers::CodeNumber) — `number` is what relaton-index keys on —
|
|
157
|
+
# so they are assigned individually rather than as a Code object.
|
|
158
|
+
# Bulletin has no code columns and never reaches this branch.
|
|
159
|
+
code_attrs.each { |name, value| identifier.public_send(:"#{name}=", value) }
|
|
156
160
|
end
|
|
157
161
|
|
|
158
162
|
# Handle other attributes
|
|
@@ -224,13 +228,13 @@ module Pubid
|
|
|
224
228
|
article_id = parsed_hash[:article_id].to_s
|
|
225
229
|
identifier.date ||= Pubid::Components::Date.new
|
|
226
230
|
identifier.date.year = article_id[0, 4]
|
|
227
|
-
identifier.
|
|
231
|
+
identifier.number = article_id[4, 2]
|
|
228
232
|
identifier.sequence = article_id[6, 2]
|
|
229
233
|
warn_on_volume_mismatch(identifier, parsed_hash[:volume_roman])
|
|
230
234
|
return
|
|
231
235
|
end
|
|
232
236
|
|
|
233
|
-
identifier.
|
|
237
|
+
identifier.number = parsed_hash[:issue].to_s if parsed_hash[:issue]
|
|
234
238
|
identifier.sequence = parsed_hash[:sequence].to_s if parsed_hash[:sequence]
|
|
235
239
|
end
|
|
236
240
|
|
|
@@ -33,18 +33,48 @@ module Pubid
|
|
|
33
33
|
# carried in the structured form and the roman volume in citations.
|
|
34
34
|
BASE_YEAR_OFFSET = 1959
|
|
35
35
|
|
|
36
|
-
#
|
|
37
|
-
# for the online-bulletin series). Always 2 digits.
|
|
38
|
-
|
|
36
|
+
# The issue: the zero-padded number within the volume ("01".."04",
|
|
37
|
+
# plus "07"/"10" for the online-bulletin series). Always 2 digits. The
|
|
38
|
+
# year is the volume and the issue is the number, as in the citation
|
|
39
|
+
# form "LXVII(2)".
|
|
40
|
+
#
|
|
41
|
+
# Declared as `number`, so it is the relaton index key
|
|
42
|
+
# (`id.root.number.to_s`) and every index row with an issue shows a
|
|
43
|
+
# `number`. The key puts the same issue number of all volumes in one
|
|
44
|
+
# bucket; the MR slug keeps each article distinct.
|
|
45
|
+
#
|
|
46
|
+
# Declared on this LEAF, which has no subclasses. It redefines the
|
|
47
|
+
# `Components::Code number` of ::Pubid::Identifier as a :string, and a
|
|
48
|
+
# redefinition on a class that other classes inherit is the
|
|
49
|
+
# multi-flavor determinism landmine (see Identifiers::CodeNumber).
|
|
50
|
+
#
|
|
51
|
+
# nil for a volume ("OIML Bulletin 1960") and for the bare periodical
|
|
52
|
+
# reference "OIML Bulletin", which name no issue.
|
|
53
|
+
attribute :number, :string
|
|
39
54
|
# Zero-padded sequence within the issue ("00" = editorial, "01"+ for
|
|
40
55
|
# articles). Always 2 digits.
|
|
41
56
|
attribute :sequence, :string
|
|
42
57
|
|
|
43
58
|
key_value do
|
|
44
|
-
map "
|
|
59
|
+
map "number", to: :number
|
|
45
60
|
map "sequence", to: :sequence
|
|
46
61
|
end
|
|
47
62
|
|
|
63
|
+
# The inherited hook reads through `code`, which Bulletin does not
|
|
64
|
+
# have, so it would return nil and collapse every article of a year
|
|
65
|
+
# onto `oiml.bulletin.<year>`; `to_slug` is an output FILENAME, so that
|
|
66
|
+
# is an overwrite. Emit the rest of the locator instead.
|
|
67
|
+
#
|
|
68
|
+
# The year is deliberately NOT included: Renderers::MrString already
|
|
69
|
+
# gives it its own segment (`mr_year`), so repeating it here would
|
|
70
|
+
# render `oiml.bulletin.1960-03-01.1960`.
|
|
71
|
+
def mr_number_with_part
|
|
72
|
+
segments = [number, sequence].compact
|
|
73
|
+
return nil if segments.empty?
|
|
74
|
+
|
|
75
|
+
segments.join("-")
|
|
76
|
+
end
|
|
77
|
+
|
|
48
78
|
def type_string
|
|
49
79
|
"Bulletin"
|
|
50
80
|
end
|
|
@@ -60,18 +90,18 @@ module Pubid
|
|
|
60
90
|
# Volume as a roman-numeral string ("LXVII"), derived from the year.
|
|
61
91
|
# nil when the year is absent.
|
|
62
92
|
def volume_roman
|
|
63
|
-
|
|
64
|
-
return nil unless
|
|
93
|
+
volume = volume_arabic&.to_i
|
|
94
|
+
return nil unless volume&.positive?
|
|
65
95
|
|
|
66
|
-
self.class.to_roman(
|
|
96
|
+
self.class.to_roman(volume)
|
|
67
97
|
end
|
|
68
98
|
|
|
69
99
|
# 8-digit oiml.org article id ("20260211"). Composed by concatenating
|
|
70
|
-
# year + issue + sequence. nil unless all three are present.
|
|
100
|
+
# year + issue (number) + sequence. nil unless all three are present.
|
|
71
101
|
def article_id
|
|
72
|
-
return nil unless date&.year &&
|
|
102
|
+
return nil unless date&.year && number && sequence
|
|
73
103
|
|
|
74
|
-
"#{date.year}#{
|
|
104
|
+
"#{date.year}#{number}#{sequence}"
|
|
75
105
|
end
|
|
76
106
|
|
|
77
107
|
class << self
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Oiml
|
|
5
|
+
module Identifiers
|
|
6
|
+
# Installs the flat, index-friendly code columns and their serialization
|
|
7
|
+
# on the seven concrete OIML document leaves (Recommendation, Document,
|
|
8
|
+
# Vocabulary, Guide, BasicPublication, ExpertReport, SeminarReport).
|
|
9
|
+
#
|
|
10
|
+
# Why the leaves and not Pubid::Oiml::SingleIdentifier, which they all
|
|
11
|
+
# inherit from: `number` redefines the parent ::Pubid::Identifier's
|
|
12
|
+
# `attribute :number, Components::Code` as a plain :string (and `part` /
|
|
13
|
+
# `subpart` likewise). Declaring that on a class the concrete types
|
|
14
|
+
# INHERIT from resolves against the parent definition nondeterministically
|
|
15
|
+
# under multi-flavor load — it passes an OIML-only run and can flip
|
|
16
|
+
# `root.number` to "" under the full suite (the IEEE lesson; see
|
|
17
|
+
# lib/pubid/ieee/identifiers/code_number.rb and CLAUDE.md). Declaring on
|
|
18
|
+
# each leaf removes the ambiguity at the point of use.
|
|
19
|
+
#
|
|
20
|
+
# This matters because relaton-index sorts and bsearches every row on
|
|
21
|
+
# `id.root.number.to_s`. OIML kept the code in an Oiml::Components::Code
|
|
22
|
+
# under a `code` attribute and never set `number`, so all 12,226 lines of
|
|
23
|
+
# the published relaton-data-oiml index-v2 keyed "".
|
|
24
|
+
#
|
|
25
|
+
# The serialized hash ALREADY had these as bare top-level scalars — the
|
|
26
|
+
# old converters merely read them through `code` — so the wire format is
|
|
27
|
+
# byte-identical and that index needs no regeneration.
|
|
28
|
+
#
|
|
29
|
+
# Bulletin deliberately does NOT include this module. It carries no code
|
|
30
|
+
# at all (its locator is the year/issue/sequence tuple), so it would only
|
|
31
|
+
# gain permanently-nil part/subpart/suffix columns. It declares its own
|
|
32
|
+
# `number` (the issue) instead; see bulletin.rb.
|
|
33
|
+
module CodeNumber
|
|
34
|
+
def self.included(base)
|
|
35
|
+
install_attributes(base)
|
|
36
|
+
install_mappings(base)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.install_attributes(base)
|
|
40
|
+
# Bare document number ("144"), the relaton index key. The part is a
|
|
41
|
+
# sibling column, never folded in, so every part of a document shares
|
|
42
|
+
# one bucket and a part-less reference finds them all.
|
|
43
|
+
base.attribute :number, :string
|
|
44
|
+
base.attribute :part, :string
|
|
45
|
+
base.attribute :subpart, :string
|
|
46
|
+
# Free-form trailing suffix glued to the code, e.g. "sup", "A",
|
|
47
|
+
# "erratum", "GUM 1", "ISO3930". Preserved verbatim for round-trip.
|
|
48
|
+
base.attribute :suffix, :string
|
|
49
|
+
# When true the suffix is space-separated ("D 1 Brochure") rather
|
|
50
|
+
# than the default dash ("R 60-sup"). Named for the RARE case with a
|
|
51
|
+
# false default, so the canonical to_hash drops it from every
|
|
52
|
+
# ordinary row.
|
|
53
|
+
base.attribute :space_suffix, :boolean, default: -> { false }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Merged by lutaml with the block SingleIdentifier declares, which
|
|
57
|
+
# carries publisher/year/edition/stage/iteration.
|
|
58
|
+
def self.install_mappings(base)
|
|
59
|
+
base.key_value do
|
|
60
|
+
map "number", to: :number
|
|
61
|
+
map "part", to: :part
|
|
62
|
+
map "subpart", to: :subpart
|
|
63
|
+
map "suffix", to: :suffix
|
|
64
|
+
map "space_suffix", to: :space_suffix
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The composed document code, rebuilt on demand from the split columns
|
|
69
|
+
# so the renderer and the URN generator keep one place to ask for the
|
|
70
|
+
# printed form ("144-1", "60-sup"). Deliberately NOT an attribute and
|
|
71
|
+
# NOT memoised: the columns are writable (the base #exclude rebuilds
|
|
72
|
+
# through them), so a cached Code would go stale.
|
|
73
|
+
#
|
|
74
|
+
# nil when there is no number, preserving the old nil-`code` semantics
|
|
75
|
+
# the URN generator branches on.
|
|
76
|
+
def code
|
|
77
|
+
return nil if number.nil?
|
|
78
|
+
|
|
79
|
+
Components::Code.new(
|
|
80
|
+
number: number,
|
|
81
|
+
part: part,
|
|
82
|
+
subpart: subpart,
|
|
83
|
+
suffix: suffix,
|
|
84
|
+
space_suffix: space_suffix,
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -7,6 +7,7 @@ module Pubid
|
|
|
7
7
|
autoload :Annex, "#{__dir__}/identifiers/annex"
|
|
8
8
|
autoload :BasicPublication, "#{__dir__}/identifiers/basic_publication"
|
|
9
9
|
autoload :Bulletin, "#{__dir__}/identifiers/bulletin"
|
|
10
|
+
autoload :CodeNumber, "#{__dir__}/identifiers/code_number"
|
|
10
11
|
autoload :Document, "#{__dir__}/identifiers/document"
|
|
11
12
|
autoload :Errata, "#{__dir__}/identifiers/errata"
|
|
12
13
|
autoload :ExpertReport, "#{__dir__}/identifiers/expert_report"
|
data/lib/pubid/oiml/parser.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "parslet"
|
|
|
4
4
|
|
|
5
5
|
module Pubid
|
|
6
6
|
module Oiml
|
|
7
|
-
class Parser <
|
|
7
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
8
8
|
include ::Pubid::Parser::CommonParseRules
|
|
9
9
|
include ::Pubid::Parser::CommonParseMethods
|
|
10
10
|
|
|
@@ -122,9 +122,14 @@ module Pubid
|
|
|
122
122
|
).as(:edition_format) # Wrap entire match to capture that Edition was used
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
-
# Date - year after colon
|
|
125
|
+
# Date - year after colon, the VIM's paren-year form ("OIML V 2-200
|
|
126
|
+
# (2000)" — space + (YYYY) instead of :YYYY, the shape #342 flags as
|
|
127
|
+
# the one real-world spelling that did not parse), OR edition portion
|
|
128
|
+
# (with optional space before year)
|
|
126
129
|
rule(:date) do
|
|
127
|
-
edition_portion |
|
|
130
|
+
edition_portion |
|
|
131
|
+
(colon >> space.maybe >> year_digits.as(:year)) |
|
|
132
|
+
(space.maybe >> lparen >> year_digits.as(:year) >> rparen)
|
|
128
133
|
end
|
|
129
134
|
|
|
130
135
|
# Draft stage - WD or CD with optional iteration
|
data/lib/pubid/oiml/renderer.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Pubid
|
|
|
65
65
|
result = "#{id.publisher} Bulletin"
|
|
66
66
|
if id.date&.year
|
|
67
67
|
result += " #{id.date.year}"
|
|
68
|
-
result += "-#{id.
|
|
68
|
+
result += "-#{id.number}" if id.number
|
|
69
69
|
result += "-#{id.sequence}" if id.sequence
|
|
70
70
|
end
|
|
71
71
|
result += " (#{id.language})" if id.language
|
|
@@ -77,9 +77,9 @@ module Pubid
|
|
|
77
77
|
# structured since OIML's citation format doesn't define volume-only
|
|
78
78
|
# or issue-only variants.
|
|
79
79
|
def render_bulletin_citation(id)
|
|
80
|
-
return render_bulletin_structured(id) unless id.date&.year && id.
|
|
80
|
+
return render_bulletin_structured(id) unless id.date&.year && id.number && id.sequence
|
|
81
81
|
|
|
82
|
-
"#{id.publisher} Bulletin #{id.volume_roman}(#{id.
|
|
82
|
+
"#{id.publisher} Bulletin #{id.volume_roman}(#{id.number.to_i}) #{id.article_id}"
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def effective_format(id)
|
|
@@ -5,7 +5,6 @@ module Pubid
|
|
|
5
5
|
class SingleIdentifier < Identifier
|
|
6
6
|
# Base class for OIML single identifiers (non-supplements)
|
|
7
7
|
attribute :publisher, :string
|
|
8
|
-
attribute :code, Oiml::Components::Code
|
|
9
8
|
attribute :date, Pubid::Components::Date
|
|
10
9
|
attribute :edition, :string
|
|
11
10
|
attribute :stage, :string
|
|
@@ -16,46 +15,24 @@ module Pubid
|
|
|
16
15
|
} # Track parsed format
|
|
17
16
|
|
|
18
17
|
# Serialization delta on top of Oiml::Identifier's shared block. The
|
|
19
|
-
# `
|
|
20
|
-
#
|
|
21
|
-
# (
|
|
22
|
-
#
|
|
18
|
+
# `date` (year) component is flattened to a top-level key rather than a
|
|
19
|
+
# nested hash, mirroring ISO (lib/pubid/iso/identifier.rb). `type` is
|
|
20
|
+
# intentionally omitted (recomputed from the class on load).
|
|
21
|
+
#
|
|
22
|
+
# The code columns (number/part/subpart/suffix/space_suffix) are NOT
|
|
23
|
+
# here: they are declared, and mapped, by Identifiers::CodeNumber on each
|
|
24
|
+
# concrete leaf, because redefining the inherited `number` on this class
|
|
25
|
+
# — which every leaf inherits — is the multi-flavor determinism landmine.
|
|
26
|
+
# Keeping the mapping with the attribute is also what lets Bulletin, the
|
|
27
|
+
# one leaf with no code, declare its own `number` (the issue) and map it.
|
|
23
28
|
key_value do
|
|
24
29
|
map "publisher", to: :publisher
|
|
25
|
-
map "number", with: { to: :number_to_kv, from: :number_from_kv }
|
|
26
|
-
map "part", with: { to: :part_to_kv, from: :part_from_kv }
|
|
27
|
-
map "subpart", with: { to: :subpart_to_kv, from: :subpart_from_kv }
|
|
28
|
-
map "suffix", with: { to: :suffix_to_kv, from: :suffix_from_kv }
|
|
29
|
-
map "space_suffix",
|
|
30
|
-
with: { to: :space_suffix_to_kv, from: :space_suffix_from_kv }
|
|
31
30
|
map "year", with: { to: :year_to_kv, from: :year_from_kv }
|
|
32
31
|
map "edition", to: :edition
|
|
33
32
|
map "stage", to: :stage
|
|
34
33
|
map "iteration", to: :iteration
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
# --- code components flattened to top-level keys ---
|
|
38
|
-
def number_to_kv(model, doc) = emit_kv(doc, "number", model.code&.number)
|
|
39
|
-
def number_from_kv(model, value) = code_for(model).number = value.to_s
|
|
40
|
-
def part_to_kv(model, doc) = emit_kv(doc, "part", model.code&.part)
|
|
41
|
-
def part_from_kv(model, value) = code_for(model).part = value.to_s
|
|
42
|
-
def subpart_to_kv(model, doc) = emit_kv(doc, "subpart", model.code&.subpart)
|
|
43
|
-
def subpart_from_kv(model, value) = code_for(model).subpart = value.to_s
|
|
44
|
-
def suffix_to_kv(model, doc) = emit_kv(doc, "suffix", model.code&.suffix)
|
|
45
|
-
def suffix_from_kv(model, value) = code_for(model).suffix = value.to_s
|
|
46
|
-
|
|
47
|
-
def space_suffix_to_kv(model, doc)
|
|
48
|
-
return unless model.code&.space_suffix
|
|
49
|
-
|
|
50
|
-
doc.add_child(
|
|
51
|
-
Lutaml::KeyValue::DataModel::Element.new("space_suffix", true),
|
|
52
|
-
)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def space_suffix_from_kv(model, value)
|
|
56
|
-
code_for(model).space_suffix = value
|
|
57
|
-
end
|
|
58
|
-
|
|
59
36
|
# --- date flattened to a top-level year ---
|
|
60
37
|
def year_to_kv(model, doc) = emit_kv(doc, "year", model.date&.year)
|
|
61
38
|
|
|
@@ -69,10 +46,6 @@ module Pubid
|
|
|
69
46
|
doc.add_child(Lutaml::KeyValue::DataModel::Element.new(key, value.to_s))
|
|
70
47
|
end
|
|
71
48
|
|
|
72
|
-
def code_for(model)
|
|
73
|
-
model.code ||= Components::Code.new
|
|
74
|
-
end
|
|
75
|
-
|
|
76
49
|
attr_reader :requested_format
|
|
77
50
|
|
|
78
51
|
# Type is determined by the subclass
|
|
@@ -103,11 +76,15 @@ module Pubid
|
|
|
103
76
|
raise NotImplementedError, "Subclasses must implement type_string"
|
|
104
77
|
end
|
|
105
78
|
|
|
106
|
-
# OIML keeps identity in
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
#
|
|
79
|
+
# OIML keeps identity in the code columns and `type_string` (e.g. "R",
|
|
80
|
+
# "V", "D"), not in the inherited `typed_stage` — the generic MrString
|
|
81
|
+
# renderer would otherwise drop both and produce `OIML.<year>`.
|
|
82
|
+
# Losslessness for issue #142 requires the type letter and document
|
|
83
|
+
# number to appear in MR.
|
|
84
|
+
#
|
|
85
|
+
# Reads through `code`, which every code-bearing leaf composes from its
|
|
86
|
+
# split columns (Identifiers::CodeNumber); Bulletin has no code and
|
|
87
|
+
# returns nil here, keeping its (year, issue, sequence) slug.
|
|
111
88
|
def mr_number_with_part
|
|
112
89
|
segments = []
|
|
113
90
|
segments << code&.number&.to_s if code&.number
|
|
@@ -119,6 +96,13 @@ module Pubid
|
|
|
119
96
|
segments.join("-")
|
|
120
97
|
end
|
|
121
98
|
|
|
99
|
+
# Bulletin overrides `code`; every other leaf gets it from
|
|
100
|
+
# Identifiers::CodeNumber. Returning nil here keeps #== , the renderer
|
|
101
|
+
# and the URN generator total for the abstract class itself.
|
|
102
|
+
def code
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
|
|
122
106
|
def mr_type
|
|
123
107
|
type_string&.downcase
|
|
124
108
|
end
|