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/bipm/builder.rb
CHANGED
|
@@ -30,6 +30,8 @@ module Pubid
|
|
|
30
30
|
build_si_brochure(data[:si_brochure])
|
|
31
31
|
elsif data[:si_brochure_variant]
|
|
32
32
|
build_si_brochure_variant(data[:si_brochure_variant])
|
|
33
|
+
elsif data.key?(:si_brochure_section)
|
|
34
|
+
build_si_brochure_section(data[:si_brochure_section])
|
|
33
35
|
elsif data[:mep]
|
|
34
36
|
build_mep(data[:mep])
|
|
35
37
|
elsif data[:guide]
|
|
@@ -41,61 +43,115 @@ module Pubid
|
|
|
41
43
|
|
|
42
44
|
private
|
|
43
45
|
|
|
46
|
+
# `group` and `language` are normalized here, so a historic committee
|
|
47
|
+
# name (CCDS) and a two-letter language code (EN/FR) never reach an
|
|
48
|
+
# attribute — the index stores only the current name and the one-letter
|
|
49
|
+
# code BIPM prints.
|
|
44
50
|
def build_committee(node, form:, language: nil)
|
|
45
51
|
Identifiers::CommitteeDocument.new(
|
|
46
|
-
group: node[:group]
|
|
52
|
+
group: Identifier.normalize_group(node[:group]),
|
|
47
53
|
type_code: Identifier::TYPE_WORD_TO_CODE[node[:type_word].to_s],
|
|
48
54
|
number: node[:number]&.to_s,
|
|
49
55
|
year: node[:year]&.to_s&.to_i,
|
|
50
|
-
language: language || node[:language]
|
|
56
|
+
language: Identifier.normalize_language(language || node[:language]),
|
|
51
57
|
form: form,
|
|
52
58
|
)
|
|
53
59
|
end
|
|
54
60
|
|
|
55
61
|
def build_meeting(node, language: nil)
|
|
56
62
|
Identifiers::Meeting.new(
|
|
57
|
-
group: node[:group]
|
|
63
|
+
group: Identifier.normalize_group(node[:group]),
|
|
58
64
|
number: node[:number].to_s,
|
|
59
65
|
year: node[:year]&.to_s&.to_i,
|
|
60
|
-
language: language || node[:language]
|
|
66
|
+
language: Identifier.normalize_language(language || node[:language]),
|
|
61
67
|
)
|
|
62
68
|
end
|
|
63
69
|
|
|
70
|
+
# `number` is the volume, so every article of a volume clusters into one
|
|
71
|
+
# relaton-index bucket (the IETF draft-slug / IANA registry-slug
|
|
72
|
+
# convention). It is nil only for the journal-level record, which carries
|
|
73
|
+
# no volume at all.
|
|
74
|
+
#
|
|
75
|
+
# It is deliberately redundant with `volume`, which stays because the
|
|
76
|
+
# renderer and the URN generator read it. Two limits of that redundancy,
|
|
77
|
+
# both accepted rather than engineered around (see the note above
|
|
78
|
+
# NUMBER_SOURCE_ATTRIBUTES in identifier.rb for the half that IS
|
|
79
|
+
# handled):
|
|
80
|
+
#
|
|
81
|
+
# * THE BUILDER IS THE CONSTRUCTOR OF RECORD. A caller that bypasses it
|
|
82
|
+
# — `MetrologiaArticle.new(volume: 51, …)` — gets a nil `number` and
|
|
83
|
+
# so an empty index key. Deriving it in `initialize` instead would
|
|
84
|
+
# cover that, but `#exclude` rebuilds through `self.class.new`, so it
|
|
85
|
+
# would also silently re-fill a `number` the caller just excluded.
|
|
86
|
+
# * NO SELF-HEALING ACROSS from_hash. lutaml assigns attributes AFTER
|
|
87
|
+
# `initialize`, so a legacy pre-`number` index row (one carrying only
|
|
88
|
+
# `volume`) deserializes with `number` nil and no error at all —
|
|
89
|
+
# lutaml ignores unknown keys and relaton's `id_supported?` skips its
|
|
90
|
+
# round-trip check for concrete subclasses, which every BIPM id is.
|
|
91
|
+
# relaton-data-bipm must regenerate index-v2 to gain the key. This is
|
|
92
|
+
# weaker than the IEEE `CodeNumber` mixin, which rebuilds `code_obj`
|
|
93
|
+
# from its split columns after `from_hash`.
|
|
64
94
|
def build_metrologia(node)
|
|
65
95
|
node = {} unless node.is_a?(Hash)
|
|
66
96
|
Identifiers::MetrologiaArticle.new(
|
|
67
|
-
|
|
97
|
+
number: node[:volume]&.to_s,
|
|
68
98
|
issue: node[:issue]&.to_s,
|
|
69
99
|
article: node[:article]&.to_s,
|
|
70
100
|
)
|
|
71
101
|
end
|
|
72
102
|
|
|
103
|
+
# The SI Brochure has no document number of its own, so the edition is
|
|
104
|
+
# the index key — it clusters the English and French records of one
|
|
105
|
+
# edition. The grammar makes `edition` mandatory here, so it is never nil.
|
|
73
106
|
def build_si_brochure(node)
|
|
74
107
|
Identifiers::SiBrochure.new(
|
|
108
|
+
number: node[:edition].to_s,
|
|
75
109
|
edition: node[:edition].to_s,
|
|
76
110
|
version: node[:version].to_s,
|
|
77
111
|
years: node[:years].to_s,
|
|
78
|
-
language: node[:language]
|
|
112
|
+
language: Identifier.normalize_language(node[:language]),
|
|
79
113
|
)
|
|
80
114
|
end
|
|
81
115
|
|
|
116
|
+
# The derived products (Appendix N, Concise, FAQ) carry no edition, so
|
|
117
|
+
# the variant name is their key. The grammar makes it mandatory here.
|
|
82
118
|
def build_si_brochure_variant(node)
|
|
83
|
-
|
|
119
|
+
variant = node[:variant].to_s
|
|
120
|
+
Identifiers::SiBrochure.new(number: variant, variant: variant)
|
|
84
121
|
end
|
|
85
122
|
|
|
123
|
+
# A bare or sectioned reference names no edition, so it gets no key: it is
|
|
124
|
+
# a partial reference that wildcards every edition. The bare form captures
|
|
125
|
+
# nothing, so the parser hands back a slice rather than a hash.
|
|
126
|
+
def build_si_brochure_section(node)
|
|
127
|
+
node = {} unless node.is_a?(Hash)
|
|
128
|
+
Identifiers::SiBrochure.new(part: node[:part]&.to_s)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# The Appendix/Annex/Part tail is the full-content spelling of the SAME
|
|
132
|
+
# document, so it stays out of the key.
|
|
86
133
|
def build_mep(node)
|
|
87
134
|
Identifiers::Mep.new(
|
|
88
|
-
|
|
89
|
-
report_code: node[:report_code]&.to_s,
|
|
135
|
+
**mep_codes(node),
|
|
90
136
|
appendix: node[:appendix]&.to_s,
|
|
91
137
|
annex: node[:annex]&.to_s,
|
|
92
138
|
part: node[:part]&.to_s,
|
|
93
139
|
)
|
|
94
140
|
end
|
|
95
141
|
|
|
142
|
+
# A MEP is identified by its unit code, or by the report code for the
|
|
143
|
+
# `Rapport BIPM-YYYY/NN` variant; exactly one of the two is set, and
|
|
144
|
+
# whichever it is becomes the relaton index key.
|
|
145
|
+
def mep_codes(node)
|
|
146
|
+
mep_code = node[:mep_code]&.to_s
|
|
147
|
+
report_code = node[:report_code]&.to_s
|
|
148
|
+
{ number: mep_code || report_code, mep_code: mep_code,
|
|
149
|
+
report_code: report_code }
|
|
150
|
+
end
|
|
151
|
+
|
|
96
152
|
def build_guide(node)
|
|
97
153
|
Identifiers::Guide.new(
|
|
98
|
-
group: node[:group]
|
|
154
|
+
group: Identifier.normalize_group(node[:group]),
|
|
99
155
|
guide_kind: node[:guide_kind].to_s,
|
|
100
156
|
number: node[:number].to_s,
|
|
101
157
|
appendix: node[:appendix]&.to_s,
|
|
@@ -19,6 +19,19 @@ module Pubid
|
|
|
19
19
|
CIPM CGPM JCRB CCTF CCQM CCT CCL CCAUV CCU CCM CCEM CCPR CCRI
|
|
20
20
|
].freeze
|
|
21
21
|
|
|
22
|
+
# Historic committee names consumer references still use. BIPM renamed the
|
|
23
|
+
# CCDS (Comité Consultatif pour la Définition de la Seconde) to CCTF in
|
|
24
|
+
# 1997 and the index keys the current name, so an alias is resolved at
|
|
25
|
+
# parse time and never stored. Extend the map, not the parser, to add one.
|
|
26
|
+
GROUP_ALIASES = { "CCDS" => "CCTF" }.freeze
|
|
27
|
+
|
|
28
|
+
# Every group token the grammar accepts, current names and aliases alike.
|
|
29
|
+
PARSEABLE_GROUPS = (GROUPS + GROUP_ALIASES.keys).freeze
|
|
30
|
+
|
|
31
|
+
# Two-letter codes consumer references use for the one-letter language
|
|
32
|
+
# codes BIPM prints. Resolved at parse time, so only "E"/"F" is stored.
|
|
33
|
+
LANGUAGE_ALIASES = { "EN" => "E", "FR" => "F" }.freeze
|
|
34
|
+
|
|
22
35
|
# Committee document type codes and their printed long-form names. Note
|
|
23
36
|
# DECL prints as "Statement" in BOTH languages in the source data.
|
|
24
37
|
TYPE_CODES = %w[REC RES DECN ACT DECL].freeze
|
|
@@ -30,12 +43,20 @@ module Pubid
|
|
|
30
43
|
"REC" => "Recommandation", "RES" => "Résolution",
|
|
31
44
|
"DECN" => "Décision", "ACT" => "Action", "DECL" => "Statement"
|
|
32
45
|
}.freeze
|
|
33
|
-
#
|
|
46
|
+
# Printed type words that are not the canonical name of their code. BIPM
|
|
47
|
+
# prints DECL as "Statement" in both languages, but a reference spells the
|
|
48
|
+
# word out; without these the parser matched "Declaration" and then mapped
|
|
49
|
+
# it to NO code, so the renderer emitted a corrupt "CGPM 1 (1971)".
|
|
50
|
+
TYPE_WORD_ALIASES = {
|
|
51
|
+
"Declaration" => "DECL", "Déclaration" => "DECL"
|
|
52
|
+
}.freeze
|
|
53
|
+
|
|
54
|
+
# Every printed type word (abbrev + English + French + alias) → code.
|
|
34
55
|
TYPE_WORD_TO_CODE = TYPE_CODES.each_with_object({}) do |code, map|
|
|
35
56
|
map[code] = code
|
|
36
57
|
map[TYPE_NAME_EN[code]] = code
|
|
37
58
|
map[TYPE_NAME_FR[code]] = code
|
|
38
|
-
end.freeze
|
|
59
|
+
end.merge(TYPE_WORD_ALIASES).freeze
|
|
39
60
|
|
|
40
61
|
# Shared attributes (flat). Booleans/strings carry no default so they stay
|
|
41
62
|
# nil and drop from the serialized hash unless set.
|
|
@@ -48,8 +69,9 @@ module Pubid
|
|
|
48
69
|
# "long" (full type-word name). Defaults to "short" so it drops from the
|
|
49
70
|
# canonical hash for the indexed primary form.
|
|
50
71
|
attribute :form, :string, default: "short"
|
|
51
|
-
# Metrologia journal fields.
|
|
52
|
-
|
|
72
|
+
# Metrologia journal fields. `volume` is NOT stored — it is exactly the
|
|
73
|
+
# index key, so MetrologiaArticle derives it from `number` (the IANA
|
|
74
|
+
# `registry` / IETF `series` pattern) rather than serializing both.
|
|
53
75
|
attribute :issue, :string # may be alphanumeric ("1A")
|
|
54
76
|
attribute :article, :string
|
|
55
77
|
# SI Brochure fields.
|
|
@@ -69,6 +91,17 @@ module Pubid
|
|
|
69
91
|
attribute :annex, :string
|
|
70
92
|
attribute :part, :string
|
|
71
93
|
|
|
94
|
+
# Attributes `Builder` derives `number` from for the families that have no
|
|
95
|
+
# document number of their own. Excluding one of these has to clear
|
|
96
|
+
# `number` too, or a wildcarded identifier would keep a stale index key —
|
|
97
|
+
# the "reset the WHOLE cluster, not just the scalar" lesson CLAUDE.md
|
|
98
|
+
# records for CSA's year and IEEE's year/month/day. `:volume` is listed
|
|
99
|
+
# even though it is no longer an attribute: the base loop skips it, but
|
|
100
|
+
# `exclude(:volume)` must still clear the key it derives from.
|
|
101
|
+
NUMBER_SOURCE_ATTRIBUTES = %i[
|
|
102
|
+
volume edition variant mep_code report_code
|
|
103
|
+
].freeze
|
|
104
|
+
|
|
72
105
|
# Polymorphic type map for lutaml::Model key_value (de)serialization:
|
|
73
106
|
# maps each subclass's polymorphic_name to its class name so a stored hash
|
|
74
107
|
# rebuilds the correct identifier type via from_hash.
|
|
@@ -91,7 +124,6 @@ module Pubid
|
|
|
91
124
|
map "year", to: :year
|
|
92
125
|
map "language", to: :language
|
|
93
126
|
map "form", to: :form
|
|
94
|
-
map "volume", to: :volume
|
|
95
127
|
map "issue", to: :issue
|
|
96
128
|
map "article", to: :article
|
|
97
129
|
map "edition", to: :edition
|
|
@@ -117,6 +149,20 @@ module Pubid
|
|
|
117
149
|
group == "CGPM" ? "de la" : "du"
|
|
118
150
|
end
|
|
119
151
|
|
|
152
|
+
# Resolve a historic committee name to the name the index keys.
|
|
153
|
+
def self.normalize_group(token)
|
|
154
|
+
name = token.to_s
|
|
155
|
+
GROUP_ALIASES.fetch(name, name)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Resolve a two-letter language code to the one-letter code BIPM prints.
|
|
159
|
+
def self.normalize_language(token)
|
|
160
|
+
return nil if token.nil?
|
|
161
|
+
|
|
162
|
+
code = token.to_s
|
|
163
|
+
LANGUAGE_ALIASES.fetch(code, code)
|
|
164
|
+
end
|
|
165
|
+
|
|
120
166
|
def long?
|
|
121
167
|
form == "long"
|
|
122
168
|
end
|
|
@@ -130,6 +176,7 @@ module Pubid
|
|
|
130
176
|
def exclude(*args)
|
|
131
177
|
result = super
|
|
132
178
|
result.year = nil if args.include?(:year) || args.include?(:date)
|
|
179
|
+
result.number = nil if args.intersect?(NUMBER_SOURCE_ATTRIBUTES)
|
|
133
180
|
result
|
|
134
181
|
end
|
|
135
182
|
|
|
@@ -138,13 +185,93 @@ module Pubid
|
|
|
138
185
|
render(format: :human, **opts)
|
|
139
186
|
end
|
|
140
187
|
|
|
188
|
+
# --- MR string / slug -------------------------------------------------
|
|
189
|
+
#
|
|
190
|
+
# `to_slug` is what consumers use as an output FILENAME, so every BIPM
|
|
191
|
+
# identifier needs a non-empty, filename-safe, non-colliding MR. None of
|
|
192
|
+
# the base ::Pubid::Identifier hooks work here unchanged, because BIPM
|
|
193
|
+
# models each of them with its own flat attribute rather than the shared
|
|
194
|
+
# component the base expects. Each override below says which.
|
|
195
|
+
#
|
|
196
|
+
# The number segment and the family discriminator are supplied per leaf
|
|
197
|
+
# (`mr_number_with_part` / `mr_type`), because BIPM's six families share
|
|
198
|
+
# no numbering.
|
|
199
|
+
#
|
|
200
|
+
# Three deliberate collapses — MR is a canonical DOCUMENT slug, so
|
|
201
|
+
# alternate print spellings of one document share it (the URN already
|
|
202
|
+
# collapses the first two): `form` (short vs long committee spelling) and
|
|
203
|
+
# the MEP/Guide `appendix`/`annex`/`part` full-content tail are omitted,
|
|
204
|
+
# while `language` is kept because the E and F records are distinct
|
|
205
|
+
# documents upstream.
|
|
206
|
+
|
|
207
|
+
# BIPM keeps its publisher in the PUBLISHER constant rather than the
|
|
208
|
+
# inherited `publisher` attribute (which would fail type validation), so
|
|
209
|
+
# the base hook — `publisher&.to_s` — is nil. The JIS/IANA shape.
|
|
210
|
+
def mr_publisher
|
|
211
|
+
PUBLISHER.downcase
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# BIPM stores the publication year in its own :integer attribute rather
|
|
215
|
+
# than a Components::Date, so the base hook reads an unset `date`.
|
|
216
|
+
def mr_year
|
|
217
|
+
year&.to_s
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# BIPM's `edition` is a plain :string ("9e"), not a Components::Edition,
|
|
221
|
+
# so the base hook's `edition.number` raises NoMethodError. SiBrochure
|
|
222
|
+
# folds the edition into its own number segment instead.
|
|
223
|
+
def mr_edition
|
|
224
|
+
nil
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# BIPM has a single `language` string, not the base's `languages`
|
|
228
|
+
# collection.
|
|
229
|
+
def mr_languages
|
|
230
|
+
language&.to_s&.downcase
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# BIPM uses its own `type_code` attribute rather than a typed_stage, so
|
|
234
|
+
# the base hook is always nil; the leaves supply the discriminator.
|
|
235
|
+
def mr_type
|
|
236
|
+
nil
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Join the parts of a number segment into one filename-safe token.
|
|
240
|
+
#
|
|
241
|
+
# The sanitisation is by CHARSET, not an enumerated escape list, so a
|
|
242
|
+
# field added later cannot leak an unsafe character: everything outside
|
|
243
|
+
# [a-z0-9] collapses to `-`. BIPM needs at least three of those today —
|
|
244
|
+
# a `/` (the MEP report code "BIPM-2019/05"), a space (the SI Brochure
|
|
245
|
+
# variant "Appendix 3") and a `.` (the brochure version "v3.01"). The
|
|
246
|
+
# dot matters beyond filename safety: Renderers::MrString joins SEGMENTS
|
|
247
|
+
# with ".", so a dot inside one would break the documented segment
|
|
248
|
+
# structure.
|
|
249
|
+
#
|
|
250
|
+
# Caveat: `-` is both the intra-segment join and a substitute, so two
|
|
251
|
+
# different field splits could in principle produce one slug. That
|
|
252
|
+
# cannot happen with today's grammar — none of `group`, `guide_kind`,
|
|
253
|
+
# `mep_code`, `issue` or `article` admits a `-`, and `number`'s own
|
|
254
|
+
# internal `-` ("10-1") is unambiguous because the `group` before it
|
|
255
|
+
# cannot contain one. A future hyphen-bearing free-text field would
|
|
256
|
+
# need a different join.
|
|
257
|
+
def mr_slug(*parts)
|
|
258
|
+
slug = parts.compact.map(&:to_s).reject(&:empty?).join("-").downcase
|
|
259
|
+
slug = slug.gsub(/[^a-z0-9]+/, "-").gsub(/\A-+|-+\z/, "")
|
|
260
|
+
slug unless slug.empty?
|
|
261
|
+
end
|
|
262
|
+
|
|
141
263
|
# Parse a BIPM identifier string into an identifier object.
|
|
142
264
|
# @param identifier [String] the BIPM identifier string
|
|
143
265
|
# @return [Identifier] the appropriate identifier object
|
|
144
|
-
# @raise [
|
|
266
|
+
# @raise [Pubid::Errors::ParseError] if parsing fails
|
|
145
267
|
def self.parse(identifier)
|
|
268
|
+
unless identifier.is_a?(String)
|
|
269
|
+
raise Pubid::Errors::InvalidInputError,
|
|
270
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
271
|
+
end
|
|
272
|
+
|
|
146
273
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
147
|
-
raise
|
|
274
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
148
275
|
end
|
|
149
276
|
|
|
150
277
|
# Normalize legacy/docnumber-style spellings before parsing
|
|
@@ -152,8 +279,6 @@ module Pubid
|
|
|
152
279
|
normalized = Core::UpdateCodes.apply(identifier, :bipm)
|
|
153
280
|
parsed = Parser.parse(normalized)
|
|
154
281
|
Builder.build(parsed)
|
|
155
|
-
rescue Parslet::ParseFailed => e
|
|
156
|
-
raise "Failed to parse BIPM identifier '#{identifier}': #{e.message}"
|
|
157
282
|
end
|
|
158
283
|
end
|
|
159
284
|
end
|
|
@@ -18,6 +18,18 @@ module Pubid
|
|
|
18
18
|
{ key: :committee_document, web: :committee_document,
|
|
19
19
|
title: "Committee Document", short: "committee-document" }
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
# MR: `bipm.<type>.<group>-<number>.<year>[.<lang>]`. The type code
|
|
23
|
+
# discriminates REC/RES/DECN/ACT/DECL; the bare CIPM MRA form has none.
|
|
24
|
+
def mr_type
|
|
25
|
+
type_code&.downcase
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The group has to be in the number segment or `CCTF REC 2` and
|
|
29
|
+
# `CCEM REC 2` would share a slug.
|
|
30
|
+
def mr_number_with_part
|
|
31
|
+
mr_slug(group, number)
|
|
32
|
+
end
|
|
21
33
|
end
|
|
22
34
|
end
|
|
23
35
|
end
|
|
@@ -18,6 +18,17 @@ module Pubid
|
|
|
18
18
|
def self.type
|
|
19
19
|
{ key: :guide, web: :guide, title: "Guide", short: "guide" }
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
# MR: `bipm.guide.<group>-<kind>-<number>`. Both the committee and the
|
|
23
|
+
# kind are needed — the trailing sequence restarts per committee, so
|
|
24
|
+
# `CCL-GD-MeP-1` and `CCEM-GD-RSI-1` both carry number "1".
|
|
25
|
+
def mr_type
|
|
26
|
+
"guide"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def mr_number_with_part
|
|
30
|
+
mr_slug(group, guide_kind, number)
|
|
31
|
+
end
|
|
21
32
|
end
|
|
22
33
|
end
|
|
23
34
|
end
|
|
@@ -35,6 +35,18 @@ module Pubid
|
|
|
35
35
|
def ordinal_en
|
|
36
36
|
"#{number}#{self.class.ordinal_suffix(number)}"
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
# MR: `bipm.meeting.<group>-<number>.<year>`. The English and French
|
|
40
|
+
# spellings of one meeting collapse onto the same slug on purpose.
|
|
41
|
+
def mr_type
|
|
42
|
+
"meeting"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The group has to be in the number segment or the 17th CGPM and the
|
|
46
|
+
# 17th CIPM meeting would share a slug.
|
|
47
|
+
def mr_number_with_part
|
|
48
|
+
mr_slug(group, number)
|
|
49
|
+
end
|
|
38
50
|
end
|
|
39
51
|
end
|
|
40
52
|
end
|
|
@@ -15,6 +15,18 @@ module Pubid
|
|
|
15
15
|
def self.type
|
|
16
16
|
{ key: :mep, web: :mep, title: "Mise en pratique", short: "mep" }
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
# MR: `bipm.mep.<code>`. Exactly one of `mep_code` / `report_code` is
|
|
20
|
+
# set; the report code carries a `/` that `mr_slug` sanitises away. The
|
|
21
|
+
# full-content "Appendix 2 Part x" tail is the same document, so it
|
|
22
|
+
# stays out of the slug.
|
|
23
|
+
def mr_type
|
|
24
|
+
"mep"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def mr_number_with_part
|
|
28
|
+
mr_slug(mep_code || report_code)
|
|
29
|
+
end
|
|
18
30
|
end
|
|
19
31
|
end
|
|
20
32
|
end
|
|
@@ -18,6 +18,30 @@ module Pubid
|
|
|
18
18
|
{ key: :metrologia_article, web: :metrologia_article,
|
|
19
19
|
title: "Metrologia Article", short: "metrologia-article" }
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
# MR: `bipm.metrologia[.<volume>[-<issue>[-<article>]]]`.
|
|
23
|
+
# The volume IS the index key, so it is derived from `number` instead
|
|
24
|
+
# of being stored beside it — storing both would duplicate the same
|
|
25
|
+
# value in every one of the 6,204 published article rows. Kept as an
|
|
26
|
+
# Integer because that is the public type consumers already read
|
|
27
|
+
# (`Relaton::Bipm::Bibliography#id_hash` calls `pubid.volume`).
|
|
28
|
+
#
|
|
29
|
+
# Safe as a plain method only because `volume` is no longer a lutaml
|
|
30
|
+
# attribute anywhere in the hierarchy — a method that shadows a
|
|
31
|
+
# generated accessor corrupts attribute resolution (CLAUDE.md).
|
|
32
|
+
def volume
|
|
33
|
+
number&.to_i
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def mr_type
|
|
37
|
+
"metrologia"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# `number` is only the volume (it is the CLUSTERING relaton-index key),
|
|
41
|
+
# so per-article distinctness has to come from here: the full triple.
|
|
42
|
+
def mr_number_with_part
|
|
43
|
+
mr_slug(volume, issue, article)
|
|
44
|
+
end
|
|
21
45
|
end
|
|
22
46
|
end
|
|
23
47
|
end
|
|
@@ -14,6 +14,19 @@ module Pubid
|
|
|
14
14
|
{ key: :si_brochure, web: :si_brochure,
|
|
15
15
|
title: "SI Brochure", short: "si-brochure" }
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
# MR: `bipm.si-brochure.<edition>-<version>[.<lang>]` for the brochure
|
|
19
|
+
# itself, `bipm.si-brochure.<variant>` for a derived product. Exactly
|
|
20
|
+
# one of `variant` / `edition` is set (the grammar guarantees it).
|
|
21
|
+
def mr_type
|
|
22
|
+
"si-brochure"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The edition is folded in here rather than emitted through
|
|
26
|
+
# `mr_edition`, whose base implementation expects a Components::Edition.
|
|
27
|
+
def mr_number_with_part
|
|
28
|
+
variant ? mr_slug(variant) : mr_slug(edition, version)
|
|
29
|
+
end
|
|
17
30
|
end
|
|
18
31
|
end
|
|
19
32
|
end
|
data/lib/pubid/bipm/parser.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Pubid
|
|
|
11
11
|
#
|
|
12
12
|
# Group and type-word alternations are built from the shared vocabularies on
|
|
13
13
|
# {Identifier} (sorted longest-first so e.g. "CCTF" is tried before "CCT").
|
|
14
|
-
class Parser <
|
|
14
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
15
15
|
# --- primitives ---
|
|
16
16
|
rule(:space) { str(" ") }
|
|
17
17
|
rule(:digits) { match["0-9"].repeat(1) }
|
|
@@ -21,7 +21,11 @@ module Pubid
|
|
|
21
21
|
(digits >> (str("-") >> digits).repeat).as(:number)
|
|
22
22
|
end
|
|
23
23
|
rule(:year) { match["0-9"].repeat(4, 4).as(:year) }
|
|
24
|
-
|
|
24
|
+
# "E"/"F" as BIPM prints them, plus the two-letter codes consumer
|
|
25
|
+
# references use (longest first, so "EN" is never read as a bare "E").
|
|
26
|
+
rule(:lang) do
|
|
27
|
+
(str("EN") | str("FR") | match["EF"]).as(:language)
|
|
28
|
+
end
|
|
25
29
|
# "(YYYY)" or "(YYYY, E)"
|
|
26
30
|
rule(:year_paren) do
|
|
27
31
|
str("(") >> year >> (str(", ") >> lang).maybe >> str(")")
|
|
@@ -34,7 +38,7 @@ module Pubid
|
|
|
34
38
|
tokens.sort_by { |t| -t.length }.map { |t| str(t) }.reduce(:|)
|
|
35
39
|
end
|
|
36
40
|
|
|
37
|
-
rule(:group) { alternation(Identifier::
|
|
41
|
+
rule(:group) { alternation(Identifier::PARSEABLE_GROUPS).as(:group) }
|
|
38
42
|
|
|
39
43
|
rule(:type_abbrev) do
|
|
40
44
|
alternation(Identifier::TYPE_CODES).as(:type_word)
|
|
@@ -49,6 +53,9 @@ module Pubid
|
|
|
49
53
|
end
|
|
50
54
|
rule(:connective) { str("de la") | str("du") }
|
|
51
55
|
rule(:ordinal) { str("st") | str("nd") | str("rd") | str("th") }
|
|
56
|
+
# The word naming a meeting in French. BIPM prints it lowercase; a
|
|
57
|
+
# consumer reference capitalizes it, as relaton's `Id::TYPES` does.
|
|
58
|
+
rule(:meeting_word_fr) { str("Réunion") | str("réunion") }
|
|
52
59
|
|
|
53
60
|
# --- committee documents ---
|
|
54
61
|
# The trailing "(YYYY)" date is optional (`.maybe`) so a partial reference
|
|
@@ -68,6 +75,17 @@ module Pubid
|
|
|
68
75
|
connective >> space >> group >> (space >> year_paren_nolang).maybe)
|
|
69
76
|
.as(:committee_long_fr)
|
|
70
77
|
end
|
|
78
|
+
# Loose consumer form: a French type name in the English (group-leading)
|
|
79
|
+
# word order, e.g. "CIPM Décision 101-1 (2012)". BIPM never prints this,
|
|
80
|
+
# so it renders back as the canonical "Décision 101-1 du CIPM (2012)".
|
|
81
|
+
# Tried after `committee_long_en`, which is what keeps the words both
|
|
82
|
+
# languages share ("Action", "Statement") English.
|
|
83
|
+
rule(:committee_group_fr) do
|
|
84
|
+
(group >> space >> type_name_fr >>
|
|
85
|
+
(space >> number).maybe >> (space >> year_paren_nolang).maybe)
|
|
86
|
+
.as(:committee_long_fr)
|
|
87
|
+
end
|
|
88
|
+
|
|
71
89
|
# Bare MRA-interpretation form: a group directly followed by a document
|
|
72
90
|
# number with no type word (e.g. "CIPM 2005-06"). Tried last, so typed
|
|
73
91
|
# committee documents and meetings always win; only fires when a digit
|
|
@@ -78,13 +96,26 @@ module Pubid
|
|
|
78
96
|
end
|
|
79
97
|
|
|
80
98
|
# --- meetings ---
|
|
99
|
+
# Canonical: "<group> <n><ordinal> Meeting [(YYYY)]". The second branch is
|
|
100
|
+
# the loose consumer word order "<group> Meeting <n>", which relaton's
|
|
101
|
+
# bespoke grammar accepts; both build the same tree, so the loose form
|
|
102
|
+
# renders back in the canonical spelling.
|
|
81
103
|
rule(:meeting_en) do
|
|
82
|
-
(group >> space >> number >> ordinal >> space >>
|
|
83
|
-
|
|
84
|
-
|
|
104
|
+
((group >> space >> number >> ordinal >> space >> str("Meeting") >>
|
|
105
|
+
(space >> year_paren).maybe) |
|
|
106
|
+
(group >> space >> str("Meeting") >> space >> number >>
|
|
107
|
+
(space >> year_paren).maybe)).as(:meeting_en)
|
|
108
|
+
end
|
|
109
|
+
# Canonical: "<group> <n><sup>e</sup> réunion [(YYYY)]". The second and
|
|
110
|
+
# third branches are the loose consumer spellings — the plain "e" ordinal
|
|
111
|
+
# and the "<group> Réunion <n>" word order.
|
|
85
112
|
rule(:meeting_fr) do
|
|
86
|
-
(group >> space >> number >> str("<sup>e</sup>") >> space >>
|
|
87
|
-
str("réunion") >> (space >> year_paren).maybe)
|
|
113
|
+
((group >> space >> number >> str("<sup>e</sup>") >> space >>
|
|
114
|
+
str("réunion") >> (space >> year_paren).maybe) |
|
|
115
|
+
(group >> space >> number >> str("e") >> space >> meeting_word_fr >>
|
|
116
|
+
(space >> year_paren).maybe) |
|
|
117
|
+
(group >> space >> meeting_word_fr >> space >> number >>
|
|
118
|
+
(space >> year_paren).maybe)).as(:meeting_fr)
|
|
88
119
|
end
|
|
89
120
|
|
|
90
121
|
# --- Metrologia journal ---
|
|
@@ -99,8 +130,12 @@ module Pubid
|
|
|
99
130
|
rule(:edition) { (digits >> str("e")).as(:edition) }
|
|
100
131
|
rule(:version) { (str("v") >> match["0-9."].repeat(1)).as(:version) }
|
|
101
132
|
rule(:years) { (digits >> (str("/") >> digits).maybe).as(:years) }
|
|
133
|
+
# The "BIPM " prefix is optional, as it is on the variant and section
|
|
134
|
+
# rules: `si-brochure.yaml` stores the docnumber WITHOUT it, and
|
|
135
|
+
# `Relaton::Bipm::Bibliography.search` strips a leading "BIPM " before it
|
|
136
|
+
# ever reaches pubid. Either spelling renders back with the prefix.
|
|
102
137
|
rule(:si_brochure) do
|
|
103
|
-
(str("BIPM SI Brochure") >> space >>
|
|
138
|
+
((str("BIPM SI Brochure") | str("SI Brochure")) >> space >>
|
|
104
139
|
(str("sur le SI") >> space).maybe >>
|
|
105
140
|
edition >> space >> version >> space >>
|
|
106
141
|
str("(") >> years >> str(", ") >> lang >> str(")")).as(:si_brochure)
|
|
@@ -120,6 +155,24 @@ module Pubid
|
|
|
120
155
|
brochure_variant).as(:si_brochure_variant)
|
|
121
156
|
end
|
|
122
157
|
|
|
158
|
+
# Bare and sectioned SI Brochure references: "SI Brochure",
|
|
159
|
+
# "SI Brochure Part 1". Neither names an edition, so both are partial
|
|
160
|
+
# references whose `number` stays nil and which wildcard every edition —
|
|
161
|
+
# the same reading a date-less "CCTF REC 2" gets. "Part N" points at a
|
|
162
|
+
# section INSIDE the brochure, not a separate record, so it rides in the
|
|
163
|
+
# shared `part` attribute and stays out of the index key, exactly as the
|
|
164
|
+
# MEP/guide "Part N.M" tail does. Listed after the edition and variant
|
|
165
|
+
# rules for readability, not for correctness: Parslet threads
|
|
166
|
+
# `consume_all` down through an alternation, so an alternative that
|
|
167
|
+
# matches only a PREFIX ("SI Brochure" of "SI Brochure Concise") counts
|
|
168
|
+
# as a failure and the next one is tried whatever the order. Order only
|
|
169
|
+
# decides between two alternatives that BOTH consume the whole input.
|
|
170
|
+
rule(:si_brochure_section) do
|
|
171
|
+
((str("BIPM SI Brochure") | str("SI Brochure")) >>
|
|
172
|
+
(space >> str("Part") >> space >> digits.as(:part)).maybe)
|
|
173
|
+
.as(:si_brochure_section)
|
|
174
|
+
end
|
|
175
|
+
|
|
123
176
|
# Shared "Appendix N [Annex N] Part N[.M]" tail carried by the full
|
|
124
177
|
# docidentifier content of MEPs and CC guides (the "Appendix 2 Part 1.1"
|
|
125
178
|
# or "Appendix 2 Annex 2 Part 1" suffix on "BIPM SI MEP …" etc.).
|
|
@@ -166,12 +219,12 @@ module Pubid
|
|
|
166
219
|
# a digit → meeting; a type word → committee.
|
|
167
220
|
rule(:group_leading) do
|
|
168
221
|
meeting_en | meeting_fr | committee_short | committee_long_en |
|
|
169
|
-
committee_bare
|
|
222
|
+
committee_group_fr | committee_bare
|
|
170
223
|
end
|
|
171
224
|
|
|
172
225
|
rule(:identifier) do
|
|
173
|
-
metrologia | si_brochure | si_brochure_variant |
|
|
174
|
-
committee_long_fr | group_leading
|
|
226
|
+
metrologia | si_brochure | si_brochure_variant | si_brochure_section |
|
|
227
|
+
mep | guide | committee_long_fr | group_leading
|
|
175
228
|
end
|
|
176
229
|
|
|
177
230
|
root(:identifier)
|
data/lib/pubid/bipm/renderer.rb
CHANGED
|
@@ -75,6 +75,9 @@ module Pubid
|
|
|
75
75
|
# Appendix / derived-product form indexed by relaton, keyed on the full
|
|
76
76
|
# "BIPM SI Brochure …" primary docidentifier content.
|
|
77
77
|
return "BIPM SI Brochure #{id.variant}" if id.variant
|
|
78
|
+
# Bare or sectioned reference: no edition means no version and no year
|
|
79
|
+
# to print either — just the brochure, optionally down to one part.
|
|
80
|
+
return "BIPM SI Brochure#{part_segment(id)}" unless id.edition
|
|
78
81
|
|
|
79
82
|
phrase = id.language == "F" ? "sur le SI " : ""
|
|
80
83
|
lang = id.language ? ", #{id.language}" : ""
|
|
@@ -82,6 +85,11 @@ module Pubid
|
|
|
82
85
|
"(#{id.years}#{lang})"
|
|
83
86
|
end
|
|
84
87
|
|
|
88
|
+
# Optional " Part <n>" segment of an SI Brochure section reference.
|
|
89
|
+
def part_segment(id)
|
|
90
|
+
id.part ? " Part #{id.part}" : ""
|
|
91
|
+
end
|
|
92
|
+
|
|
85
93
|
# MEP: short docnumber ("SI MEP <code>" / "Rapport BIPM-YYYY/NN"), or the
|
|
86
94
|
# full "BIPM … Appendix N [Annex N] Part N.M" content the crawler keys on.
|
|
87
95
|
def render_mep(id)
|